einzelnen buchstaben an einen string anhängen



  • Daniel E. schrieb:

    Richtig, das ist in C nicht ganz einfach. Als erstes mußt Du genug Speicher bereitstellen (malloc) und dann kannst Du strcat verwenden.

    ...damit hab ich's schon probiert, aber strcat(mystring,c) funzt nicht, weil der compiler meckert...und mit nem typecast wie strcat(mystring,(char 😉 c); kam ich auch nicht weiter...

    gibt's keine einfache möglichkeit, aus dem einzel-char einen string zu machen? ne konvertier-funktion sozusagen !? weil strcat ja eigentlich zwei char* erwartet...



  • KC schrieb:

    gibt's keine einfache möglichkeit, aus dem einzel-char einen string zu machen? ne konvertier-funktion sozusagen !? weil strcat ja eigentlich zwei char* erwartet...

    die einfachste wäre memcpy

    char text[100];
    int c = 'K';
    
    strcpy(text, "abc");
    /* da ich weiß, dass text 99-Zeichen lange Strings speichern kann
       und "abc" nur 3 lang ist, brauch ich mich jetzt um den Speicher
       keine Sorgen zu machen */
    
    memcpy(text + strlen(text), &c, 1);
    text[4] = 0; /* das \0 neu setzten nicht vergessen ! */
    

    [schamlose Werbung] 😃
    Wenn du noch nicht richtig mit den Strings in C umgehen kannst, könntest du einen Blick auf http://klingsor.informatik.uni-freiburg.de/projects/sstrings/index.php werfen, das ist eine kleine Bibliothek, die ich geschrieben habe, um C Anfänger bzw. C-Strings unerfahrene Leute zu unterstützen.
    [/schamlose Werbung]





  • ich hab mich mal bissel hingesetzt und rumprobiert...so richt gut sieht's noch nicht aus, aber es tut was es (aus meiner sicht) soll...ein einzelner character aus einem file-stream wird an ein bestehendes wort angehängt...speicher hole ich über realloc immer wieder neu (das dürfte in etwa der idee von daniel entsprechen).
    mit nem typecast klappt's also auch mit einzelnen chars...naja...kennt man aus anderen sprachen bequemer 😉

    hier noch der code, falls es jemanden interessiert, vorschläge zur verbesserung sind natürlich gerne gelesen...

    fp=fopen("c:/myfile2.txt","r");
    
    int stream_char; //a single char of the file-stream
    char* temp_word; //the word to add the single chars to
    
    int malloc_counter=1; //counter for each incomming char
    temp_word=malloc(sizeof(char)*malloc_counter); //allocate first memory
    strcpy(temp_word,""); //'initialize' the temp_word
    
    printf("\n initial temp_word: %s", temp_word);
    
    while ((stream_char = fgetc(fp)) != EOF) //read single chars of file until EOF
    {
        if(stream_char!=' ') //ignore whitespaces (just as an example)
        {
            malloc_counter++; //count up for every incomming char
    
            realloc(temp_word,sizeof(char)*malloc_counter); //increment memory
    
            strcat(temp_word,(char *)&stream_char); //concat old word and new char
        }
    }
    
    printf("\n final temp_word: %s", temp_word);
    


  • hmm...bei großen dateien=vielen chars gibt's offensichtlich ein speicherproblem...
    ich hab die realloc-stelle geändert in

    realloc(temp_word,sizeof(temp_word)+sizeof(char));
    

    (ist denke ich mal sinnvoller), trotzdem gibt's speicherprobleme...*wunder*



  • Du hast vermutlich ein Problem mit der Null-Terminierung. Die String-Funktionen erwarten, daß am Ende ihrer Eingabefolgen ein \0 steht ´- und das trifft bei einem einzeln stehenden char nicht zu.

    Aber anstelle des strcat() kannst du die neuen Zeichen direkt per Zuweisung einfügen:

    while ((stream_char = fgetc(fp)) != EOF) //read single chars of file until EOF
    {
        if(stream_char!=' ') //ignore whitespaces (just as an example)
        {
            malloc_counter++; //count up for every incomming char
    
            realloc(temp_word,sizeof(char)*malloc_counter); //increment memory
    
            temp_word[malloc_counter-2]=stream_char; //concat old word and new char
        }
    }
    temp_word[malloc_counter-1]='\0';//Stringende-Marke anhängen
    

    PS: sizeof(char)==1 und sizeof(temp_word) ist auch während des gesamten Programms konstant (idR 4).



  • KC schrieb:

    realloc(temp_word,sizeof(char)*malloc_counter); //increment memory
    

    kannste dir nicht die vielen 'reallocs' sparen?
    die grösse der datei kannste doch vorher ermitteln
    mach nach dem öffnen der datei das:

    // get the file size
       size_t size;
       fseek (fp, 0, SEEK_END);  // ans ende
       size = ftell (fp);        // wo bin ich?
       fseek (fp, 0, SEEK_SET);  // wieder zurueck
    

    :xmas2:



  • danke für deine antwort cstoll, der hinweis mit \0 und der direkten zuweisung war hilfreich *gemerkt*

    ich habe den code wie folgt geändert:

    FILE* fp;
    fp=fopen("c:/myfile2.txt","r");
    
    int stream_char; //a single char of the file-stream
    char* temp_word; //the word to add the single chars to
    
    int malloc_counter=1; //counter for each incomming char
    //temp_word=(char*)malloc(sizeof(int)*malloc_counter); //funktioniert nicht
    temp_word=(char*)malloc(sizeof(int)*5000); //funktioniert
    
    strcpy(temp_word,""); //'initialize' the temp_word
    
    printf("\n initial temp_word: %s", temp_word);
    
    while ((stream_char = fgetc(fp)) != EOF) //read single chars of file until EOF
    {
        if(stream_char!="") //ignore whitespaces (just as an example)
        {
            malloc_counter++; //count up for every incomming char
    
            realloc(temp_word,sizeof(char)*malloc_counter); //increment memory
    
            temp_word[malloc_counter-2]=stream_char; //concat old word and new char
        }
    }
    temp_word[malloc_counter-1]='\0';//Stringende-Marke anhängen
    
    printf("\n final temp_word:\n%s", temp_word);
    printf("\n StrLen: %d", strlen(temp_word));
    
    printf("\n");
    

    das file welches ich zu testzwecken einlese ist 5952byte groß. durch das "parsen" in meiner funktion bleiben nach abzug der "CRLF" noch 5760byte, was soweit ja richtig ist (ich habe 192 zeilen). soweit, so gut ... dank deiner hilfe steht soweit erstmal alles korrekt dort, allerdings kann ich den speicher noch immer nicht dynamisch allozieren. wie im code zu sehen, funktioniert die erste (auskommentierte) variante nicht...das programm arbeit nur fehlerfrei wenn ich viel speicher von vornherein bereitstelle, aber das hat ja mit dynamisch nichts mehr zu tun...ich hatte auch schon probiert:

    realloc(temp_word,strlen(temp_word)+(sizeof(int))); //size up memory
    

    , (weil die chars ja eigentlich int-werte sind (??)) bzw.

    realloc(temp_word,strlen(temp_word)+(sizeof(char))); //size up memory
    

    resultat: auch keine verbesserung...ich würde gerne verstehen wo der fehler liegt, dass die dynamische erweiterung von temp_word noch nicht funktioniert...

    beste grüße, KC



  • ten schrieb:

    KC schrieb:

    realloc(temp_word,sizeof(char)*malloc_counter); //increment memory
    

    kannste dir nicht die vielen 'reallocs' sparen?
    die grösse der datei kannste doch vorher ermitteln
    mach nach dem öffnen der datei das:

    // get the file size
       size_t size;
       fseek (fp, 0, SEEK_END);  // ans ende
       size = ftell (fp);        // wo bin ich?
       fseek (fp, 0, SEEK_SET);  // wieder zurueck
    

    :xmas2:

    gute idee, danke dafür...
    allerdings: wenn ich den code abändere und nur bestimmte teile der datei parsen wollen würde, oder ein abbruchkriterium während des parsens hätte, wäre der restliche speicher ja umsonst alloziert worden !?



  • KC schrieb:

    allerdings: wenn ich den code abändere und nur bestimmte teile der datei parsen wollen würde, oder ein abbruchkriterium während des parsens hätte, wäre der restliche speicher ja umsonst alloziert worden !?

    naja, wenn das ein problem ist, dann musste zweimal parsen. beim ersten mal die länge ermitteln und beim zweiten mal einlesen...



  • hmm, ich weiß nicht, ob ich dich da jetzt richtig verstehe...du würdest also das erste mal durch das file gehen um zu "errechnen" wieviele bytes ich brauche, und danach diesen speicher allozieren, und anschließend die entsprechenden bytes auslesen? *kopfkratz* denn die größe der gesamten datei kenne ich ja dank deines code-schnibbsels nun schon...



  • KC schrieb:

    hmm, ich weiß nicht, ob ich dich da jetzt richtig verstehe...du würdest also das erste mal durch das file gehen um zu "errechnen" wieviele bytes ich brauche, und danach diesen speicher allozieren, und anschließend die entsprechenden bytes auslesen?

    richtig, aber nur wenn der aufruf von malloc mit der gesamten dateigrösse aus irgendwelchen gründen ein echtes problem wird (weil die datei riesengross ist ect.).
    :xmas2:



  • ok, dann habe ich dich doch richtig verstanden...
    ich gehe zb mal von einem extrem-fall aus, dass das file 1mb oder 5mb groß ist, ich aber vielleicht nur wenige bytes extrahieren will, die wohlmöglich noch verstreut liegen...daher war meine idee halt, dass ich einfach immer nur dann speicher dazuhole, wenn mein parser was gefunden hat. und ich hätte nur einen durchlauf gehabt. letztendlich hat ja deine variante (so gut sie bei mir jetzt auch funktioniert) ja leider auch wieder diesen statischen charakter, wenn auch zumindest an das file angepasst...



  • Immer um ein Zeichen reallocen ist Schwachsinn. Merk dir die Größe des Buffers, wenn der Buffer voll ist verdoppelst seine Größe mit realloc.



  • TactX schrieb:

    Merk dir die Größe des Buffers, wenn der Buffer voll ist verdoppelst seine Größe mit realloc.

    wird ja oft so gemacht, aber stell dir vor du hast 200000 bytes im buffer, der buffer ist voll, er wird auf 400000 erhöht und dann kommt aber nur noch 1 byte 😃



  • Manchmal will ich dich einfach nur hauen 😉



  • naja, letztendlich scheint es am realloc zu scheitern, egal wann und um wieviel ich versuche temp_word zu "vergrößern"... 😕

    ich initialisiere mit:

    temp_word=(char*)malloc(mybuffer);
    

    und wenn es soweit ist versuche ich nachzuallozieren:

    realloc(temp_word,mybuffer*2);
    

    aber dann schmiert das programm mit ner fehlermeldung ab.



  • Hier wird realloc auch falsch benutzt bzw. kann es zu bösen Überraschungen führen wie segmentation fault. Realloc sollte man so benutzen

    int groesse = ...;
    char *buffer, *tmp;
    
    buffer = malloc(groesse);
    
    /* ganz wichtig, sonst knallt's */
    if(!buffer)
      /* Fehlerbehandlung, Abbrechen, was auch immer */
    
    ...
    
    /* da wir mit char Arbeiten, brauchen wir das ganze
       sizeof(char) gar nicht, weil sizeof(char) immer 1 ist */
    tmp = realloc(buffer, groesse + new_size);
    
    if(!tmp)
      /* realloc Fehler, Speichergröße kann nicht verändert werden!,
         Abbrechen */
    
    buffer = tmp;
    
    /* ab hier ist es sicher auf buffer zuzugreifen */
    


  • aaaaah, ok, jetzt klappt's endlich, danke sehr 🙂


Anmelden zum Antworten