Problem fgets() für nächste Zeile
-
Hi @ all,
Ich habe eine Frage. Ich möchte in einer Datei die Zeilen einlesen/verarbeiten.
Problem: Abhängig von der nächsten Zeile + übernächsten Zeile.
Der Code schaut so aus: (soweit ich das sehe ist dqs_line nicht die zeile, die ich brauche).while (fgets(inpline, MAXLENGTH, fcache) != NULL) { if(inpline[0]=='e' && inpline[1]=='v' && inpline[2]=='e' || inpline[0]=='o' && inpline[1]=='d') { if(mode == 1 && strncmp(inpline,"odd <01",18)==0) { fprintf(fmake_list,"odd <"); for(i=17;i<41;++i) fprintf(fmake_list,"%c",inpline[i]); fgets(dqs_line, MAXLENGTH, fcache); if(strncmp(dqs_line,inpline,40)==0) { for(i=41;i<45;++i) fprintf(fmake_list,"%c",dqs_line[i]); fgets(dq_line, MAXLENGTH, fcache); if(strncmp(dqs_line,dq_line,44)==0) { for(i=45;inpline[i]!='\n';++i) fprintf(fmake_list,"%c",dq_line[i]); } else { for(i=45;inpline[i]!='\n';++i) fprintf(fmake_list,"%c",dqs_line[i]); } fprintf(fmake_list,"\n"); else { for(i=41;inpline[i]!='\n';++i) fprintf(fmake_list,"%c",inpline[i]); fprintf(fmake_list,"\n"); } }
Danke für die Hilfe
-
Und wo genau ist dein Problem jetzt? fgets() liest so lange, bis entweder n-1 Zeichen eingelesen wurden oder es auf ein \n stößt. Das heißt, in 'inpline' landet die aktuelle Zeile, in dqs_line und dq_line die beiden folgenden Zeilen (wenn du denn so weit kommst).
Allerdings solltest du eventuell sicherstellen, daß die Eingabezeilen mindestens 45 Zeichen enthalten, sonst gibst du nur Datenmüll aus. (Randfrage: Wie ist denn die Eingabedatei aufgebaut?)
-
Eingangsdatei:
odd <0101111000000000000000000011Z0010101010101010100100011> even WS_NN <1001111000000000000000001100Z0010101010101010100100011> even WS_NN <1011111000000000000000001100Z0001010101010101010100011> odd <0111111000000000000000000011Z0001010101010101010100011> odd <0101111000000000000000000011Z0011001100110011000100011> even WS_NN <1001111000000000000000001100Z0011001100110011000100011> even WS_NN <1011111000000000000000001100Z0000110011001100110100011> odd <0111111000000000000000000011Z0000110011001100110100011> odd <0101111000000000000000000011Z0010101010101010100100011> even WS_NN <1001111000000000000000001100Z0010101010101010100100011>
ein odd und ein even sind immer gleich bis auf das 10 und 01 am anfang und in der mitte. (die letzte zeile ob odd oder even schaue ich mit dem mode == 1 oder 2)
also prinzipiell soll er ja lesen:
inpline = aktuelle zeile
dqs_line = nächste zeile
dq_line = übernächste zeileAusgangsdatei:
even WS_NN <1011111001000000001111001100ZZZZZZZZZZZZZZZZZZZ0100011>
odd <0111111000000000000000000011Z0001010101010101010100011>
even WS_NN <1011111000000000000000001100Z0010101010101010100100011>
odd <0111111000000000000000000011Z0000110011001100110100011>Problem:
Das dick markierte ist eine zeile zu weit oben. das gehört erst in die nächste even zeile.
-
strncmp() liefert 0 zurück, wenn die verglichenen Strings identisch sind. Das heißt, wenn die Eingabezeilen nicht übereinstimmen, geht er nicht in die jeweiligen if()-Blöcke rein.
PS: Vielleicht ist es eine gute Idee, deinen Quelltext vernünftig zu formatieren - so wie das aussieht, hat man Probleme, die einzelnen Anweisungsblöcke zuzuordnen.
-
ja aber das ist ja beabsichtigt. wenn die zeilen nicht gleich sind, soll er da ja auch nicht reingehen.
das problem ist eher, wenn er in den if-block wo er dann die dqs_line schreibt nicht reingehen soll, schreibt er dennoch die dqs_line in die ausgangsdatei.
Und das verstehe ich nicht *g*Da hab ich schon ewig rumgebastelt, weil die seite den etwas verzogen hat, weil er nicht in eine zeile passen wollte!!!
*unschuldig*
-
Nein, er schreibt nicht die dqs_line (schau mal genau hin). Aber wenn die Zeilen nicht zusammenpassen, fällt auch das Einlesen der dq_line aus, das heißt, daß du im nächsten Schleifendurchlauf die "übernächste Zeile" bekommst.
PS: Schonmal etwas von Debugging gehört? Schreib doch die eingelesenen Zeilen testweise nach stdout, bevor du sie verarbeitest.
-
ja aber das problem ist: sie steht drin. er soll ja wenn die nicht gleich sind die 2 zeilen einfach die stink normale inpline rausschreiben.
sinn des ganzen ist ja:
1x odd + 1x even zusammenfassen + wenn z.b. 1x odd + 4x even vorkommt muss der ausgang sein: die odd-zeile + die 3 ersten even-zeilen.
Wenn also die dqs_line nicht identisch ist mit der inpline, dann ist die dq_line für diese zeilenkombination unbrauchbar und gehört schon zur nächsten zeile.Ja ich hab breakpoints gesetzt.
da kommt aber eben nicht das raus an zeilen, was nach dem programm her herauskommen müsste.
-
Dein Programm fasst aber nicht die "odd"- und "even"-Zeilen zusammen. Der Zeilenanfang wird auch schon mit verglichen. Das bedeutet, bei der Folge oeeee läuft die Schleife so ab:
fgets(inpline) -> odd ->fgets(dqs_line) -> even1 ungleich -> Ende fgets(inpline) -> even2 ->fgets(dqs_line) -> even3 gleich ->fgets(dq_line) -> even4
Und effektiv wird die odd-Zeile im ersten Durchlauf und entweder even3 oder even4 im zweiten Durchlauf ausgegeben.
Also nochmal ganz von vorne: Was genau willst du nach welchen Kriterien zusammenfassen?
-
Okay, ich erklär es nochmal anders:
Eingangsdatei oben...
Ich untersuche am ende der while schleife (wo ich die inpline einlese) immer ob es eine odd oder eine even war. je nachdem setze ich mode auf 1 oder 2.
Dann liest die while die nächste zeile ein und stellt fest es ist z.b. eine even.
Dann macht er ja nur etwas wenn mode auf 2 ist (also die zeile davor eine odd war).
Also ist die inpline die erste even.
Er schreibt dann die ersten 40 zeichen der inpline in eine neue datei.
Dann soll er die nächste (dqs_line) einlesen und die mit der aktuellen inpline vergleichen und wenn die ersten 40 zeichen gleich sind weitermachen und die nächsten 4 zeichen hinten dran in die neue datei schreiben.
Sollte jetzt die nächste zeile (dq_line) gleich sein (die 44 zeichen) dann soll er den rest aus der dq_line dran hängen. wenn nicht gleich, soll er die dqs_line dran hängen.
und sollte allergdings gleich am anfang die dqs_line nicht mit der inpline übereinstimmen, dann einfach nur die inpline komplett rausschreiben.(ich hoffe die erklärung ist einigermaßen verständlich)
-
Ja, soweit komme ich mit - und was genau soll das Programm mit der dqs_line bzw. der dq_line machen, wenn sie nicht zu den gerade betrachteten Daten passen? Die Schleife dort oben verwirft sie einfach, so daß die jeweils erste "odd"- bzw. "even"-Zeile deiner Eingabedatei komplett unter den Tisch fällt.
(Korrektur: Und nebenbei unterscheiden sich die Eingabezeilen bereits an Position 20 voneinander, so daß du wohl nie in den Abschnitt "und die nächsten 4 Zeichen hinten dran ... schreiben" kommst)
-
Nein, wenn 4 even zeilen hintereinander kommen schauen die ersten 3 bis position 44 identisch aus.
wenn die dq_line, dqs_line nicht passen dann ignorieren (für die aktuelle zeile). Dann gehört sie zur nächsten zeile, die verarbeitet werden soll.Hier sieht man es besser...
Die interessante Zeile ist jeweils die 3.
Daher soll er immer die ersten xx zeichen vergleichen und dann eine zeile draus machen.
Eingangsdateieven WS_NN <101111100000000000000000ZZZZZZZZZZZZZZZZZZZZZZZ0100011> even WS_NN <101111100000000000000000HHLLZZZZZZZZZZZZZZZZZZZ0100011> even WS_NN <101111100000000000000000HHLLZZZLHLHLHLHLHLHLHLH0100011> odd <011111100000000000000000ZZZZZZZZZZZZZZZZZZZZZZZ0100011> odd <011111100000000000000000LLHHZZZZZZZZZZZZZZZZZZZ0100011> odd <011111100000000000000000LLHHZZZHLHLHLHLHLHLHLHL0100011> even WS_NN <101111100000000000000000ZZZZZZZZZZZZZZZZZZZZZZZ0100011> even WS_NN <101111100000000000000000HHLLZZZZZZZZZZZZZZZZZZZ0100011> even WS_NN <101111100000000000000000HHLLZZZLLHHLLHHLLHHLLHH0100011> odd <011111100000000000000000ZZZZZZZZZZZZZZZZZZZZZZZ0100011> odd <011111100000000000000000LLHHZZZZZZZZZZZZZZZZZZZ0100011> odd <011111100000000000000000LLHHZZZHHLLHHLLHHLLHHLL0100011>
-
manu1984 schrieb:
wenn die dq_line, dqs_line nicht passen dann ignorieren (für die aktuelle zeile). Dann gehört sie zur nächsten zeile, die verarbeitet werden soll.
Und da ist möglicherweise das Problem - du ignorierst diese Zeilen nicht nur für den aktuellen Durchlauf, sondern endgültig.
Hier sieht man es besser...
Die interessante Zeile ist jeweils die 3.Ich bin jetzt echt zu faul, die Zeichen auszufählen
Also könntest du bitte in Zukunft kennzeichnen, wo Position 41 bzw. 45 stehen?
-
ja das ist wahrscheinlich das problem. wie kriege ich es denn dann hin, dass er die zeilen nur für diesen durchlauf ignoriert???
sonst brauch ich die ja!!!tut mir leid.
zeile 41 - 45 sind die zeilen, wo immer 1100 - 0011 oder HHLL - LLHH steht.
davor kommen meistens nur 0er.
-
Du hast die nächste zu bearbeitende Zeile in dqs_line bzw. dq_line stehen, also müsstest du sie (anstelle des fgets()-Aufrufes) umkopieren nach inpline (stichwort strncpy()), bevor du wieder in die Schleife reinspringst.
-
das verstehe ich jetzt nicht so ganz.
ich muss die zeile doch einlesen. ich kann natürlich die zeile dqs_line umkopieren in inpline, aber dann liest er doch von der while-schleife, die um den ganzen spass ist wieder die nächste zeile ein, oder?
-
Du hast diese Zeile schon eingelesen, also mußt du sie nicht nochmal einlesen (wenn du unbedingt willst, müsstest du den Lesezeiger entsprechend zurückschieben). Und natürlich müsstest du auch die umliegende While-Schleife so anpassen, daß sie nicht nochmal einliest
-
ja aber das verstehe ich komplett nicht wie ich das machen soll.
mit rewind() kann ich einen zeiger doch zurück setzen, oder?aber wie soll ich die while-schleife anpassen?
mir ist schon klar, dass ich die nächsten 2 zeilen schon eingelesen habe, aber ich weiss nicht wie ich den zeiger auf die position der eigentlichen inpline setzen kann
-
Der direkte Weg:
fseek(fcache,-(strlen(dqs_line)+1),SEEK_CUR);
(die '+1' steht für das \r, das beim Einlesen unter den Tisch gefallen sein könnte - mußt du eventuell nachjustieren).Der bessere Weg: Du reduzierst die Schleifenbedingung auf
while(!feof(fcache))
und kopierst am Ende der Schleife den Inhalt von dqs_line bzw. dq_line nach inpline (je nachdem, welche Eingabezeile nicht mehr zum Vorgänger gepasst hat - wenn beide Zeilen korrekt waren, holst du die neue Anfangszeile per fgets()).
-
okay, also das mit fseek() verstehe ich, allerdings wenn ich das so eingebe läuft das programm nicht mehr durch sondern bleibt in der while-schleife stehen.
die andere lösung ist mir noch etwas unklar.
soweit ich es glaube zu verstehen:ich kopiere mir am ende der while-schleife die dqs_line nach inpline und
dq_line nach dqs_line. Dann komme ich allerdings mit meinen fgets() durcheinander, weil ich ja dann wieder 2 neue zeilen einlese.
Also habe ich dann auf einmal 4 zeilen.
Aber am anfang für den ersten schritt muss ich ja 3 zeilen einlesen um den vergleich zu machen ...
-
Jetzt hast du vermutlich zu viel kopiert.
Du hast drei mögliche (reguläre) Fälle (in der Reihenfolge, wie sie im Originalpost abgefangen werden):- dqs_line un dg_line passen zu inpline (Zeile 20/21):
Der nächste Block beginnt mit einer neuen Eingabezeile -> fgets(inpline,...) - dqs_line passt, dq_line ist falsch (Zeile 25/26):
dq_line ist der Anfang des nächsten Blocks -> strcpy(inpline,dq_line) - dqs_line ist falsch (Zeile 31-33):
dqs_line ist der Anfang des nächsten Blocks, dq_line wurde gar nicht eingelesen -> strcpy(inpline,dq_line)
- dqs_line un dg_line passen zu inpline (Zeile 20/21):
-
also ich hab die schleifen jetzt mal modifiziert, dann bleibt er auch in der while hängen.
aber dafür habe ich die lösung mit fseek() hinbekommen.
aber: rein logisch muss ich den zeiger ja dann 2 zeilen hochsetzen.
und 2 zeilen lässt er sich nicht zurücksetzen. dann bleibt er auch in der while hängen.while(!feof(fcache)) { if(mode == 0) fgets(inpline,MAXLENGTH,fcache); if(mode == 1 && strncmp(inpline,"odd <01",18)==0) { fprintf(fmake_list,"odd <"); for(i=17;i<41;++i) fprintf(fmake_list,"%c",inpline[i]); fgets(dqs_line, MAXLENGTH, fcache); fgets(dq_line, MAXLENGTH, fcache); if(strncmp(dqs_line,inpline,40)==0 && strncmp(dq_line,"even",4)!=0) { for(i=41;i<45;++i) fprintf(fmake_list,"%c",dqs_line[i]); if(strncmp(dqs_line,dq_line,44)==0) { for(i=45;inpline[i]!='\n';++i) fprintf(fmake_list,"%c",dq_line[i]); strcpy(inpline,dq_line); } else { for(i=45;inpline[i]!='\n';++i) fprintf(fmake_list,"%c",dqs_line[i]); strcpy(inpline,dqs_line); } fprintf(fmake_list,"\n"); } else { for(i=41;i<45;++i) fprintf(fmake_list,"%c",inpline[i]); for(i=45;inpline[i]!='\n';++i) fprintf(fmake_list,"%c",inpline[i]); fprintf(fmake_list,"\n"); mode = 0; }