need-some-blood Geschrieben 20. August 2003 Geschrieben 20. August 2003 Hey, ich habe gerade ein Programm erstell, indem eine CNF-Datei ausgelesen wird. In der CNF-Datei stehen verschiedene Werte in eckigen Klammern. // In etwa so wert1 = [123456] wert2 = [78945] wert3 = [123456789] Ich benötige NUR den Wert der Klammern und muss den als String vorliegen haben. Deshalb habe ich folgendes Programm geschrieben. ============================================================ #define T_BUFFER = 16000; static in a,b,d,e,zeichen, k_buffer[15]; static int t_buffer[T_BUFFER]; /* Datei einlesen und Größe der Datei in a speichern */ a=_dos_findfirst(dateipfad,_a_normal,&find); in=open(dateipfad,O_RDONLY|O_BINARY,S_IREAD); if (a||in==FILEERROR) { //Fehlermeldung, abbruch blabla. das übliche } else { a=(int)find.size; read(in,&t_buffer,a); close (in); /* ab jetzt wirds interresant */ for (b=0;b<a;b++){ if (t_buffer[b]=='['){ for (d=0;d<14;d++){ if (t_buffer[b+d]==']'){ datensatz++; zeichen=0; for (e=b+1;e<(b+(d-1)); e++){ k_buffer[zeichen]=t_buffer[e]; zeichen++; } for (e=zeichen;e<15;e++) k_buffer[e]=0; d=14; b++; switch (datensatz){ case 1: strcpy(struktur.wert1, k_buffer); case n: strcpy(struktur.wertn, k_buffer); } } } } } [/php] (Ich hoffe mal das ich das jetzt so richtig abgeschrieben habe.) Das ganze funzt auch prima. Aber gibt es da nicht ne elegantere Möglichkeit. Ich dachte schon an Zeilenweises einlesen der Datei und nach dem ersten aufkommen einer [ und einer ] suchen. Aber damit würde ich höchstens ein paar Zeilen sparen. Hat jemand nen besseren Vorschlag? MVG need-some-blood Zitieren
idefix Geschrieben 21. August 2003 Geschrieben 21. August 2003 Was heißt für dich eleganter? ein Problem wird wahrscheinlich sein, wenn das File größer als 16000 Byte ist. Warum schließt du das File und suchst im Speicherblock? Man könnte doch auch blockweise lesen (z.B. 512 Byte) und den File Pointer zum Werte auszulesen benutzen. Vielleicht ist es dann auch möglich die Schleifenschachtelung etwas zuminimieren. Ansonsten sehe ich kein Problem, es sei denn während des Parsens tretten Fehler auf oder die Syntax der CNF-Files variiert. Wenn, die Werte sich immer an der gleichen Stelle befinden könnte man doch über eine Offset-Parameter nachdenken. Zitieren
need-some-blood Geschrieben 21. August 2003 Autor Geschrieben 21. August 2003 Danke für die Antwort wenigstens einer. :uli Tja was heißt für mich eleganter? Also ich weiß zwar das das ganze Funzt. Aber ich bin damit nicht zufrieden. Das ganze muss doch wesentlich besser gehen. Aber ich beantworte dir erstmal deine Fragen. ein Problem wird wahrscheinlich sein, wenn das File größer als 16000 Byte ist. Sehr unwarscheinlich. Das ganze ist ne Konfigurationsfile, und da sind 16Kb schon verdammt viel. Und wenn es das ganz doch mal überschreitet, dann kann ich ja einfach die Konstante erhöhen. Warum schließt du das File und suchst im Speicherblock? Weil wir mit nem Multi-Tasking-System arbeiten. Ich lese damit zyklisch aus der Datei, und da ich nicht zehn mal die gleiche Datei geöffnet haben möchte, schließe ich sie wieder. Ausserdem habe ich mal gelernt, dass man keine Dateien offen liegen lässt. Ein Absturz und die Datei ist möglicherweise beschädigt. Man könnte doch auch blockweise lesen (z.B. 512 Byte) und den File Pointer zum Werte auszulesen benutzen. Vielleicht ist es dann auch möglich die Schleifenschachtelung etwas zuminimieren. a) siehe oben Wenn ich das täte müsste ich jedesmal überprüfen, ob ich die gleiche Anzahl von geöffneten und geschlossenen Klammer habe. Wenn nicht, dann müsste ich den nächsten Block in einen anderen Speicher lesen und den geteilten Datensatz wieder mühsam zusammenfügen. Ich weiß nicht ob dies nicht evtl sogar ein Mehraufwand wäre? Die Datensätze varieren (Länge, Größe, Inhalt) aber nicht die Bezeichnungen. Diese sind nur unterschiedlich lang. Ich hoffe mal dir deine Fragen beantwortet zu haben. Evtl kommen wir ja doch noch auf ein besseres Ergebniss. MVG need-some-blood Zitieren
idefix Geschrieben 21. August 2003 Geschrieben 21. August 2003 Klingt interessant. Mal seh'n wo die Reise hingeht. Also, mit schliessen meine ich nicht das File die ganze Zeit auf zulassen, sondern nur bis alle Werte ausgelesen sind. Wenn deine Routine in mehreren Threads aufgerufen wird, gibt's glaube ich Probleme mit static Buffer. Beispiel: char sBuffer[512]; char *p; FILE* pF; long n; long nPos; long nPosBracketOpen; long nPosBracketClose; char sWert[128]; pF=fopen(....); while(feof(pF)) { n=fread(sBuffer,sizeof(char),sizeof(sBuffer),pF); p=sBuffer; while((p-sBuffer)<=n) { //if( suchen==true) { nPos=fseek(pF,0,SEEK_CUR); fseek(pF,nPosBracketOpen+1,SEEK_SET); fread(sWert,sizeof(char),nPosBracketClosenPosBracketOpen,pF); fseek(pF,nPos,SEEK_SET); } } } fclose(pF); ich weiß geht alles auch mit std::ifstream (fopen,fseek,fclose ...) das geht nartürlich nur wenn sich die Datei nicht laufend ändert (jedenfalls weiß ich das nicht so genau) Was ich als Gedankenanstoß geben wollte ist, dass das Lesen der Werte im File geht und das Parsen im Buffer. Die Verbindung beider über File Position. Die Größe des Buffers klein gehalten werden kann. PS: Quellcode habe ich nicht aus probiert, kann sein das ich was vergessen habe Zitieren
idefix Geschrieben 22. August 2003 Geschrieben 22. August 2003 Vielleicht helfen dir Library's für das Parsen weiter: GRETA: http://research.microsoft.com/projects/greta/ BOOST: http://www.boost.org/ lex yacc: http://www.monmouth.com/~wstreett/lex-yacc/lex-yacc.html hier noch ein vergleich zwischen GRETA & BOOST (MS lastig) http://research.microsoft.com/projects/greta/regex_perf.html In der C-Library gibt es nartürlich auch fscanf und sscanf In der stl ist es dann ofstream mit dem operator >> und stringstream (bin mir aber nicht ganz sicher) Nun das sollte fürs Erste reichen. Die Library's wirken etwas übertrieben für eine solche "trivale" Aufgabe, aber prinzipiell anwendbar. Ich bin mir aber nicht sicher inwieweit diese Thread sicher sind. Würde mich ja interessieren was du nun gewählt hast und welche Erfahrung du gemacht hast. Oder war's nur ein Schuß ins Blaue? Zitieren
Empfohlene Beiträge
Dein Kommentar
Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.