string mit readline einlesen



  • Hallo Forum,

    ich bin dabei mich mit C zu beschätigen.

    Ich möchte nun eine kleines Programm schreiben, welches einen String entgegen nimmt, den Nutzer fragt ob der von ihm eingebene Strnig korrekt ist, und wenn nicht erneut nach dem String fragt.

    Dazu folgendes:

    int getBoxId(char *box_id) {
    
        char *confirm;
    
        while(confirm[0] != 'j' && confirm[0] != 'J') {
            box_id = readline("\nBitte Seriennummer angeben:\n");
    
            printf("Seriennummer >> %s << korrekt?", box_id);
            input = readline(" [J/n]\n");
        }
    
        return 1;
    }
    

    Aufrufen tue ich die Funktion wie folgt:

    char *box_id = (char*) malloc(BOX_ID_LENGTH);
    
    getBoxId(box_id);
    

    Ich scheine nun aber irgendwas mit den Pointern falsch verstanden zu haben.

    Der printf() Aufruf innerhalb der Funktion getBoxId() gibt die richtige Seriennummer aus.

    Versuche ich aber nach dem Aufruf von getBoxId(box_id) box id auszugeben, kommt da nichts.

    Was mache ich verkehrt?

    Lg
    MasseElch



  • Fangen wir mal mit dem Einfachsten an: readline gibt's ned.
    Durch welche Geisterhand sich confirm füllen soll, bleibt auch Dein Geheimnis.

    In anderen Worten: Das compiliert nie und nimmer und da nehmen die meisten an, daß sie veralbert werden sollen.

    Meine, den Fünfzeiler kriegt man schon hier am Board komplett unter und wenn er dann noch nicht tut, hilft jemand.



  • GNU readline malloc'd einen char* , den Du nach Gebrauch wieder freigeben musst.
    von daher brauchst Du überhaupt kein malloc() , sondern nur ein free() .
    Insbesondere, wenn der User seine Eingabe berichtigen will, musst Du den alten string wieder deallozieren.

    Ausserdem willst Du ja, dass box_id im Anschluß auf den String zeigt. D.h. Du musst box_id per Referenz übergeben:
    void getBoxId(char **box_id);
    oder Du "returnst" das schlußendliche Ergebnis von readline():
    char *getBoxId(void);

    In Z. 5 deallozierst Du übrigens gleich mal den Zeiger confirm , der gar nicht initialisiert ist...



  • Furble Wurble schrieb:

    In Z. 5 deallozierst Du übrigens gleich mal den Zeiger confirm , der gar nicht initialisiert ist...

    s/deallozierst/dereferenzierst/



  • Danke! Mit euren (teilweise sehr freundlich 😮 ausgedrückten) Hinweisen:

    int getBoxId(char **box_id) {
    
        char *confirm = (char*) malloc(1);
    
        while(confirm[0] != 'j') {
            free(*box_id);
            free(confirm);
            *box_id = readline("\nBitte Serien-Nummer der Box angeben:\n");
    
            printf("Seriennummer >> %s << korrekt?", *box_id);
            confirm = readline(" [j/n]\n");
        }
    
        return 1;
    }
    
    int main() {
    
        [...]
    
        //Speicher für Serien-Nummer
        char *box_id;
    
        getBoxId(&box_id);
    
        printf("\nNutze Seriennummer %s", box_id);
    
        [...]
    
    }
    


  • Da fehlt was:

    Es funktioniert jetzt. Vielen Dank für die Hinweise.

    Ist der Code an sich denn so "vernünftig"?

    Ich weiß nicht so recht ob das mit dem malloc bei initialisiren richtig ist.

    MasseElch



  • MasseElch schrieb:

    int getBoxId(char **box_id) {
     
        char *confirm = (char*) malloc(1);
     
        while(confirm[0] != 'j') {
            free(*box_id);
            free(confirm);
            *box_id = readline("\nBitte Serien-Nummer der Box angeben:\n");
     
            printf("Seriennummer >> %s << korrekt?", *box_id);
            confirm = readline(" [j/n]\n");
        }
     
        return 1;
    }
     
    int main() {
     
        [...]
     
        //Speicher für Serien-Nummer
        char *box_id;
     
        getBoxId(&box_id);
     
        printf("\nNutze Seriennummer %s", box_id);
     
        [...]
     
    }
    

    Ja. Das geht doch schon in die richtige Richtung.
    Der Wert von von confirm[0] in Z. 5 ist nicht definiert. Gleiches gilt für *box_id in Z. 6 - auf keinen Fall darfst Du so free() auf *box_id aufrufen - das ließe sich allerdings Durch ein char* box_id=NULL; in Z. 22 kitten. free() auf einen NULL-Zeiger ist eine no-op.

    Am Ende von getBoxId() musst Du aufjedenfall den confirm-String noch freigeben. (s.u.)

    Ich kann mir vorstellen, dass Du mit ein wenig Logik und Umstellungen das ganze gut hinbekommst - auch ohne das dummy malloc() von confirm .

    Evtl. hilft es auch die ja/nein frage in eine extra Funktion auszulagern á la
    bool again(); // readline(), freigeben, true oder false zurueckgeben .



  • Erst Mal vielen Dank für die ganze Hilfe 🙂

    Folgendes habe ich nun gebastelt:

    int getBoxId(char **box_id) {
    
        char *confirm;
        int ret = 0;
    
        *box_id = readline("Bitte Serien-Nummer der Box eingeben:\n");
    
        printf("Serien-Nummer >> %s << korrekt?", *box_id);
        confirm = readline(" [j/n]\n");
    
        ret = confirm[0] != 'j';
    
        free(confirm);
    
        return ret;
    }
    
    int main() {
    
        [...]
    
        //Speicher für Serien-Nummer
        char *box_id;
    
        while(getBoxId(&box_id));
    
        printf("\nNutze Seriennummer >> %s <<\n\n", box_id);
    
        [...]
    
        free(box_id);
        return 0;
    
    }
    

    Jetzt wird jedes Mal nach dem confirm der SPeicher wieder freigegeben, genauso auch am Ende, bevor das Programm terminiert der Speicher von box_id.
    So korrekt?

    Kann man das mit dem while so machen? Oder ist sowas auch nicht den Konventionen entsprechend oder Ähnliches?

    MasseElch



  • Aber wenn ich mich jetzt versehe bei der Eingabe wird der alte box_id string nie freigegeben, oder?

    Und zu allem Überfluß kann readline() auch noch NULL zurückgeben...

    Eine Menge Stolperfallen.
    Aber letztlich ein Logikproblem und Du bist ja schon auf dem richtigen Weg...



  • OK, wußte nicht, daß das hier das GNU-Libs- Forum ist. Bitte sowas in einem Kommentar vermerken oder den inlude hinschreiben. Oder beides.

    Noch 'ne Unschönheit: malloc() bitte nicht typisieren, das ist ganz schnöde eine Startadresse auf ein Stückchen reservierten Speichers, sofern nicht NULL. Die Typisierung erfolgt durch die Speicherung auf den Pointer.


Anmelden zum Antworten