Size: 13119
Comment:
|
Size: 13177
Comment:
|
Deletions are marked like this. | Additions are marked like this. |
Line 4: | Line 4: |
@Tina: So wie ich das verstehe, hat das wirklich nur 3 Argumente, du könntest ebensogut ./GrepMain --input-file=<filename> xyz schreiben. Und an der Stelle, wo du argv[1] = const_cast<char*>("--input-file=???") brauchst, willst du ja den Dateinamen parsen - d.h. an der Stelle ist in _inputFileName eben noch nichts gespeichert. Das wird ja grade erst durch das parsen gemacht. An der Stelle im Test musst Du also erst von Hand ein Testfile anlegen, z.B. mit |
@Tina: So wie ich das verstehe, hat das wirklich nur 3 Argumente, du könntest ebensogut ./GrepMain --input-file=<filename> xyz schreiben. Und an der Stelle, wo du argv[1] = const_cast<char*>("--input-file=???") brauchst, willst du ja den Dateinamen parsen - d.h. an der Stelle ist in _inputFileName eben noch nichts gespeichert. Das wird ja grade erst durch das parsen gemacht. An der Stelle im Test musst Du also erst von Hand ein Testfile anlegen, z.B. mit |
Line 14: | Line 13: |
''' Fabian 13Jan10 17:08''' | Das kannst du dann als "--input-file=testfile.txt" parsen. ''' Fabian 13Jan10 17:08''' |
Fragen und Kommentare zur 7. Vorlesung / zum 7. Übungsblatt
Problem hat sich erledigt - fclose(outputFile) muss an passender Stelle eingebunden werden!
@Tina: So wie ich das verstehe, hat das wirklich nur 3 Argumente, du könntest ebensogut ./GrepMain --input-file=<filename> xyz schreiben. Und an der Stelle, wo du argv[1] = const_cast<char*>("--input-file=???") brauchst, willst du ja den Dateinamen parsen - d.h. an der Stelle ist in _inputFileName eben noch nichts gespeichert. Das wird ja grade erst durch das parsen gemacht. An der Stelle im Test musst Du also erst von Hand ein Testfile anlegen, z.B. mit
FILE* testInputFile = NULL; testInputFile = fopen("testfile.txt", "w"); fprintf("Testzeile 1\n"); (...) fclose(testInputFile);
Das kannst du dann als "--input-file=testfile.txt" parsen. Fabian 13Jan10 17:08
Ich habe noch eine Frage, die ganz unten schon mal gestellt wurde, aber ich habe die Antwort nicht ganz verstanden: wenn ich bei der parse-Funktion z.B. (nur) die Option --input-file testen möchte, muss
argv[1] = const_cast<char*>("--input-file= ???") sein, wobei die ??? für den Optionsparameter <filename> stehen, den wir ja aber in _inputFileName gespeichert haben, oder? Wie geb ich das dann hier an?
Und hat der Funktionsaufruf ./GrepMain --input-file <filename> xyz dann nur 3 Argumente, und nicht 4, obwohl Option und <filename> durch Komme getrennt wurden? Tina 13Jan10 15:58 Uhr
Ich verzweifle grad: Die Datei testoutout existiert bei mir mit dem Inhalt:
This is line 1. This is line 3 and the line is too long because it has too many characters: This
Jetzt versuche ich, diesen Inhalt zu testen, und zwar in der GrepTest.cpp mit folgendem Code:
FILE* outFile = NULL; outFile = fopen("testoutput", "r"); if (outFile != NULL) { char* line = new char[MAX_LINE_LENGTH + 1]; fgets(line, MAX_LINE_LENGTH + 1, outFile); printf("Line: %s\n", line); ASSERT_EQ('1', line[13]); fgets(line, MAX_LINE_LENGTH + 1, outFile); }
Ich bekomme folgendes: (Wobei die ? eigentlich ganz komische Zeichen sind, aber die mag das Wiki nicht..)
Line: ??,@??,@? GrepTest.cpp:334: Failure Value of: line[13] Actual: '?' (4, 0x4) Expected: '1' Which is: '1' (49, 0x31)
Zum Testen hab ich noch eine Test.cpp ohne jegliches googleTest geschrieben mit folgendem Inhalt:
#include <stdio.h> int MAX_LINE_LENGTH = 80; int main() { FILE* outFile = NULL; outFile = fopen("testoutput", "r"); if (outFile != NULL) { char* line = new char[MAX_LINE_LENGTH + 1]; fgets(line, MAX_LINE_LENGTH + 1, outFile); printf("Line: %s\n", line); fclose(outFile); } }
Und diese Datei gibt mir, kompiliert, wunderbar und friedlich meine erste Zeile aus. Keine Fragezeichen. Warum??? Fabian 13Jun10 15:34
Sollen wir, wenn wir für --output-file<filename> eine Datei zum reinschreiben mit fopen öffnen, als Argument 'a' nehmen, damit der Text angehängt wird, oder 'w' das der Dateiinhalt falls vorhanden gelöscht bzw. überschrieben wird? Tina 13Jun10 14:57
Ich kann den aktuellen Makefile nicht kompilieren. Bei den letzen Uebungen habe immer -lgtest_main -static -pthread hinzugefügt und hat es geklappt. Dieses mal wohl nicht.
make build g++ -Wall -o GrepTest GrepTest.o Grep.o -lgtest -static -pthread /usr/lib/gcc/x86_64-linux-gnu/4.4.3/../../../../lib/crt1.o: In function `_start': (.text+0x20): undefined reference to `main' collect2: ld returned 1 exit status make: *** [GrepTest] Fehler 1
Dario 13Jun10 14:40
@Dario: Sei meinen am Anfang in der Zeile CXX = g++ -Wall? Das -W steht einfach für warnings und -Wall heißt, dass der Compiler besonders pingelig sein und jede Warnung ausgeben soll. Bei früheren g++ Versionen hat das einen großen Unterschied gemacht, inzwischen ist aber die default Einstellung schon fast so pingelig wie -Wall. Was auch richtig ist, denn 99% aller Warnungen sind ein Hinweis auf Programmierfehler, gerade bei Programmieranfängern. Hannah 13Jun10 14:07
Was heißt die -Wall am Ende der Make file datei? Dario 13Jun10 13:14
@MartinW bez. Testen von findMatches und --input-file und --output-file. Erzeugen Sie in Ihrem Test eine einfache Eingabedatei, setzen Sie _inputFileName und _outputFileName, rufen Sie findMatches auf, lesen Sie die Ausgabedatei in einen String (mit fgets oder fread) und prüfen Sie dann ob der Inhalt dieser Datei der ist, der er sein sollte. Hannah 13Jun10 00:53
@fry: Danke für die Kommentare, stimmt beides genau. Wobei vielleicht noch ergänzen wäre, dass man fprintf auch genau verwenden kann wie printf, also mit Platzhalte wie %s oder %d in dem string und dann die entsprechenden Variablen als weitere Argumente. Hannah 13Jun10 00:47
@Martin: Wegen der MAX_LINE_LENGTH, ja genau, wenn Sie die auch in der GrepTest.cpp brauchen, müssen Sie sie in der Grep.h deklarieren. Das hatten wir ja auch glaube ich schon mal mit MAX_LIST_SIZE in der ListOfIntegers.h. Hannah 13Jun10 00:46
@Martin + Fabian + Alle: Ja, das muss natürlich -- heißen, habe das gerade im SVN korrigiert, danke für den Hinweis. Hannah 13Jun10 00:44
Gibt es eine Möglichkeit im Test auf die Konstante MAXIMUM_LINE_LENGTH zuzugreifen? Zum Beispiel in dem die Definition nicht in der Grep.cpp sondern bei den Membervariabeln in der Grep.h festgelegt wird? Ich muss die Konstante lesen können, um den Test für das Überschreiten der maximalen Zeilenlänge zu schreiben. MartinS 12Jun10 21:36
Da hat sich wohl jemand verschrieben. Auf dem Aufgabenblatt steht's mit "--" und ich tippe mal schwer drauf, dass das stimmt. Fabian 12Jun10 18:28
Wieso muss eigentlich -regular-expression-match nur mit einem - aufgerufen werden, während alle anderen mit zwei -- aufgerufen werden (laut usage info). Und wie sag ich das dann getopt? Martin 12Jun10 18:24
PS: Wenn man das Ding mit ShortOps aufrufen können will müssen die, die ein Argument brauchen ein hinter sich":". Beispiel "i" und "o" brauchen ein Argument:
static struct option options[] = { {"input-file" , 1, NULL, 'i'}, {"case-insensitive-match" , 0, NULL, 'c'}, {"output-file" , 1, NULL, 'o'}, {"regular-expression-match", 0, NULL, 'r'}, {NULL , 0, NULL, 0 } }; optind = 1; int c = 0; while ((c = getopt_long(argc, argv, "i:co:r", options, NULL)) != -1)
fry (UTC+2:00) 1276356859 UTS
@Martin das ganze funktioniert mit
fprintf(yourfile, "The string to be added")
Beachte dabei dass wenn die Datei bereits vorhanden ist sie mit den neuen Werten überschrieben wird. Der Code drumrum hat da Ähnlichkeiten mit dem von FILE* inputFile... und ich glaub wenn der Pfad nicht angegeben ist wird standardmäßig der aktuelle Pfad des Programms benutzt. fry (UTC+2:00) 1276355745 UTS
Ich habe noch eine Frage: Ich weiß leider noch nicht so richtig, wie ich meinem Programm sagen soll, dass es, falls die -o=file.txt Option angegeben ist, keine Standard ausgabe macht, sondern in die Datei file.txt schreibt. Geht das irgendwie mit fwrite? MartinW 12Jun10 15:50
Wie sollen wir eigentlich die input und output Optionen testen? Und: Sollen wir die findMatches Methode testen? Im ersten Teil gibt es ja eine Abbruchbedingung, aber ich wüsste nicht, wie man die mit ASSERT_DEATH testen soll. MartinW 12Jun10 15:40
@Fabian: Sie haben völlig Recht, habe ich vergessen, 1/2 Punkt Abzug für mich Ich habe es jetzt im SVN korrigiert. Hannah 10Jun10 14:31
@Hannah: Noch eine Frage zu Ihrer Musterlösung zum letzten Blatt: Ist die Musterlösung const-korrekt? Meiner Meinung nach müsste hinter find noch ein const, da ja nichts an dem Objekt verändert wird. Fabian 10Jun10 14:18
@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 in der Tat von Hand zurücksetzen. Ich habe das jetzt auch in der vorlesungen/vorlesung-7/Grep.cpp geändert und kommentiert, einfach svn update machen. Hannah 10Jun10 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");
Läuft der Test dann durch? Hannah 10Jun10 10:39
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