Strings in der Datei ersetzen



  • Auch gut! 😃

    char *buff = (char *)malloc(GetFileSize(deinFilePointer)*sizeof(char));
    


  • Also mir gefällt

    char *buff = malloc(GetFileSize(deinFilePointer));
    

    wesentlich besser. Dazu sollte man aber auch einen C-Compiler benutzen, keinen C++-Compiler.



  • Javaner schrieb:

    Auch gut! 😃

    char *buff = (char *)malloc(GetFileSize(deinFilePointer)*sizeof(char));
    

    Danke. Es tut was. 😉

    Aber mein Problem bleibt noch immer. Ich kapiere es einfach nicht, wie ich "jpg" durch "jpeg" ersetzen kann. Die Anleitung, die ich bereits bekommen habe ist zwar logisch aber nicht für einen Anfänger.

    Ich weiß nicht mit welchen Funktionen unter C es zu realisiren ist aber die Lösung für mich wäre:

    Datei zum Lesen öffnen.
    Zeile für Zeile auslesen.
    Nach einem String in der Zeile suchen.
    Wenn das String gefunden wird, dann ersetzen (durch überschreiben wahrscheinlich).
    Weiter suchen bis die Datei zu Ende ist.
    Datei schließen.



  • Meine Variante ist aber sauberer! 🕶



  • Datei 1 zum Lesen öffnen.
    Datei 2 zum Schreiben öffnen.
    Zeile für Zeile auslesen.
    Nach einem String in der Zeile suchen.
    Solange der String gefunden wird, ersetzen
    Zeile in die neue Datei schreiben
    Weiter suchen bis die Datei zu Ende ist.
    Datei 1 schließen.
    Datei 2 schließen.
    Datei 1 löschen.
    Datei 2 in Datei 1 umbenennen.



  • Javaner schrieb:

    Solange der String gefunden wird, ersetzen
    Zeile in die neue Datei schreiben

    Ersetzen wahrscheinlich Zeichen für Zeichen? Die Funktion strstr findet zwar die Anfangstelle des gesuchten String aber dann?.. was mache ich dann?



  • shuriko schrieb:

    Ersetzen wahrscheinlich Zeichen für Zeichen?

    Das ist in C (im Vergleich zu Java) schon ziemlich friemelig. Deshalb
    habe ich mich davor auch gedrückt! :p
    Anstatt einen neuen String zusammen zu basteln, schreibe die Teilergebnisse
    sofort raus. In etwa so:

    const char *p = zeile;
    const char *q;
    
    while (p && (q=strstr(p, "jpg")) != NULL) {
      // Ausgabe der Zeichen von p bis ausschließlich q
      // Ausgabe des Strings "jpeg"
      p = q+3;
    }
    


  • Javaner schrieb:

    Meine Variante ist aber sauberer! 🕶

    😮



  • Javaner schrieb:

    shuriko schrieb:

    Ersetzen wahrscheinlich Zeichen für Zeichen?

    Das ist in C (im Vergleich zu Java) schon ziemlich friemelig. Deshalb
    habe ich mich davor auch gedrückt! :p
    Anstatt einen neuen String zusammen zu basteln, schreibe die Teilergebnisse
    sofort raus. In etwa so:

    const char *p = zeile;
    const char *q;
    
    while (p && (q=strstr(p, "jpg")) != NULL) {
      // Ausgabe der Zeichen von p bis ausschließlich q
      // Ausgabe des Strings "jpeg"
      p = q+3;
    }
    

    Laut dem Beispiel müsste das hier auch laufen:

    int main (int argc, char *argv[]) {
    
        if(argc < 3){
    
            exit(1);
    
        }
    
        FILE *fpToInputFile;
        FILE *fpToOutputFile;
    
        char *pcCpy;
        char *pcTmp;
    
        fpToInputFile = fopen(argv[1], "r");
        fpToOutputFile = fopen(argv[2], "w+a");
    
        size_t size = GetFileSize(fpToInputFile);
    
        pcTmp = (char *)malloc(size);
        pcCpy = (char *)malloc(size);
    
        char pcNr[] = "jpg";
    
        if (fpToInputFile != NULL) {
    
            while (!feof(fpToInputFile)){
    
                fgets(pcTmp, size, fpToInputFile);
    
                pcCpy = strstr(pcTmp, pcNr);
    
                pcTmp = pcCpy+3;
    
                printf("TEST: %s\n", pcTmp);
    
            }
    
        }
    
        if (fpToInputFile != NULL) fclose(fpToInputFile);
        if (fpToOutputFile != NULL) fclose(fpToOutputFile);
    
        free(pcTmp);
        free(pcCpy);
    
        return 0;
    
    }
    

    ???



  • Nein! 😮

    while (!feof(fpToInputFile)) { 
      fgets(pcTmp, size, fpToInputFile); 
      pcCpy = strstr(pcTmp, pcNr);
      pcTmp = pcCpy+3; 
    
      Hier setzt du pcTmp auf das erste Vorkommen von "jpg" und machst
      dann gar nichts damit. Außerdem verlierst du den originalen Wert
      von pcTmp sodaß du schließlich den Speicher nicht mehr freigeben kannst.
      Und danach liest du gleich eine weitere Zeile ein.
    }
    

    Bau doch am besten meinen Codeausschnitt in deinen ein.



  • Javaner schrieb:

    Bau doch am besten meinen Codeausschnitt in deinen ein.

    jpg->jpeg? 😞



  • Schade... es ist alles zu eckig... 😞

    Ich werde wohl meine Daten mit sed oder mit perl parsen.



  • 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;
    

Anmelden zum Antworten