Strings in der Datei ersetzen
-
Hallo Leute,
ich musste doch mein Problem in C lösen.
Ich habe mein Code nue geschrieben und möchte eure Kritik oder vielleicht am besten ein paar gute Tipps lesen. Falls ihr Zeit und Lust habt, dann bin ich sehr dankbar.
Also, aus diesem Datenstrom:
<old_tag nr="xxxx" length="yyyy"> data, data, data data, data, data data, data, data data, data, data </old_tag>
möchte ich das hier bekommen:
<new_tag n="xxxx" l="yyyy">data, data, data, data, data, data, data, data, data, data, data, data</new_tag>
Die Anfänger-Logik meines Programms liest die Daten zeilenweise aus und bearbeitet sie entsprechend meinen Vorstellungen so, dass die Daten zw. <new_tag...> und </new_tag> in einer Zeile stehen. Die Kommentare (# oder //) aus der Input-Datei werden übersprungen.
Das funktioniert soweit gut. Aber wenn die Input-Daten selbst in einer Zeile stehen:
<old_tag nr="xxxx" length="yyyy">data, data, data, data, data, data, data,data, data, data, data, data</old_tag>
dann
geht nichts mehr...
#define BUF_SIZE_S 128 #define BUF_SIZE_M 256 #define BUF_SIZE_L 512 #define BUF_SIZE_XL 1024 #define BUF_SIZE_XXL 10240 int main (char *pcInputXMLFile, char *pcOutputXMLFile) { if (pcInputXMLFile == NULL) exit(1); if (pcOutputXMLFile == NULL) exit(1); FILE *fpToInputFile = NULL; FILE *fpToOutputFile = NULL; fpToInputFile = fopen(pcInputXMLFile, "r"); fpToOutputFile = fopen(pcOutputXMLFile, "w+b"); if (fpToInputFile != NULL) { char *pcBuff; char *pcTmp; char *pcBuffTmp; char *pcComment[] = { "#", "//", NULL}; char pcOpenXMLTag[] = "<new_tag "; char pcOpenCFGTag[] = "<old_tag "; char pcCloseCFGTag[] = "</old_tag>"; char pcNr[] = "nr="; char pcN[] = "n="; char pcLength[] = "length="; char pcL[] = "l="; char *openXMLTagPos; char *attrFirstPos; char *attrSecondPos; int dataFlow = 0; int commentIndex = 0; NEW_READ: pcTmp = (char *)calloc(BUF_SIZE_XL,sizeof(char)); if (!pcTmp) exit(1); pcBuff = (char *)calloc(BUF_SIZE_XL,sizeof(char)); if (!pcBuff) exit(1); pcBuffTmp = (char *)calloc(BUF_SIZE_XL,sizeof(char)); if (!pcBuffTmp) exit(1); openXMLTagPos = (char *)calloc(BUF_SIZE_S,sizeof(char)); if (!openXMLTagPos) exit(1); attrFirstPos = (char *)calloc(BUF_SIZE_S,sizeof(char)); if (!attrFirstPos) exit(1); attrSecondPos = (char *)calloc(BUF_SIZE_S,sizeof(char)); if (!attrSecondPos) exit(1); while (!feof(fpToInputFile)){ fgets(pcTmp, BUF_SIZE_L, fpToInputFile); commentIndex = 0; while(pcComment[commentIndex] != NULL) { if ((strstr(pcTmp, pcComment[commentIndex])) != NULL) { goto NEW_READ; } commentIndex++; } if ((openXMLTagPos = strstr(pcTmp, pcOpenXMLTag)) != NULL) { strcpy(pcBuff, pcOpenCFGTag); attrFirstPos = strstr(pcTmp, pcNr); attrSecondPos = strstr(pcTmp, pcLength); if (attrFirstPos != NULL) { strcat(pcBuff, pcN); int lenFirstAttr = (strlen(strstr(pcTmp, "\""))) - (strlen(strstr(attrSecondPos, pcLength))); if ((strstr(pcTmp, "\"")) != NULL) { strncat(pcBuff, (strstr(pcTmp, "\"")), lenFirstAttr); } } if (attrSecondPos != NULL) { strcat(pcBuff, pcL); int lenSecondAttr = (strlen(strstr(attrSecondPos, "\""))) - (strlen(strstr(attrSecondPos, ">"))); if ((strstr(attrSecondPos, "\"")) != NULL) { strncat(pcBuff, (strstr(attrSecondPos, "\"")), lenSecondAttr+1); } else { printf("\"-not found!\n"); return 1; } } dataFlow++; openXMLTagPos = NULL; if (fpToOutputFile != NULL) fwrite(pcBuff, strlen(pcBuff), 1, fpToOutputFile); goto NEW_READ; } if (dataFlow == 1) { unsigned m = 0; unsigned n = 0; for(; m < strlen(pcTmp); m++){ if (*(pcTmp+m)!='\n' && *(pcTmp+m)!='\r' && *(pcTmp+m)!='\t' && *(pcTmp+m)!='\b' && *(pcTmp+m)!='\v' && *(pcTmp+m)!=' '){ if (*(pcTmp+m)=='<'){ sprintf(pcBuff, "%s\n", pcCloseCFGTag); m = strlen(pcTmp); dataFlow = 0; } else { sprintf(&pcBuff[n], "%c", *(pcTmp+m)); n++; } } } if (fpToOutputFile != NULL) fwrite(pcBuff, strlen(pcBuff), 1, fpToOutputFile); } } if (pcBuff) free(pcBuff); if (pcTmp) free(pcTmp); if (openXMLTagPos) free(openXMLTagPos); if (attrFirstPos) free(attrFirstPos); if (attrSecondPos) free(attrSecondPos); } else { return 1; } if (fpToInputFile != NULL) fclose(fpToInputFile); if (fpToOutputFile != NULL) fclose(fpToOutputFile); return 0; }
Danke.
-
du willst das zum baum parsen, den baum manipulieren, den baum dumpen/serialisieren.
-
c.rackwitz schrieb:
du willst das zum baum parsen, den baum manipulieren, den baum dumpen/serialisieren.
Leider verstehe ich dich nicht. Ich will wie du es schreibst manipulieren. D.h. die Strings in der XML-Datei umschreiben.
-
dazu musst du aus dem dateiinhalt, naemlich einem langen string, eine baumstruktur machen, die du dann veraendern kannst.
c kann nicht jeder und wenn du noch nie programmiert hast, ist c eine denkbar schlechte wahl fuer schnellschuesse.
mensch, machs mit ner scriptsprache, dann waerst du laengst fertig.
-
c.rackwitz schrieb:
eine baumstruktur machen
Könntest du mir bitte ein paar Links oder Beispiele geben?
Danke
-
Was c.rackwitz meint, wenn ich ihn richtig verstehe, ist dass du dass ganze mit Tokenverarbeitung machen sollst. Aus diesen Token baust du dir dann einen Baum.
So etwa in der Art:
-<old_tag> --nr ---XXXX --length ---YYYY ----data ----data ----data -</old_tag>
Die einzelnen Token veränderst du dann und schreibst Sie wie du sie brauchst in die Datei zurück.
Hat den Vorteil, dass beim Parsen (wenn man es richtig anfängt) die Daten kommen können wie sie wollen.
Grüsse
Tobi
-
von tokenisieren halte ich garnichts. mit ner gescheiten parserimplementation kann man ein PEG fast 1:1 uebernehmen und damit baeume machen.
aber wie ich bereits sagte: nimm ne scriptsprache! dann kommst du wenigstens vom fleck. wenn du noch nie nen baum oder ne verkettete liste in c implementiert hast... nun ja, wenn du denkst, baeume sind schwer, dann wird parserbau fuer dich schwarze magie sein (wird ja leider erst im studium durchgenommen).
fuer python z.b. gibts beautifulsoup. damit kannst du noch so kaputtes html lesen und manipulieren.
du kannst natuerlich auch einen ganz winzigen parser bauen, der nur zwischen tags und text unterscheidet. den benutzt du dann zum "sauber formatieren" des html codes.
einen zweiten parser kannst du dann so einhaengen, dass der fuer jeden gefundenen tag (ne sache in spitzen klammern) aufgerufen wird. der kann sich dann an die zerlegung des tags machen und den tag neu schreiben.bei der ganzen arbeit sollte dir klar sein, dass du VIEL malloc() und free() brauchen kannst. also pass bloss auf, dass du auch alles immer genau einmal freigibst.
-
c.rackwitz schrieb:
bei der ganzen arbeit sollte dir klar sein, dass du VIEL malloc() und free() brauchen kannst. also pass bloss auf, dass du auch alles immer genau einmal freigibst.
Wenn ich dich richtig verstehe, bin ich dann falsch mit meinem 1.Aufruf (Zeile Nr. 80) von:
goto NEW_READ;
-
falsch... aehm ja, sehr falsch. alloziierten speicher MUSST du freigeben. machst dus nicht, beissts dir irgendwann in den arsch.
ich hab nen parser in einer sprache geschrieben, da gibts keine gotos.dazu kommt, dass du deinen ganzen code in die main() gepackt hast.
aus deinem code kann ich nicht viel machen. dein ganzer ansatz ist ne einbahnstrasse.
*sigh* ich hab jetzt eigentlich weder die lust, deinen code zu begreifen, noch dir den parser zu schreiben.
aber welche wahl hab ich denn schon? dir ein buch ueber parser um die ohren zu hauen oder dir etwas von meiner zeit zu geben.scripte dir das doch einfach. C kannst du auch anders lernen.
-
c.rackwitz schrieb:
falsch... aehm ja, sehr falsch. alloziierten speicher MUSST du freigeben. machst dus nicht, beissts dir irgendwann in den *****.
Du hast recht.
c.rackwitz schrieb:
dazu kommt, dass du deinen ganzen code in die main() gepackt hast.
Das ist eine Testversion, deshlab in main.
c.rackwitz schrieb:
aber welche wahl hab ich denn schon? dir ein buch ueber parser um die ohren zu hauen.... C kannst du auch anders lernen.
Danke, danke.
Kann ich und das ist der richtige Zeitpunkt.
-
shuriko schrieb:
Das ist eine Testversion, deshlab in main.
funktionen sind nicht zur lesbarkeit erfunden worden. funktionen brauchst du z.b. fuer rekursion, funktionelle programmierung, wartungsersparnisse (redundanz ist dein feind, du willst jeden code nur einmal, naemlich in einer funktion).
"ist ja ein prototyp" kannst du da nicht sagen