Fragen und Kommentare zur 7. Vorlesung / zum 7. Übungsblatt
@Martin: Stimmt + super, dass Sie das rausgefunden haben, ein wirklicher gemeiner und schwer zu findender Bug, ich würde sagen das ist (mindestens) einen Bonuspunkt wert! Ich habe da beim Erklären nicht dran gedacht, weil man ja normalerweise die Kommandozeilen-Parameter nur einmal parsed. Aber bei mehreren Tests hintereinander halt öfter, und dann muss man optind von Hand zurücksetzen. Ich habe das jetzt auch in der vorlesungen/vorlesung-7/Grep.cpp geändert, einfach svn update machen. Hannah10Jun10 12:43
Habe den Fehler durch merkwürdige Fehlermeldungen von GTest gefunden. Ich hatte in GrepTest die drei Tests mit Optionen als den für das input file, output file und case insensitive match hintereinander. Zuerst war der Fehler beim output file test. Nachdem ich den mal auskommentiert hatte war er im case insensitive match test. Dann habe ich mal die Reihenfolge vertauscht. Der Fehler trat also immer in dem Test nach dem ersten Test mit Option auf. Dies ließ sich dann beheben indem ich die Variable "optind" vor der while Schleife auf 1 gesetzt habe. optind ist eine externe Variable von getopt die auf den Index des nächsten zu prozessierenden Eintrags im Feld argv zeigt. Diese wird vom System standardmäßig auf 1 gesetzt und läuft hoch, wenn die Optionen geparsed werden (siehe man 3 getopt). Wenn man jetzt den nächsten Test aufruft, steht diese Variable immer noch auf dem letzten Element des argv Zeigers. Das hießt c wird gleich auf -1 gesetzt und verlässt die Schleife und setzt auch _outputFileName nicht. Es ist also sinnvoll vor jedem Durchlauf der Parsingschleife optind auf 1 zu setzen. Eine Lösung wäre also:
optind = 1; while (true) { int c = getopt_long(argc, argv, "ioc", options, NULL); if (c == -1) break; switch (c) ...
Beim Aufruf machen "--output-file=out.txt" und "--output-file out.txt" keinen Unterschied. Sowohl im Test als auch beim Aufruf der GrepMain direkt. Es funktioniert beides. MartinS 10Jun10 11:21
In der Vorlesung wurde gesagt, dass die Parameterwerte mit einem = direkt an ihre Schalter angehaengt werden.
argv[0] = const_cast<char*>(""); argv[1] = const_cast<char*>("--output-file=out.txt"); argv[2] = const_cast<char*>("P");
Sollte dann richtig funktionieren. AxelLehmann 10Jun10 11:03
@Martin: Was passiert, wenn Sie in in Ihrem Test schreiben
int argc = 3; char* argv[3]; argv[0] = const_cast<char*>(""); argv[1] = const_cast<char*>("--output-file=out.txt"); argv[2] = const_cast<char*>("P"); Bin gerade dabei die parseCommandLineArguments Funktion mit den Optionen input-file und output-file zu testen. Hock' jetzt schon 'ne Weile dran und find' den Fehler nicht. Vielleicht hat jemand gerade mehr Gehirnschmalz, als ich. Hier das Codestück in der Grep.cpp (Ich hoffe, dass ist OK, wenn ich das hier rein Stelle, ist ja nicht wirklich viel mehr als das von der Vorlesung): {{{ // First parse the options. struct option options[] = { {"input-file" , 1, NULL, 'i'}, {"output-file" , 1, NULL, 'o'}, {"case-insensitive-match", 0, NULL, 'c'}, {NULL , 0, NULL, 0 } }; while (true) { int c = getopt_long(argc, argv, "ioc", options, NULL); if (c == -1) break; switch (c) { case 'i': _inputFileName = optarg; break; case 'c': _caseSensitiveMatch = false; break; case 'o': _outputFileName = optarg; break; default: printUsage(); exit(1); }
Mein Test:
Grep grep; int argc = 4; char* argv[4]; argv[0] = const_cast<char*>(""); argv[1] = const_cast<char*>("--output-file"); argv[2] = const_cast<char*>("out.txt"); argv[3] = const_cast<char*>("P"); grep.parseCommandLineArguments(argc, argv); ASSERT_EQ(0, grep._inputFileName[0]); ASSERT_EQ('P', grep._pattern[0]); ASSERT_EQ(0, grep._pattern[1]); ASSERT_EQ('o', grep._outputFileName[0]); ASSERT_EQ('u', grep._outputFileName[1]); ASSERT_EQ('t', grep._outputFileName[2]); ASSERT_EQ('.', grep._outputFileName[3]); ASSERT_EQ('t', grep._outputFileName[4]); ASSERT_EQ('x', grep._outputFileName[5]); ASSERT_EQ('t', grep._outputFileName[6]);
Fehlermeldung:
Value of: grep._outputFileName[0] Actual: '\0' (0, 0x0) Expected: 'o' Which is: 'o' (111, 0x6F)
Den Test für das input file hab' ich im Prinzip analog dazu gemacht. Der funktioniert. MartinS 10Jun10 10:34
@Simson: Indeed, da fehlt ein Punkt, danke für den Hinweis! Habe ihn jetzt gerade noch zugefügt und die neue Version committed. Machen Sie einfach svn update, dann bekommen Sie ihn auch Hannah 10Jun10 00:14
Sollte isMatch("This is just a line", "a..ne$") wirklich wahr zurückgeben? Fehlt da nicht ein . ? Simson 10Jun10 00:09