7577
Comment:
|
37124
|
Deletions are marked like this. | Additions are marked like this. |
Line 1: | Line 1: |
## page was renamed from ProgrammierenCplusplusSS2010/Blatt4Fragen == Fragen und Kommentare zur 4. Vorlesung / zum 4. Übungsblatt == Wie soll dieser String ausgewertet werden? "1 4,3 5" bzw. muss man den Fall auswerten, dass in einer Zahl ein Leerzeichen stehen kann? '''Manuel 13. Mai 15:43''' Soo, ich weiß, ich weiß aber leider haben wir immernoch keine OFF-TOPIC-Section und ich dachte das muss ich mal mitteilen: http://www.youtube.com/watch?v=FIT3WlIyy1Y&NR=1&feature=fvwp '''fry UTC+1 1273757790UTS''' Wie soll eigentlich genau mit einer Liste umgegangen werden, die Beispielsweiße so aussieht: ",,,5,7 ,3". Soll das Programm dann daraus : 0,0,0,5,7,3,-1 machen, oder die 0er weg lassen? '''David Z. 13. Mai 15:04''' @JonathanN Spontan würde ich dann sagen, dass du entweder die falsche Variable bearbeitest (unwahrscheinlich), oder dein Zähler irgendeinen Wert hat, den er nicht haben sollte. Probier doch mal: {{{ finallist[k] = -1; //Also warum dieser Befehl nicht ausgeführt wird? printf("%d %d",k,finallist[k]); }}} '''SebastianS 13Mai10 14:25''' @Sebastian, ja was in der Schleife steht wird sauber ausgeführt, nur diese Zeile nach der Schliefe iergendwie nicht. Also habe soeben noch mal was geprüft, er geht raus aus der Schleife, denn wenn ich einen printf befehl dahin setzte, der wird aus geführt, oder ist etwas an der Syntax des Befehls "faul"? '''JonathanN 13Mai10 14:12''' @Hannah: Ah, verstehe, danke :-) @JonathanN: Wird die Schleife ausgeführt? Also kommt er überhaupt zu dem Punkt? Wenn ja, sollte auch die Bedingung ausgeführt werden... Überprüf vlt nochmal deine Klammern :) '''SebastianS 13Mai10 13:22''' Kann mir jemand erklären warum beim folgenden Code der Letze Befehl nicht ausgeführ wird {{{ while (bedingung) |
== Fragen und Kommentare zur 7. Vorlesung / zum 7. Übungsblatt == Der Backslash muss vor das $, nicht vor das Pattern, nehme ich an. '''SebastianD 16Jun10 13:11''' Guter fund! ändert beim ausführen des Programs in der Shell leider nichts bei mir. {{{ echo ^testing$ | ./GrepMain ^^testing$$ }}} gibt nichts aus, dasselbe mit einem Backslash vor dem pattern. aber der selbe test funktioniert rund... '''JonathanB 16Jun 13:11 ''' Der Zugriff auf die Variable kann mit einem vorangestellten Backslash unterdrückt werden! --> {{{\$rdsdfsdf$}}} gibt {{{$rdsdfsdf$}}} '''Simson 16Jun10 13:04''' Ja, {{{echo $$}}} gibt mir auch {{{392}}} zurück und {{{echo $[irgendwas]}}} gibt mir nur eine leere Zeile zurück... '''Simson 16Jun10 12:55''' Ich habe nur begrenzte Linux-Kenntnisse, aber ich glaube das Problem mit $ ist das es ein special character für die Shell ist, u.a. kann man so auf sogennante Umgebungsvariablen des Betriebssystems zugreifen. Irgendwie ersetzt dann die Shell beim ausführen eines Befehls, wo $ drin ist, diese $ durch die dazugehörige Variable, oder sowas in der Richtung... ^^ Ding ist, wie die Umgebungsvariablen heissen, eingesetzt werden usw, hängt von der Konfiguration des Betriebssystems ab, d.h. es gibt ein fix der für jeden funktionieren würde ... ''' JonathanB 16Jun10 12:49''' Noch mehr Probleme mit {{{$}}}: nach {{{parseCommandLineArguments}}} mit {{{$rdsdfsdf$}}} als pattern bekomme ich bei {{{printf("%s\n", _pattern);}}} als Ausgabe {{{$}}} (Länge1) und sonst nichts. Auch bei pattern {{{rdsdfsdf$fdddddddddd}}} ist nach dem parsen nur noch {{{rdsdfsdf}}} übrig. '''Simson 16Jun10 12:23''' @Jens: meinst du stringLength aus der Grep.cpp ? wie gesagt die sagt 13, obwohls es nur 11 Zeichen sind. '''Jonathan 16June 11:40''' @Jonathan & Jens: das ist mir auch schon aufgefallen (Simson 15Jun10 13:45). Length & strlen ist dann die tatsächliche Länge (bei Jonathan also 13). '''Simson 16Jun 11:30''' @Jonathan: Was sagt denn strlen? '''Jens 16Jun 11:28''' @Regina: grub ist das Bootloader von deinem Linux, d.h. es ist was schief an deiner Installation/Bootsektor passiert, das ist schon ein größeres Problem... kannst mal versuche nach "grub rescue" zu googlen, da gibts es jede Menge. '''JonathanB 16June 11:17''' Ich bin gerade auf was merkwürdiges gekommen... wenn ich mir die Länge des Patterns {{{ ^^testing$$ }}} ausgeben lasse, gibt das Program 13 aus, sollte aber 11 sein, der char* ist ausgefüllt mit: {{{ ^^testing1309 }}} An der Prozedur zur Berechnung der Länge habe ich nichts geändert, es funzt auch für alle Arten von char* . Also den Befehl {{{ echo $$ }}} gibt tatsächlich 1390 aus ... erm was ist den da los? Umgebungsvariable in $$ ? wie kann ich dann den o.g. Pattern Grep übergeben? '''JonathanB 16June11:08''' HILFE!! Wenn ich versuche, den Laptop hochzufahren, bekomme ich die Fehlermeldung: {{{ error: unknown filesystem grub rescue > }}} Was ist das, und wie löse ich das problem?? '''Regina 16Jun10 11:20''' Das war es, ich hatte den Ordner aus dem Vorlesungsverzeichnis kopiert. Vielen Dank für deine Hilfe :) '''Norman 16Jun10 03:00''' Entweder versuchst du, den Ordner "vorlesungen" (das ist der, über den wir die Vorlesungsdateien bekommen können) zu committen (welcher offenbar schreibgeschützt ist - ist auch gut so), oder du hast einfach den gesamten Ordner in dein Unterverzeichnis kopiert und umbenannt (was man nicht tun sollte). Falls letzteres: .svn Unterordner (in uebungsblatt-7) löschen und das Verzeichnis neu adden. '''SebastianD 16Jun10 00:27''' @Jens: Also ich erhalte beim checkout folgenden Fehler: ''Übertragen schlug fehl (Details folgen): Der Server hat einen unerwarteten Rückgabewert (403 Forbidden) in Antwort auf die Anfrage CHECKOUT für »/teaching/cplusplus-ss2010/!svn/ver/3748/vorlesungen/vorlesung-7/Grep.cpp« zurückgeliefert'' '''Norman 15Jun10 00:22 ''' @Dennis: Wie Fabian schon sagt liegt es dann ziemlich sicher an einem fehlenden fclose. Schau mal in deiner findMatches() Methode ob du auch wirklich zu allen Files am Schluss ein fclose aufrufst. Schließlich arbeitet findMatches() in deinem Test auch auf der output.txt, du wirst da das fclose vergessen haben. Auch in deinem Test würde ich unten noch ein fclose(outputFile) machen. @Jan: Dumme Frage, aber hast du auch _regularExpressionMatch auf true gesetzt in deinem Test? '''Roman 15Jun10 23:55''' @Dennis: Das einzige, was mir im Moment noch einfällt, wäre, dass "output.txt" irgendwo zweimal hintereinander geöffnet wurde, aber vergessen wurde, es zu schließen(wahrscheinlich in findMatches). Die Dateien sollte man, wenn man sie nicht mehr braucht immer sofort schließen, oder man kann leicht Fehler machen. Bsp.: {{{ FILE* file; char line[200]; { FILE* f2 = fopen("out.txt", "w"); fprintf(f2,"Help\n"); // hier fehlt fclose(f2); } file = fopen("out.txt", "r"); fgets(line, 200, file); printf("%s\n", line);//falsche Ausgabe // aber nach Ende des Programms richtige Datei fclose(file); }}} '''Fabian 15Jun10 23:25''' @ Roman: ich habe for fgets noch ein fopen eingefügt so wie Fabian es gesagt hat. Das mit %c stimmt ich habe es jedoch nur mal testweise von %s auf %c gesetzt. ist mitlerweile wieder auf %s. ändert ja aber auch nichts daran dass fgets einfach nicht das den inhalt von output.txt in line kopiert. '''Dennis 15Jun10 23:09''' @Dennis: Dein fclose(outputFile) darf nicht vor fgets stehen, in fgets liest du ja noch aus outputFile. Und dein printf kann so auch nicht klappen, %c steht für einen _einzelnen_ char.'''Roman 15Jun10 22:39''' @Norman: Ich sehe kein Problem. Sie haben Schreib- und Leserechte auf den Ordner uebungsblatt-7. '''Jens 1537Jun10 22:''' @Hannah: Ich kann seit heute Mittag nichts comitten... Es ist mir "forbidden" (Error 403).... '''Norman 15Jun10 22:33''' @Fabian Ich öffne sie ja mit "w" weil ich zwei neue Dateien für den Test anlegen muss. Wie du gesagt hast hab ich nun noch vor fgets ein fopen eingefügt. Hier dann auch mit "r" da ich ja nur lesen will. Sollte also eigentlich richtig so sein. '''Dennis 15Jun10 22:31''' @Dennis: Ich habe eine ganz ähnliche Ausgabe erzeugen können, indem ich eine Datei mit "w" statt mit "r" geöffnet habe. Nur mit "w" nur aufrufen, wenn du die Datei komplett neu schreiben (und auch nur schreiben) willst ("a" um ans Ende der Datei zu schreiben), "r" wenn du nur ausliest. Vielleicht behebt das ja dein Problem '''Fabian 15Jun10 21:39''' Ich habe das Problem, dass Test fehlschlagen, welche jedoch per direktem Aufruf funktionieren. Bspw. der Aufruf {{{ ./GrepMain "^This" --input-file in.txt --regular-expression-match }}} mit dem Inhalt "This is Just A Line" funktioniert einwandfrei. Der Testfall {{{ ASSERT_TRUE(g.isMatch("This is Just A Line", "is..ust")); }}} hingegen, funktioniert nicht. '''Jan 15Jun10 21:31''' Ja stimmt aber ändert nichts. Ausgabe von line ist immer noch "Line: ��.@��.@" obwohl in output.txt die gefundene Zeile steht. '''Dennis 15Jun10 21:21''' @Dennis: Könnte es sein, dass du vor '''fgets''' vergessen hast, die Datei zu öffnen??? '''Fabian 15Jun10 21:01''' Ich möchte die Ausgabe in eine Datei testen. Mit dem folgenden Code wird die output.txt Datei auch erzeugt und enthält nach dem aufruf von {{{findMatches()}}} auch mit die richtige Ausgabe ("Das ist eine Zeile"). Jedoch schlägt der test fehl weil in {{{line}}} nur wirre sonderzeichen geschrieben wurden (sieht man wenn man {{{line}}} printed). habe ich dem befüllen von {{{line}}} einen fehler gemacht? {{{ // Test the findMatches method. TEST(GrepTest, findMatches) |
Line 30: | Line 114: |
ein paar berechnungen | Grep g; FILE* testInputFile = NULL; testInputFile = fopen("testfile.txt", "w"); fprintf(testInputFile, "Das ist eine Zeile\n"); fclose(testInputFile); g._inputFileName = "testfile.txt"; FILE* outputFile = NULL; outputFile = fopen("output.txt", "w"); fclose(outputFile); g._outputFileName = "output.txt"; g._pattern = "eine"; g.findMatches(); char* line = new char[30]; fgets(line, 30, outputFile); printf("Line: %c\n", line); ASSERT_EQ('D', line[0]); |
Line 32: | Line 131: |
finallist[k] = -1; //Also warum dieser Befehl nicht ausgeführt wird? }}} '''JonathanN 13Mai10 13:27''' @SebastianS: Ok, ich verstehe. Es ist so, Sie dürfen immer annehmen, dass Sie genau zwei Argumente bekommen. In den strings dieser Argumente dürfen allerdings Leerzeichen stehen. Von der Kommandozeile aus geht das zum Beispiel so: ''./ListProcessingMain "1,2,3, 5,6 , 7" "8,9,0, 10"''. Das erste Argument wäre dann ''1,2,3, 5,6 , 7'' und das zweite Argument wäre ''8,9,0, 10''. '''Hannah 13Mai10 13:05''' @Hannah: Nunja, ich verstehe Aufgabe 1 so, dass wir auch aus so etwas: ''1,2,3, 5,6,7 8,9,0, 10,11'' zwei Listen generieren sollen (''1,2,3,5,6,7'' und ''8,9,0,10,11''). Allerdings würde argv bei obiger Argumentenübergabe ja folgendes liefern: ''[1] => "1,2,3,", [2] => "5,6,7", [3] => "8,9,0", [4] => "10,11"'' Somit erhalten wir ja nicht zwei sondern vier Argumente. An sich kein Problem, nur ist jetzt die Frage, ob wir in main() solche Vorkommnisse überprüfen sollen und die Strings entsprechend "zusammenkleben" sollen, oder ob wir das ganze an die Funktion weiterreichen sollen, damit die das entsprechend verarbeitet. '''SebastianS 13Mai10 12:50''' @SebastianD: Ich würde erstmal gerne verstehen, wofür Sie diesen Rückgabewert brauchen. In meiner Lösung des Übungsblattes brauche ich den nicht. Genau wie die anderen Listen soll ja auch die Ergebnisliste mit einem ''-1'' aufhören, so dass man also immer herausfinden kann wo Sie aufhört. Listen, die Ihre eigene Größe kennen ohne erst einmal durchzulaufen, machen mir in einer späteren Vorlesung. '''Hannah 13Mai10 9:50''' @Jonathan: Ja, genau, man muss die ''.h'' Datei in der ''.cpp'' includen, das macht man aber auch eigentlich immer so, wir haben es bisher bloß noch nie gebraucht, jetzt brauchen wir es zum ersten Mal. Falls Sie sich fragen, ob es korrekt ist: es ist korrekt, in der ''.h'' Datei stehen ja die Deklarationen und in der ''.cpp'' Datei die Definitionen. Das ist genauso wie erst ''int x;'' zu schreiben und dann später im Programm ''x = 4;''. Zum zweiten Teil Ihrer Frage: Ja, die Funktion soll drei Argumente haben: die beiden Eingabelisten und die Ausgabeliste, alle als ''int*''. Wobei Sie darauf achten müssen die Ausgabeliste vor dem Aufruf als Feld zu deklarieren, genau wie wir das in der Vorlesung vor den Aufrufen von ''parseListOfIntegers'' gemacht haben. '''Hannah 13Mai10 9:48''' @SebastianS: Die ''parseListOfIntegers'' Funktion soll nur eine Liste bearbeiten. Ich verstehe das Problem, dass sich dann bei Aufgabe 1 stellen soll nicht, erklären Sie es doch bitte nochmal genauer bzw. an einem konkreten Beispiel. Zum zweiten Teil der Frage: Ja, die Konvention ist, dass eine Liste bei ''-1'' zu Ende ist, egal was danach noch kommt. Genauso wie in ''C / C++'' ein string zu Ende ist wenn ein null-character kommt, egal was danach noch kommt. Und genau, die leere Liste ist die, wo gleich als erstes Element die ''-1'' kommt. '''Hannah 13Mai10 9:44''' Spricht irgendetwas gegen eine Änderung des Rückgabetyps der ''parseListOfIntegers''-Funktion? Ich würde die sonst dahingehend ändern, dass ich zurückgebe, wie viele Elemente die Liste enthält. '''SebastianD 12Mai10 23:59''' ---- /!\ '''Edit conflict - other version:''' ---- Guten Abend, dann bring ich mal gleich auch meine Fragen hier rein. Also die Variable MAX_LIST_SIZE kann ich in der .cpp Datei ja nicht nutzen wenn ich die .h nicht include, dies ist ja aber grad, das was nicht passieren soll. Diesen Wert brauch ich ja aber um zuüberprüfen, dass mein i mir nicht zu weit wegläuft, oder? Dann zum AufgabenTeil 2? Soll hier die Funktion diesmal die neue Liste als Ausgabewert haben, oder nehme ich wieder eine Liste, dann als 3. Parameter auf? Da ja die 2 Listen ja schon in der Main aufgeteilt werden, und mir also so schon 2 Parameter liefert? '''JonathanN 12Mai10 22:23''' ---- /!\ '''Edit conflict - your version:''' ---- Guten Abend, dann bring ich mal gleich auch meine Fragen hier rein. ---- /!\ '''End of edit conflict''' ---- ---- /!\ '''Edit conflict - other version:''' ---- ---- /!\ '''Edit conflict - your version:''' ---- Also die Variable MAX_LIST_SIZE kann ich in der .cpp Datei ja nicht nutzen wenn ich die .h nicht include, dies ist ja aber grad, das was nicht passieren soll. Diesen Wert brauch ich ja aber um zuüberprüfen, dass mein i mir nicht zu weit wegläuft, oder? Dann zum AufgabenTeil 2? Soll hier die Funktion diesmal die neue Liste als Ausgabewert haben, oder nehme ich wieder eine Liste, dann als 3. Parameter auf? Da ja die 2 Listen ja schon in der Main aufgeteilt werden, und mir also so schon 2 Parameter liefert? '''JonathanN 12Mai10 22:23''' ---- /!\ '''End of edit conflict''' ---- Ist es zulässig, dass man die parseListOfIntegers Funktion derartig umbaut, dass sie als Argument alle Argumente des Programms entgegen nimmt, und diese selbst in zwei Listen aufteilt? Weil sonst sehe ich nicht, wie man Aufgabe 1 lösen soll, wo doch die Trennung schon in der ListProcessingMain durchgeführt wird? Weitere Frage: Dürfen wir beim Zusammenführen davon ausgehen, dass bei erreichen eines Elementes mit dem Wert -1 abgebrochen werden darf, da Ende der Liste? Eine Liste die mit -1 beginnt ist ja für uns eine "leere" Liste, oder? '''SebastianS 12Mai10 22:06''' [[http://www.gnu.org/software/make/manual/make.html#reference|Hier]] und [[http://www.gnu.org/software/autoconf/manual/make/Automatic-Variables.html|hier]]. Links sind in den Folien der heutigen Vorlesung entnommen. '''SebastianS 12Mai10 19:41''' Wo kann man denn den Link zu der Erklärung für den verwendeten Make Syntax finden? '''Daniel 12Mai10 18:43''' |
}}} '''Dennis 15Jun10 20:49''' Für mich ist das Warten auf eine nie kommende Eingabe gerade die Definition eines "Hängers", aber nun gut, dann vertrau ich auf die intelligente Eingabe des Users. Danke für die Antwort. '''Ben 15Jun10 20:28''' @Ben: ''fgets'' kann sich nicht aufhängen, es wartet dann auf das nächste newline. Unabhängig davon können sie Eingabe über standard input nicht automatisch testen und müssen Sie von daher auch nicht. Dasselbe mit Ausgabe nach standard output. Was Sie testen sollen ist Eingabe von einer Datei und Ausgabe in eine Datei. '''Hannah 15Jun10 19:16''' Hallo, wie kann man auf leeres stdin testen (also kein Testfall, sondern per if abfangen). fgets hängt sich bei mir nämlich immer auf, wenn ich das auf das leere stdin anwende. '''Ben 15Jun10 19:08''' @Johanna: Wenn man schon weiß, dass man die Datei nur schreiben will, wie hier der Fall, dann mit ''"w"'' öffnen. Das ist so ein Grundprinzip beim Programmieren und überhaupt: immer nur so viele Rechte wie nötig, umso weniger unbeabsichtigte Fehler kann man machen. Das ''const'' hat man ja zum Beispiel auch aus genau so einem Grund. '''Hannah 15Jun10 19:01''' @Hannah: Danke! :D Dann war wohl das Ubuntu Update schuld.... '''Niklas 15Jun10 18:58''' Ist es besser, fopen bei der Output-Datei mit 'r+' oder mit 'w' zu öffnen? Oder ist das völlig egal, so lange man im Falle von 'r+' eine Fehlermeldung ausgibt, falls die Datei nicht existiert? '''Johanna 15Jun10 18:48''' @Niklas: Das ist keine Sache von uns, sondern alleine von Ihren lokalen Einstellungen. Sie können einen Editor Ihrer Wahl einstellen mit ''export SVN_EDITOR=...'', wobei ''...'' zum Beispiel ''vim'' ist oder ''xemacs'' oder ''gedit'' oder ... '''Hannah 15Jun10 18:46''' Anscheinend muss man die svn logs jetzt mit vim schreiben, sehe ich das richtig? Jedenfalls habe ich gerade 15 Minuten damit zugebracht ihn zu überreden meinen Eintrag zu speichern... leider ohne Erfolg! Könnte mir bitte jemand kurz erklären, wie das geht? '''Niklas 15Jun10 17:22''' @Tina: Schreiben Sie hinter ''-lgtest_main'' auch noch ''-static'', dann sollte es gehen. Ausführlich erklärt habe ich das Ganze auf der [[http://vulcano.informatik.uni-freiburg.de/wiki/teaching/ProgrammierenCplusplusSS2010/Blatt3Fragen|Seite mit den Kommentaren zum 3. Übungsblatt]], und zwar in meinem Beitrag ''9Mai10 18:54''. '''Hannah 15Jun10 17:14''' Auf die Gefahr hin, das das schon mehr als einmal gefragt wurde: Was bedeutet bei make test folgende Fehlermeldung: ''./GrepTest: error while loading shared libraries: libgtest_main.so.0: cannot open shared object file: No such file or directory. make: *** [test] Fehler 127''? '''Tina 15Jun10 16:57''' @Jonathan: Wenn ''--regularExpressionMatch == false'', sind das Hütchen und Dollar Zeichen wie jede andere auch. Das heißt, das pattern {{{^abc$}}} würde dann zu der Zeile {{{xxx^abc$yyy}}} matchen, aber nicht zur der Zeile {{{abc}}}. '''Hannah 15Jun10 14:54''' Und was ist bei ''--regularExpressionMatch == true'' ? '''JonathanN 15Juni10 15:59''' @Alle wegen Hudson: Unser Rechner ''stromboli'' wurde heute morgen nochmal rebootet und ich bin erst gerade wieder an meinen Schreibtisch gekommen. Habe Hudson jetzt neu gestartet. Eigentlich sollten da außer mir noch ein paar andere Leute draufgucken, aber dem ist gerade leider nicht so. '''Hannah 15Jun10 14:59''' @Simson 15Jun10 14:15: Ja, Sie können davon ausgehen dass egal ob die Eingabe von standard input oder von einer Datei kommt, am Ende jeder Zeile, auch der letzten, ein '\n' steht. Wenn am Ende der letzten Zeile kein '\n' steht, ist es Ihnen überlassen, ob Sie die Zeile ignorieren oder trotzdem berücksichtigen. Mein Code aus der Vorlesung ignoriert so eine Zeile, wie ich bereits unten schon mal erklärt hatte. '''Hannah 15Jun10 14:57''' @Simson 15Jun10 13:45: Ich verstehe Ihre Frage nicht, was heißt es, ein Pattern zu übergeben und gleich wieder auszugeben? '''Hannah 15Jun10 14:55''' @Dario + Alle: Ich habe in der Vorlesung an mehreren Stellen auf die Dokumentation für ''fopen'', ''fwrite'', etc. verwiesen. Entweder über ''man 3 fopen'' etc. oder im Web (der Link dazu steht auf in den Referenzen am Ende der Folien). In dieser Dokumentation steht alles aber auch alles zu diesen Funktionen, und zwar in der Regel so, dass man schnell findet was man sucht. '''Hannah 15Jun10 14:43''' @Hannah: Zu '''Hannah 14Jun10 20:18''': Können wir auch davon ausgehen, dass bei Verwendung von stdin auch ein newline am Ende ist? (Also wie die Leerzeile im inputFile) '''Simson 15Jun10 14:15''' Wenn ich als Pattern {{{"^asdf$"}}} übergebe und es gleich wieder ausgebe, erhalte ich {{{^asdf$}}} was mir als recht sinnvoll erscheint ;-) Übergebe ich allerdings {{{"^asdf$$"}}} habe ich Ausgaben wie {{{^asdf859}}} (Auch mit anderen Zahlen), was ich nicht so recht einsehe... '''Simson 15Jun10 13:45''' Hallo, folgender Patter ^abc$ macht bei isMatch nur ein True wenn regular expression mit gesetzt ist, wenn die Zeile nur aus abc besteht, oder habe ich da etwas falsch verstanden? ''' JonathanN 15Juni2010 13:45 ''' @Dario: R steht für Read (Datei öffnen, aber nur lesen lassen). @Dennis: Nope, wollte auch grad mal wieder mit Hudson testen und da geht nix... '''SebastianS 15Jun10 12:28''' Auf der Folie 11 Vorlesung 7 steht frwrite geschrieben müßte fwrite aber stehen. Was bedeutet "r" in diesem Code {{{inputFile = fopen(_inputFileName, "r")}}} Gruß '''Dario 15Jun10 11:49''' Es scheint, dass Hudson seit gestern morgen offline ist. Oder bin ich der einzige mit dem Problem? '''Dennis 15Jun10 11:36''' @Sebastian: Ja, so ist es, beim Schreiben der zusätzlichen Spezifikation habe ich meine Meinung geändert, da es auch nicht schwerer war, es so zu spezifizieren, also warum nicht gleich so wie es das richtige ''grep'' macht. Ich betone aber nochmal, dass Sie oder irgendjemand bei solchen Fällen von "Nachspezifikation" keine Punkte verlieren können, egal wie Sie es machen. Es ist nur für die, die es ganz genau wissen wollen (was mich ja freut). '''Hannah 15Jun10 10:59''' @Hannah: Mit den ergänzten Spezifikationen sollte mein Beispiel von unten (das mit den multiplen ^ und $) ja dann auch nicht mehr auf das gegebene Beispiel zutreffen, oder? '''SebastianS 15Jun10 02:19''' @Johannes: Ok, scheint nicht so leicht zu sein, das in (wenigen) Worten klar zu machen. Ich habe jetzt einfach in ''vorlesungen/vorlesung-7/Grep.h'' die Spezifikation erweitert (durch ''NEW(bast ...)'' markiert). Habe ich dann doch für die Variante entschieden, dass Hütchen und Dollar im pattern ihre Sonderbedeutung nur am Anfang bzw. Ende des patterns haben und sonst wie normale Zeichen zu behandeln sind. Weil ich zuerst gar nicht an diesen Fall gedacht habe, ist es Ihnen überlassen, ob Sie diesen Sonderfall berücksichtigen oder nicht, aber wäre toll, wenn Sie's tun. Eine gute Implementierung von ''isMatch'' sollte auch leicht abzuändern sein, so dass Sie das tut. Oder noch besser, es schon von selber tun ohne dass man vorher dran gedacht hat. '''Hannah 14Jun10 20:40''' @Betim: Fehlermeldungen und Warnungen immer auf ''stderr'' ausgeben. Das hat viele Vorteile, u.a. dass man Sie von der Kommandozeile aus leicht in eine Datei umlenken kann. Überlegen Sie einfach bei jeder Ausgabe immer, was ist normale Ausgabe von meinem Programm und was hat den Charakter einer Fehlermeldung. '''Hannah 14Jun10 20:25''' @Tim + Alle: Unser Rechner ''stromboli'' wurde rebootet und Hudson wurde aber nicht automatisch neu gestartet, obwohl es in der ''init.d'' steht, komisch. Habe es gerade von Hand neu gestartet. '''Hannah 14Jun10 20:24''' @Simson: ''getchar'' verhält sich ohne Weiteres nicht so wie Sie denken, weil die Zeichen gepuffert bis zur nächsten Eingabe eines newline gepuffert werden. Für unsere Anwendung hier brauchen Sie aber kein ''getchar'', benutzen Sie ''fgets''. '''Hannah 14Jun10 20:22''' @Martin: Das liegt einfach an der Art und Weise wie ''findMatches'' implementiert ist (ich gehe davon aus, dass Sie im Wesentlichen meine Implementierung aus der Vorlesung übernommen haben). Das ''fgets'' liest ja immer bis zum nächsten ''\n'', es sei denn es kommt keins mehr, dann liest es bis zum Ende der Datei. Wenn jetzt die letzte Zeile mit einem ''\n'' endet, dann wird die gelesen, danach ist ''feof(inputFile)'' noch *nicht* ''true'' und für die Zeile wird das ''if (isMatch...) ...'' aufgerufen. Erst in der nächsten Iteration, wird mit ''fgets'' das Ende der Datei erreicht, und direkt danach wird dann die Schleife mit ''break'' verlassen. Endet die letzte Zeile aber nicht mit einem ''\n'', liest fgets bis zum Ende der Datei, danach ist ''feof(inputFile) == true'' und mit der nächsten Zeile wir die Schleife verlassen, noch bevor das ''if (isMatch...) ...'' verlassen wird. Man kann jetzt darüber streiten ob eine Zeile ohne ein ''\n'' am Ende eine Zeile ist. Sie können meinen Code abändern, so dass er auch mit diesem Spezialfall sinnvoll(er) umgeht, Sie den Code aber auch so lassen wie er ist. Generell ist eine Textdatei ohne newline am Ende immer schlechter Stil, und die meisten Editoren zeigen für solchen Dateien auch eine Warnung an, weil es einfach bei vielen Programmen zu Fehlern führt, aus ganz ähnlichen Gründen wie den genannten. Ok? '''Hannah 14Jun10 20:18''' @TimV: Keine Ahnung ob Hudson geht, mein(e) Browser kann/können auch keine Verbindung aufbauen. Eine andere Frage: In dem TODO im ''Grepp.cpp'' steht, wenn die Zeile > ''MAX_LINE_LENGTH'' ist, soll eine Warnung ausgespuckt werden. Soll die Warnung in '''stderr''' geschrieben werden oder reicht ein ''printf("Warning...)'' aus? ('''BetimM 14Jun10 19:49''') Kann es sein, dass Hudson grad nicht geht? Habs mit Firefox und Opera probiert, aber beide sind der Meinung sie könnten keine Verbindung zum Server herstellen. Ist dem so, oder liegt der Fehler bei mir? ('''TimV 14Jun10 19:02''') Wieder mal ein merkwürdiger Fehler. Ich habe einen Test für die findMatches methode geschrieben, in der ich eine Textdatei mit drei Zeilen erzeuge. In der ersten und in der dritten Zeile befindet sich ein Schlüsselwort, was gefunden werden soll. Die Ausgabe des der Suche wird wiederum in einer Datei gespeichert, die ich dann auslese. Jetzt das merkwürdige: Wenn diese drei Zeilen alle einen Zeilenumbruch am Ende haben, funktioniert alles problemlos. Wenn ich aber bei der letzten Zeile den Zeilenumbruch weglasse - der ist ja unnötig, oder? - wird nur das erste auftreten des Patterns (also der in der ersten Zeile) gefunden und der Test geht schief, weil er beim einlesen der zweiten Zeile aus dem Suchergebnis - die ja eigentlich die dritte aus der Testfile sein sollte immer noch die erste lädt. Zusätzlich failed dann noch der Test unterhalb dieses Test, der aber gar nicht mehr in den geschweiften Klammern des ersten Tests ist. Also nochmal zum Verständnis: Wenn das Testfile schreibe ich so generiert wird: {{{ fprintf(testFile, "Here we have a pattern in the first line.\n"); fprintf(testFile, "Nothing to be found in the second line.\n"); fprintf(testFile, "Another pattern can be found in the third line.\n"); }}} ...findet er diese zwei Zeilen bei _pattern = "pattern" {{{ Here we have a pattern in the first line. Another pattern can be found in the third line. }}} Wenn das Testfile so generiert wird: {{{ fprintf(testFile, "Here we have a pattern in the first line.\n"); fprintf(testFile, "Nothing to be found in the second line.\n"); fprintf(testFile, "Another pattern can be found in the third line."); }}} ...findet er nur die erste Zeile und einer der darunterliegenden Tests failed. Geht es jemand anderes auch so? '''MartinS 14Jun15:41''' Warum schreibt folgender Code nicht die Eingabe (stdin) in die Datei? {{{ myFile = fopen("filename", "a+"); while(true) { char c; c = getchar(); fprintf(myFile, "%c", c); } }}} Mit {{{printf(myFile, "%c", c);}}} wird alles korrekt ausgegeben... '''Simson 14Jun10 15:39''' @Hannah Verstehe ich das dann richtig, dass ein ''$'' oder ein ''^'' im Pattern als wirkliches Zeichen interpretiert werden und nur am Anfang und Ende die besondere Bedeutung haben? '''Johannes 14Jun10 14:21''' @Johannes: Also das war so gedacht. Wenn ''--regularExpressionMatch == false'' dann sind Hütchen und ''$'' und ''.'' Zeichen wie jede andere, sowohl im Muster als auch im Text. Wenn ''-regularExpressionMatch == true'' dann haben Sie die beschriebene Sonderbedeutung im pattern, egal an welcher Stelle sie dort stehen, siehe mein vorheriger Kommentar dazu. Letzteres bedeutet, dass man dann ein Hütchen und ein ''$'' im Text gar nicht exakt matchen kann (man müsste dann ''.'' im pattern schreiben, weil der matched ja alles). '''Hannah 14Jun10 13:59''' Ich habe nochmal eine Frage, darf ein $ auch in einem Pattern vorkommen und wenn ja, was passiert dann? Also ich meine ('''Johannes 14Jun10 13:45''') {{{ asd$ ff$ oder asd$ ff }}} @Sebastian: Gute Frage, daran habe ich gar nicht gedacht. Ich überlasse es Ihnen, würde aber vorschlagen dass, wie Sie auch sagen, Ihr Beispielpattern auf Ihrer Beispielzeile einen Treffer gibt. '''Hannah 14Jun10 12:25''' @Johannes: Ojeoje, noch ein Fehler, ja, da habe ich ''_caseSensitiveMatch'' und ''_caseInsensitiveMatch'' durcheinander gebracht. Habe es jetzt alles mit Bezug auf ''_caseSensitiveMatch'' umgeschrieben und ins SVN gemacht, hoffentlich stimmt's jetzt. Wobei ja jeweils klar sein sollte, wie es gemeint ist. '''Hannah 14Jun10 12:17''' Wie sollen wir eigentlich mit einem Pattern der Form {{{ ^^^^^^asdf$$$$$ }}} umgehen - das funktioniert ganz normal, wenn die Zeile ''asdf'' lautet, oder? '''SebastianS 14Jun10 12:12''' Ist in dem Kommentar nicht ein Fehler drin? Es müsste doch heißen with _caseInsensitiveMatch = True oder? ('''Johannes 14Jun10 11:05''') {{{ // Of course, any combination of values for _caseSensitiveMatch and // _regularExpressionMatch should work. For example, with _caseSensitiveMatch // == true and _regularExpressionMatch == true, the following calls to isMatch // should return true: // isMatch("This is just a line", "^THis") }}} @Fabian + Alle: Mea culpa, ich habe ein '''k''' vergessen, es aber jetzt noch nachträglich eingefügt und extra fett gemacht. Erstaunlich was ein Buchstabe für einen Unterschied machen kann ... '''Hannah 14Jun10 10:45''' @Hannah: Sie widersprechen mit ('''Hannah 13Jun10 23:27''') doch ihrer eigenen Spezifikation: {{{ // If _regularExpressionMatch == true, the characters ^ and $ and . have a // special meaning. Namely, the ^ matches only at the beginning of the line, // the $ matches only at the end of the line, and the . matches any character. }}} Oder heißt bei ihnen "Treffer", dass isMatch false zurückgibt? '''Fabian 14Jun10 9:34''' @Dario: Wenn man mit ''getopt.h'' und ''getopt'' bzw. ''getopt_long'' die Optionen parsed, wie in der Vorlesung vorgemacht, dann ist in der ''while(true)'' Schleife wann immer eine Option erkannt wurde ''optarg'' gerade das Argument dieser Option (falls es eine Option mit Argument war). '''Hannah 13Jun10 23:34''' @Martin: So wie ich Fabian verstanden habe, ist sein Problem inzwischen gelöst (siehe sein Beitrag ''Fabian 13Jan10 17:08'', erster Satz). Wenn das Ihr Problem nicht löst, was ist denn dann noch Ihr Problem? '''Hannah 13Jun10 23:31''' @Simson: Wenn ^ in einem regulären Ausdruck nicht an erster Stelle vorkommt, bedeutet das mit Sicherheit '''k'''einen Treffer und so sollte sich ''isMatch'' dann auch verhalten (und idealerweise sollte es einen Test geben, der das nachprüft). Das selbe mit einem $, das nicht am Ende steht. '''Hannah 13Jun10 23:27''' Hallo, kann jemand mir sagen was dies optarg z.B. _inputFileName = optarg; bedeutet? '''Dario 13Jun10 21:47''' Ich habe das gleiche Problem wie '''Fabian 13Jun10 15:34. '''Was kann man da tun?''' MartinW 13Jun10 20:08<<BR>>''' Soll man eigentlich irgendwie auf ^/& bei einem regulären Ausdruck reagieren, wenn diese nicht am Anfang/Ende stehen oder sollen die dann einfach als normales Zeichen verwendet werden? '''Simson 13Jun10 18:36''' 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''' @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 <<BR>>''' @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 <<BR>>''' 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<<BR>>''' 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''' |
Fragen und Kommentare zur 7. Vorlesung / zum 7. Übungsblatt
Der Backslash muss vor das $, nicht vor das Pattern, nehme ich an. SebastianD 16Jun10 13:11
Guter fund! ändert beim ausführen des Programs in der Shell leider nichts bei mir.
echo ^testing$ | ./GrepMain ^^testing$$
gibt nichts aus, dasselbe mit einem Backslash vor dem pattern.aber der selbe test funktioniert rund... JonathanB 16Jun 13:11
Der Zugriff auf die Variable kann mit einem vorangestellten Backslash unterdrückt werden! --> \$rdsdfsdf$ gibt $rdsdfsdf$ Simson 16Jun10 13:04
Ja, echo $$ gibt mir auch 392 zurück und echo $[irgendwas] gibt mir nur eine leere Zeile zurück... Simson 16Jun10 12:55
Ich habe nur begrenzte Linux-Kenntnisse, aber ich glaube das Problem mit $ ist das es ein special character für die Shell ist, u.a. kann man so auf sogennante Umgebungsvariablen des Betriebssystems zugreifen. Irgendwie ersetzt dann die Shell beim ausführen eines Befehls, wo $ drin ist, diese $ durch die dazugehörige Variable, oder sowas in der Richtung... Ding ist, wie die Umgebungsvariablen heissen, eingesetzt werden usw, hängt von der Konfiguration des Betriebssystems ab, d.h. es gibt ein fix der für jeden funktionieren würde ... JonathanB 16Jun10 12:49
Noch mehr Probleme mit $: nach parseCommandLineArguments mit $rdsdfsdf$ als pattern bekomme ich bei printf("%s\n", _pattern); als Ausgabe $ (Länge1) und sonst nichts. Auch bei pattern rdsdfsdf$fdddddddddd ist nach dem parsen nur noch rdsdfsdf übrig. Simson 16Jun10 12:23
@Jens: meinst du stringLength aus der Grep.cpp ? wie gesagt die sagt 13, obwohls es nur 11 Zeichen sind. Jonathan 16June 11:40
@Jonathan & Jens: das ist mir auch schon aufgefallen (Simson 15Jun10 13:45). Length & strlen ist dann die tatsächliche Länge (bei Jonathan also 13). Simson 16Jun 11:30
@Jonathan: Was sagt denn strlen? Jens 16Jun 11:28
@Regina: grub ist das Bootloader von deinem Linux, d.h. es ist was schief an deiner Installation/Bootsektor passiert, das ist schon ein größeres Problem... kannst mal versuche nach "grub rescue" zu googlen, da gibts es jede Menge. JonathanB 16June 11:17
Ich bin gerade auf was merkwürdiges gekommen... wenn ich mir die Länge des Patterns
^^testing$$
ausgeben lasse, gibt das Program 13 aus, sollte aber 11 sein, der char* ist ausgefüllt mit:
^^testing1309
An der Prozedur zur Berechnung der Länge habe ich nichts geändert, es funzt auch für alle Arten von char* . Also den Befehl
echo $$
gibt tatsächlich 1390 aus ... erm was ist den da los? Umgebungsvariable in $$ ? wie kann ich dann den o.g. Pattern Grep übergeben? JonathanB 16June11:08
HILFE!! Wenn ich versuche, den Laptop hochzufahren, bekomme ich die Fehlermeldung:
error: unknown filesystem grub rescue >
Was ist das, und wie löse ich das problem?? Regina 16Jun10 11:20
Das war es, ich hatte den Ordner aus dem Vorlesungsverzeichnis kopiert. Vielen Dank für deine Hilfe Norman 16Jun10 03:00
Entweder versuchst du, den Ordner "vorlesungen" (das ist der, über den wir die Vorlesungsdateien bekommen können) zu committen (welcher offenbar schreibgeschützt ist - ist auch gut so), oder du hast einfach den gesamten Ordner in dein Unterverzeichnis kopiert und umbenannt (was man nicht tun sollte). Falls letzteres: .svn Unterordner (in uebungsblatt-7) löschen und das Verzeichnis neu adden. SebastianD 16Jun10 00:27
@Jens: Also ich erhalte beim checkout folgenden Fehler: Übertragen schlug fehl (Details folgen): Der Server hat einen unerwarteten Rückgabewert (403 Forbidden) in Antwort auf die Anfrage CHECKOUT für »/teaching/cplusplus-ss2010/!svn/ver/3748/vorlesungen/vorlesung-7/Grep.cpp« zurückgeliefert Norman 15Jun10 00:22
@Dennis: Wie Fabian schon sagt liegt es dann ziemlich sicher an einem fehlenden fclose. Schau mal in deiner findMatches() Methode ob du auch wirklich zu allen Files am Schluss ein fclose aufrufst. Schließlich arbeitet findMatches() in deinem Test auch auf der output.txt, du wirst da das fclose vergessen haben. Auch in deinem Test würde ich unten noch ein fclose(outputFile) machen.
@Jan: Dumme Frage, aber hast du auch _regularExpressionMatch auf true gesetzt in deinem Test? Roman 15Jun10 23:55
@Dennis: Das einzige, was mir im Moment noch einfällt, wäre, dass "output.txt" irgendwo zweimal hintereinander geöffnet wurde, aber vergessen wurde, es zu schließen(wahrscheinlich in findMatches). Die Dateien sollte man, wenn man sie nicht mehr braucht immer sofort schließen, oder man kann leicht Fehler machen.
Bsp.:
FILE* file; char line[200]; { FILE* f2 = fopen("out.txt", "w"); fprintf(f2,"Help\n"); // hier fehlt fclose(f2); } file = fopen("out.txt", "r"); fgets(line, 200, file); printf("%s\n", line);//falsche Ausgabe // aber nach Ende des Programms richtige Datei fclose(file);
Fabian 15Jun10 23:25
@ Roman: ich habe for fgets noch ein fopen eingefügt so wie Fabian es gesagt hat. Das mit %c stimmt ich habe es jedoch nur mal testweise von %s auf %c gesetzt. ist mitlerweile wieder auf %s. ändert ja aber auch nichts daran dass fgets einfach nicht das den inhalt von output.txt in line kopiert. Dennis 15Jun10 23:09
@Dennis: Dein fclose(outputFile) darf nicht vor fgets stehen, in fgets liest du ja noch aus outputFile. Und dein printf kann so auch nicht klappen, %c steht für einen _einzelnen_ char.Roman 15Jun10 22:39
@Norman: Ich sehe kein Problem. Sie haben Schreib- und Leserechte auf den Ordner uebungsblatt-7. Jens 1537Jun10 22:
@Hannah: Ich kann seit heute Mittag nichts comitten... Es ist mir "forbidden" (Error 403).... Norman 15Jun10 22:33
@Fabian Ich öffne sie ja mit "w" weil ich zwei neue Dateien für den Test anlegen muss. Wie du gesagt hast hab ich nun noch vor fgets ein fopen eingefügt. Hier dann auch mit "r" da ich ja nur lesen will. Sollte also eigentlich richtig so sein. Dennis 15Jun10 22:31
@Dennis: Ich habe eine ganz ähnliche Ausgabe erzeugen können, indem ich eine Datei mit "w" statt mit "r" geöffnet habe. Nur mit "w" nur aufrufen, wenn du die Datei komplett neu schreiben (und auch nur schreiben) willst ("a" um ans Ende der Datei zu schreiben), "r" wenn du nur ausliest. Vielleicht behebt das ja dein Problem Fabian 15Jun10 21:39
Ich habe das Problem, dass Test fehlschlagen, welche jedoch per direktem Aufruf funktionieren. Bspw. der Aufruf
./GrepMain "^This" --input-file in.txt --regular-expression-match
mit dem Inhalt "This is Just A Line" funktioniert einwandfrei. Der Testfall
ASSERT_TRUE(g.isMatch("This is Just A Line", "is..ust"));
hingegen, funktioniert nicht. Jan 15Jun10 21:31
Ja stimmt aber ändert nichts. Ausgabe von line ist immer noch "Line: ��.@��.@" obwohl in output.txt die gefundene Zeile steht. Dennis 15Jun10 21:21
@Dennis: Könnte es sein, dass du vor fgets vergessen hast, die Datei zu öffnen??? Fabian 15Jun10 21:01
Ich möchte die Ausgabe in eine Datei testen. Mit dem folgenden Code wird die output.txt Datei auch erzeugt und enthält nach dem aufruf von findMatches() auch mit die richtige Ausgabe ("Das ist eine Zeile"). Jedoch schlägt der test fehl weil in line nur wirre sonderzeichen geschrieben wurden (sieht man wenn man line printed). habe ich dem befüllen von line einen fehler gemacht?
// Test the findMatches method. TEST(GrepTest, findMatches) { Grep g; FILE* testInputFile = NULL; testInputFile = fopen("testfile.txt", "w"); fprintf(testInputFile, "Das ist eine Zeile\n"); fclose(testInputFile); g._inputFileName = "testfile.txt"; FILE* outputFile = NULL; outputFile = fopen("output.txt", "w"); fclose(outputFile); g._outputFileName = "output.txt"; g._pattern = "eine"; g.findMatches(); char* line = new char[30]; fgets(line, 30, outputFile); printf("Line: %c\n", line); ASSERT_EQ('D', line[0]); }
Dennis 15Jun10 20:49
Für mich ist das Warten auf eine nie kommende Eingabe gerade die Definition eines "Hängers", aber nun gut, dann vertrau ich auf die intelligente Eingabe des Users. Danke für die Antwort. Ben 15Jun10 20:28
@Ben: fgets kann sich nicht aufhängen, es wartet dann auf das nächste newline. Unabhängig davon können sie Eingabe über standard input nicht automatisch testen und müssen Sie von daher auch nicht. Dasselbe mit Ausgabe nach standard output. Was Sie testen sollen ist Eingabe von einer Datei und Ausgabe in eine Datei. Hannah 15Jun10 19:16
Hallo, wie kann man auf leeres stdin testen (also kein Testfall, sondern per if abfangen). fgets hängt sich bei mir nämlich immer auf, wenn ich das auf das leere stdin anwende. Ben 15Jun10 19:08
@Johanna: Wenn man schon weiß, dass man die Datei nur schreiben will, wie hier der Fall, dann mit "w" öffnen. Das ist so ein Grundprinzip beim Programmieren und überhaupt: immer nur so viele Rechte wie nötig, umso weniger unbeabsichtigte Fehler kann man machen. Das const hat man ja zum Beispiel auch aus genau so einem Grund. Hannah 15Jun10 19:01
@Hannah: Danke! Dann war wohl das Ubuntu Update schuld.... Niklas 15Jun10 18:58
Ist es besser, fopen bei der Output-Datei mit 'r+' oder mit 'w' zu öffnen? Oder ist das völlig egal, so lange man im Falle von 'r+' eine Fehlermeldung ausgibt, falls die Datei nicht existiert? Johanna 15Jun10 18:48
@Niklas: Das ist keine Sache von uns, sondern alleine von Ihren lokalen Einstellungen. Sie können einen Editor Ihrer Wahl einstellen mit export SVN_EDITOR=..., wobei ... zum Beispiel vim ist oder xemacs oder gedit oder ... Hannah 15Jun10 18:46
Anscheinend muss man die svn logs jetzt mit vim schreiben, sehe ich das richtig? Jedenfalls habe ich gerade 15 Minuten damit zugebracht ihn zu überreden meinen Eintrag zu speichern... leider ohne Erfolg! Könnte mir bitte jemand kurz erklären, wie das geht? Niklas 15Jun10 17:22
@Tina: Schreiben Sie hinter -lgtest_main auch noch -static, dann sollte es gehen. Ausführlich erklärt habe ich das Ganze auf der Seite mit den Kommentaren zum 3. Übungsblatt, und zwar in meinem Beitrag 9Mai10 18:54. Hannah 15Jun10 17:14
Auf die Gefahr hin, das das schon mehr als einmal gefragt wurde: Was bedeutet bei make test folgende Fehlermeldung: ./GrepTest: error while loading shared libraries: libgtest_main.so.0: cannot open shared object file: No such file or directory. make: *** [test] Fehler 127? Tina 15Jun10 16:57
@Jonathan: Wenn --regularExpressionMatch == false, sind das Hütchen und Dollar Zeichen wie jede andere auch. Das heißt, das pattern ^abc$ würde dann zu der Zeile xxx^abc$yyy matchen, aber nicht zur der Zeile abc. Hannah 15Jun10 14:54 Und was ist bei --regularExpressionMatch == true ? JonathanN 15Juni10 15:59
@Alle wegen Hudson: Unser Rechner stromboli wurde heute morgen nochmal rebootet und ich bin erst gerade wieder an meinen Schreibtisch gekommen. Habe Hudson jetzt neu gestartet. Eigentlich sollten da außer mir noch ein paar andere Leute draufgucken, aber dem ist gerade leider nicht so. Hannah 15Jun10 14:59
@Simson 15Jun10 14:15: Ja, Sie können davon ausgehen dass egal ob die Eingabe von standard input oder von einer Datei kommt, am Ende jeder Zeile, auch der letzten, ein '\n' steht. Wenn am Ende der letzten Zeile kein '\n' steht, ist es Ihnen überlassen, ob Sie die Zeile ignorieren oder trotzdem berücksichtigen. Mein Code aus der Vorlesung ignoriert so eine Zeile, wie ich bereits unten schon mal erklärt hatte. Hannah 15Jun10 14:57
@Simson 15Jun10 13:45: Ich verstehe Ihre Frage nicht, was heißt es, ein Pattern zu übergeben und gleich wieder auszugeben? Hannah 15Jun10 14:55
@Dario + Alle: Ich habe in der Vorlesung an mehreren Stellen auf die Dokumentation für fopen, fwrite, etc. verwiesen. Entweder über man 3 fopen etc. oder im Web (der Link dazu steht auf in den Referenzen am Ende der Folien). In dieser Dokumentation steht alles aber auch alles zu diesen Funktionen, und zwar in der Regel so, dass man schnell findet was man sucht. Hannah 15Jun10 14:43
@Hannah: Zu Hannah 14Jun10 20:18: Können wir auch davon ausgehen, dass bei Verwendung von stdin auch ein newline am Ende ist? (Also wie die Leerzeile im inputFile) Simson 15Jun10 14:15
Wenn ich als Pattern "^asdf$" übergebe und es gleich wieder ausgebe, erhalte ich ^asdf$ was mir als recht sinnvoll erscheint Übergebe ich allerdings "^asdf$$" habe ich Ausgaben wie ^asdf859 (Auch mit anderen Zahlen), was ich nicht so recht einsehe... Simson 15Jun10 13:45
Hallo, folgender Patter ^abc$ macht bei isMatch nur ein True wenn regular expression mit gesetzt ist, wenn die Zeile nur aus abc besteht, oder habe ich da etwas falsch verstanden? JonathanN 15Juni2010 13:45
@Dario: R steht für Read (Datei öffnen, aber nur lesen lassen). @Dennis: Nope, wollte auch grad mal wieder mit Hudson testen und da geht nix... SebastianS 15Jun10 12:28
Auf der Folie 11 Vorlesung 7 steht frwrite geschrieben müßte fwrite aber stehen. Was bedeutet "r" in diesem Code inputFile = fopen(_inputFileName, "r") Gruß Dario 15Jun10 11:49
Es scheint, dass Hudson seit gestern morgen offline ist. Oder bin ich der einzige mit dem Problem? Dennis 15Jun10 11:36
@Sebastian: Ja, so ist es, beim Schreiben der zusätzlichen Spezifikation habe ich meine Meinung geändert, da es auch nicht schwerer war, es so zu spezifizieren, also warum nicht gleich so wie es das richtige grep macht. Ich betone aber nochmal, dass Sie oder irgendjemand bei solchen Fällen von "Nachspezifikation" keine Punkte verlieren können, egal wie Sie es machen. Es ist nur für die, die es ganz genau wissen wollen (was mich ja freut). Hannah 15Jun10 10:59
@Hannah: Mit den ergänzten Spezifikationen sollte mein Beispiel von unten (das mit den multiplen ^ und $) ja dann auch nicht mehr auf das gegebene Beispiel zutreffen, oder? SebastianS 15Jun10 02:19
@Johannes: Ok, scheint nicht so leicht zu sein, das in (wenigen) Worten klar zu machen. Ich habe jetzt einfach in vorlesungen/vorlesung-7/Grep.h die Spezifikation erweitert (durch NEW(bast ...) markiert). Habe ich dann doch für die Variante entschieden, dass Hütchen und Dollar im pattern ihre Sonderbedeutung nur am Anfang bzw. Ende des patterns haben und sonst wie normale Zeichen zu behandeln sind. Weil ich zuerst gar nicht an diesen Fall gedacht habe, ist es Ihnen überlassen, ob Sie diesen Sonderfall berücksichtigen oder nicht, aber wäre toll, wenn Sie's tun. Eine gute Implementierung von isMatch sollte auch leicht abzuändern sein, so dass Sie das tut. Oder noch besser, es schon von selber tun ohne dass man vorher dran gedacht hat. Hannah 14Jun10 20:40
@Betim: Fehlermeldungen und Warnungen immer auf stderr ausgeben. Das hat viele Vorteile, u.a. dass man Sie von der Kommandozeile aus leicht in eine Datei umlenken kann. Überlegen Sie einfach bei jeder Ausgabe immer, was ist normale Ausgabe von meinem Programm und was hat den Charakter einer Fehlermeldung. Hannah 14Jun10 20:25
@Tim + Alle: Unser Rechner stromboli wurde rebootet und Hudson wurde aber nicht automatisch neu gestartet, obwohl es in der init.d steht, komisch. Habe es gerade von Hand neu gestartet. Hannah 14Jun10 20:24
@Simson: getchar verhält sich ohne Weiteres nicht so wie Sie denken, weil die Zeichen gepuffert bis zur nächsten Eingabe eines newline gepuffert werden. Für unsere Anwendung hier brauchen Sie aber kein getchar, benutzen Sie fgets. Hannah 14Jun10 20:22
@Martin: Das liegt einfach an der Art und Weise wie findMatches implementiert ist (ich gehe davon aus, dass Sie im Wesentlichen meine Implementierung aus der Vorlesung übernommen haben). Das fgets liest ja immer bis zum nächsten \n, es sei denn es kommt keins mehr, dann liest es bis zum Ende der Datei. Wenn jetzt die letzte Zeile mit einem \n endet, dann wird die gelesen, danach ist feof(inputFile) noch *nicht* true und für die Zeile wird das if (isMatch...) ... aufgerufen. Erst in der nächsten Iteration, wird mit fgets das Ende der Datei erreicht, und direkt danach wird dann die Schleife mit break verlassen. Endet die letzte Zeile aber nicht mit einem \n, liest fgets bis zum Ende der Datei, danach ist feof(inputFile) == true und mit der nächsten Zeile wir die Schleife verlassen, noch bevor das if (isMatch...) ... verlassen wird. Man kann jetzt darüber streiten ob eine Zeile ohne ein \n am Ende eine Zeile ist. Sie können meinen Code abändern, so dass er auch mit diesem Spezialfall sinnvoll(er) umgeht, Sie den Code aber auch so lassen wie er ist. Generell ist eine Textdatei ohne newline am Ende immer schlechter Stil, und die meisten Editoren zeigen für solchen Dateien auch eine Warnung an, weil es einfach bei vielen Programmen zu Fehlern führt, aus ganz ähnlichen Gründen wie den genannten. Ok? Hannah 14Jun10 20:18
@TimV: Keine Ahnung ob Hudson geht, mein(e) Browser kann/können auch keine Verbindung aufbauen. Eine andere Frage: In dem TODO im Grepp.cpp steht, wenn die Zeile > MAX_LINE_LENGTH ist, soll eine Warnung ausgespuckt werden. Soll die Warnung in stderr geschrieben werden oder reicht ein printf("Warning...) aus? (BetimM 14Jun10 19:49)
Kann es sein, dass Hudson grad nicht geht? Habs mit Firefox und Opera probiert, aber beide sind der Meinung sie könnten keine Verbindung zum Server herstellen. Ist dem so, oder liegt der Fehler bei mir? (TimV 14Jun10 19:02)
Wieder mal ein merkwürdiger Fehler. Ich habe einen Test für die findMatches methode geschrieben, in der ich eine Textdatei mit drei Zeilen erzeuge. In der ersten und in der dritten Zeile befindet sich ein Schlüsselwort, was gefunden werden soll. Die Ausgabe des der Suche wird wiederum in einer Datei gespeichert, die ich dann auslese. Jetzt das merkwürdige: Wenn diese drei Zeilen alle einen Zeilenumbruch am Ende haben, funktioniert alles problemlos. Wenn ich aber bei der letzten Zeile den Zeilenumbruch weglasse - der ist ja unnötig, oder? - wird nur das erste auftreten des Patterns (also der in der ersten Zeile) gefunden und der Test geht schief, weil er beim einlesen der zweiten Zeile aus dem Suchergebnis - die ja eigentlich die dritte aus der Testfile sein sollte immer noch die erste lädt. Zusätzlich failed dann noch der Test unterhalb dieses Test, der aber gar nicht mehr in den geschweiften Klammern des ersten Tests ist. Also nochmal zum Verständnis: Wenn das Testfile schreibe ich so generiert wird:
fprintf(testFile, "Here we have a pattern in the first line.\n"); fprintf(testFile, "Nothing to be found in the second line.\n"); fprintf(testFile, "Another pattern can be found in the third line.\n");
...findet er diese zwei Zeilen bei _pattern = "pattern"
Here we have a pattern in the first line. Another pattern can be found in the third line.
Wenn das Testfile so generiert wird:
fprintf(testFile, "Here we have a pattern in the first line.\n"); fprintf(testFile, "Nothing to be found in the second line.\n"); fprintf(testFile, "Another pattern can be found in the third line.");
...findet er nur die erste Zeile und einer der darunterliegenden Tests failed. Geht es jemand anderes auch so? MartinS 14Jun15:41
Warum schreibt folgender Code nicht die Eingabe (stdin) in die Datei?
myFile = fopen("filename", "a+"); while(true) { char c; c = getchar(); fprintf(myFile, "%c", c); }
Mit printf(myFile, "%c", c); wird alles korrekt ausgegeben... Simson 14Jun10 15:39
@Hannah Verstehe ich das dann richtig, dass ein $ oder ein ^ im Pattern als wirkliches Zeichen interpretiert werden und nur am Anfang und Ende die besondere Bedeutung haben? Johannes 14Jun10 14:21
@Johannes: Also das war so gedacht. Wenn --regularExpressionMatch == false dann sind Hütchen und $ und . Zeichen wie jede andere, sowohl im Muster als auch im Text. Wenn -regularExpressionMatch == true dann haben Sie die beschriebene Sonderbedeutung im pattern, egal an welcher Stelle sie dort stehen, siehe mein vorheriger Kommentar dazu. Letzteres bedeutet, dass man dann ein Hütchen und ein $ im Text gar nicht exakt matchen kann (man müsste dann . im pattern schreiben, weil der matched ja alles). Hannah 14Jun10 13:59
Ich habe nochmal eine Frage, darf ein $ auch in einem Pattern vorkommen und wenn ja, was passiert dann? Also ich meine (Johannes 14Jun10 13:45)
asd$ ff$ oder asd$ ff
@Sebastian: Gute Frage, daran habe ich gar nicht gedacht. Ich überlasse es Ihnen, würde aber vorschlagen dass, wie Sie auch sagen, Ihr Beispielpattern auf Ihrer Beispielzeile einen Treffer gibt. Hannah 14Jun10 12:25
@Johannes: Ojeoje, noch ein Fehler, ja, da habe ich _caseSensitiveMatch und _caseInsensitiveMatch durcheinander gebracht. Habe es jetzt alles mit Bezug auf _caseSensitiveMatch umgeschrieben und ins SVN gemacht, hoffentlich stimmt's jetzt. Wobei ja jeweils klar sein sollte, wie es gemeint ist. Hannah 14Jun10 12:17
Wie sollen wir eigentlich mit einem Pattern der Form
^^^^^^asdf$$$$$
umgehen - das funktioniert ganz normal, wenn die Zeile asdf lautet, oder? SebastianS 14Jun10 12:12
Ist in dem Kommentar nicht ein Fehler drin? Es müsste doch heißen with _caseInsensitiveMatch = True oder? (Johannes 14Jun10 11:05)
// Of course, any combination of values for _caseSensitiveMatch and // _regularExpressionMatch should work. For example, with _caseSensitiveMatch // == true and _regularExpressionMatch == true, the following calls to isMatch // should return true: // isMatch("This is just a line", "^THis")
@Fabian + Alle: Mea culpa, ich habe ein k vergessen, es aber jetzt noch nachträglich eingefügt und extra fett gemacht. Erstaunlich was ein Buchstabe für einen Unterschied machen kann ... Hannah 14Jun10 10:45
@Hannah: Sie widersprechen mit (Hannah 13Jun10 23:27) doch ihrer eigenen Spezifikation:
// If _regularExpressionMatch == true, the characters ^ and $ and . have a // special meaning. Namely, the ^ matches only at the beginning of the line, // the $ matches only at the end of the line, and the . matches any character.
Oder heißt bei ihnen "Treffer", dass isMatch false zurückgibt? Fabian 14Jun10 9:34
@Dario: Wenn man mit getopt.h und getopt bzw. getopt_long die Optionen parsed, wie in der Vorlesung vorgemacht, dann ist in der while(true) Schleife wann immer eine Option erkannt wurde optarg gerade das Argument dieser Option (falls es eine Option mit Argument war). Hannah 13Jun10 23:34
@Martin: So wie ich Fabian verstanden habe, ist sein Problem inzwischen gelöst (siehe sein Beitrag Fabian 13Jan10 17:08, erster Satz). Wenn das Ihr Problem nicht löst, was ist denn dann noch Ihr Problem? Hannah 13Jun10 23:31
@Simson: Wenn ^ in einem regulären Ausdruck nicht an erster Stelle vorkommt, bedeutet das mit Sicherheit keinen Treffer und so sollte sich isMatch dann auch verhalten (und idealerweise sollte es einen Test geben, der das nachprüft). Das selbe mit einem $, das nicht am Ende steht. Hannah 13Jun10 23:27
Hallo, kann jemand mir sagen was dies optarg z.B. _inputFileName = optarg; bedeutet? Dario 13Jun10 21:47
Ich habe das gleiche Problem wie Fabian 13Jun10 15:34. Was kann man da tun? MartinW 13Jun10 20:08
Soll man eigentlich irgendwie auf ^/& bei einem regulären Ausdruck reagieren, wenn diese nicht am Anfang/Ende stehen oder sollen die dann einfach als normales Zeichen verwendet werden? Simson 13Jun10 18:36
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
@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