Benötige Erklärung für char me [20]; --- Anfängerprobleme ---



  • Hi!

    #include <stdio.h>
    
    int main(void)
    
    {
       char me[20];
       printf("Wie heissen sie?");
       scanf("%s", me);
       printf("Hallo %s, nett, sie kennenzulernen!", me);
    
       return 0;
    }
    

    In meinem Buch steht, dass es 20 Zeichen Speicherplatz organisieren muss.
    "Sie können also Text mit maximal 20 Zeichen Länge in "me" speichern.

    Ich gab mehr als 20 Zeichen ein z.B. meinen Namen komplett in die Länge gezogen (über 20 Zeichen) und es passierte nichts, jedoch wenn es wirklich übertrieben viel war, schloss sich das Programm.

    Dann versuchte ich es mit char me [1]; ... da passten auch so einige Wörter.

    Meine andere Frage wäre: Wie hoch darf die Zahl in der eckigen Klammer sein?
    Es ging auch über 127... obwohl in meinem Buch steht von -128 bis 127. (stand nicht im Text bis jetzt, aber auf der ersten Seite für nummerische Datentypen). Jedoch funktionierte es nicht mit null, logischerweise. Wofür ist das eigtl.?

    Ach ja, nett wäre es, wenn mir jemand erklärt wofür scanf("%s", me) ist und was es wirklich exakt macht. Mein Buch erklärt es mir ein wenig zu verwirrend.

    Tut mir leid für all diese Anfängerfragen, aber ich möchte es unbedingt lernen.



  • scanf("%s",me) liest in erster Linie deine Eingabe in der Konsole als String deswegen "%s". "%d" wäre z.B. ein integer, "%f" eine Gleitkommazahl usw...
    Doch Vorsicht: scanf("%s",me) liest nur das ERSTE Wort dass du geschrieben hast. Falls du fgets() schon kennst, benutze diesen Befehl, der liest alles ein bis du enter drückst.
    scnaf(2%s",me) liest einfach deine Eingabe in den String me ein, mehr nicht.



  • Vielen Dank! Jetzt habe ich es verstanden.



  • Ich gab mehr als 20 Zeichen ein z.B. meinen Namen komplett in die Länge gezogen (über 20 Zeichen) und es passierte nichts, jedoch wenn es wirklich übertrieben viel war, schloss sich das Programm.

    dann überschreibst du irgendwelchen Speicher und bekommst undefiniertest Verhalten - aka Random-Absturz-Generator



  • Dein Buch ist Schrott.
    TocToc auch keine Ahnung, weil er wie üblich Unsinn erzählt.

    Die einzig korrekte Lösung wäre

    char me[20]; /* Definition von Speicherplatz für einen max. 19 Zeichen langen C-String */
       printf("Wie heissen sie?");
       scanf("%19[^\n]", me); /* liest max. 19 Zeichen, '\0' wird immer angehängt */
       while( getchar()!='\n' ); /* leert alle nicht gelesenen Zeichen inkl. des bei scanf immer terminierenden vorhandenen '\n' aus stdin, damit folgende stdin-Operationen keinen Schaden nehmen */
    

    Beachte die while-Schleife danach, die wird von 99% aller Tutorials/Bücher und 100% aller Anfänger hier im Forum ignoriert.



  • Zuviele Informationen aufeinmal. 😕 Ich kenne diese ganzen Befehle nicht einmal.



  • Welches Buch würdest du für einen Anfänger denn so empfehlen?



  • für Anfänger:

    Prata: C Primer Plus

    für Fortgeschrittene:

    Koenig: C Traps and Pitfalls
    Kernighan/Ritchie: The C Programming Language
    Kernighan/Ritchie: Programmieren in C (dt. Übersetzung)



  • Sorry, bin erst 16. So gut sind meine Englischkenntnisse noch nicht. 😃

    Würde man es dennoch eventuell schaffen zu verstehen? Wenn man ja die ganzen Wörter nachschlägt etc. Oder sind sehr gute Englischkenntnisse für das Buch: "Prata: C Primer Plus" erforderlich?



  • Bleib erstmal bei dem Buch.

    Hauptsache Dir macht das ganze Spaß.

    Du hast auf jeden Fall schon was sehr wichtiges entdeckt, nur dass ein Programm läuft heißt nicht, dass es richtig ist.
    In diesem Fall:
    Wenn Du in einen Puffer mehr reinschreibst als er groß is läuft er über (engl. Buffer overflow). Das ist ein ernster Fehler.

    Das mit dem Wertebereich -128...127 ist übrigens was ganz anderes...lies erstmal weiter.

    Ganz wichtig: aktivier Warnungen Deines Compilers - z.B. gcc -Wall -pedantic ... beim gcc.

    Zum Abschluß noch das Einführungsbeispiel von K&R zum thema scanf() . Ist auch nicht gegen Pufferüberläufe gesichert. 😉

    int day, year;
    char monthname[20];
    scanf("%d %s %d", &day, monthname, &year);
    


  • TocToc auch keine Ahnung, weil er wie üblich Unsinn erzählt.

    <333

    @Bladestorm: Wenn du fgets() kennst, benutze es denn es ist, wie ich vor ein paar tagen/Wochen erfahren hab um einiges besser. 🙂



  • Wenn du fgets empfiehlst, hast du scanf nicht verstanden.

    Beide haben Vor- und Nachteile und auch Tücken.



  • Wutz schrieb:

    Dein Buch ist Schrott.
    TocToc auch keine Ahnung, weil er wie üblich Unsinn erzählt.

    Die einzig korrekte Lösung wäre

    char me[20]; /* Definition von Speicherplatz für einen max. 19 Zeichen langen C-String */
       printf("Wie heissen sie?");
       scanf("%19[^\n]", me); /* liest max. 19 Zeichen, '\0' wird immer angehängt */
       while( getchar()!='\n' ); /* leert alle nicht gelesenen Zeichen inkl. des bei scanf immer terminierenden vorhandenen '\n' aus stdin, damit folgende stdin-Operationen keinen Schaden nehmen */
    

    Beachte die while-Schleife danach, die wird von 99% aller Tutorials/Bücher und 100% aller Anfänger hier im Forum ignoriert.

    Kann man die 19 durch eine Variable ersetzen ?



  • ja, mittels sprintf:

    char me[100];
    char s[20];
    sprintf(s, "%%%u[^\n]", sizeof(me)-1);
    scanf(s, me);
    

    Die drei % sind nötig, da mittels der ersten beiden das Prozentzeichen geschrieben wird und %u dann den Parameter auswertet.



  • Oder z.B. sowas machen:

    #include <stdio.h>
    
    #define STRSIZE 20
    #define SCNSTR "19"
    
    void f() {
      char me[STRSIZE];
      scanf("%" SCNSTR "s", me);
      // ...
    }
    

  • Mod

    edit: Hier stand Unsinn.



  • SeppJ: was willst du mir damit sagen?
    Es geht hier darum einen Formatstring für scanf zu erzeugen, nicht einen String auszugeben...



  • @Th69: Dein Vorschlag ist falsch weil du sprintf falsch benutzt.

    Da das Problem mit variabler Größe für ein sicheres Einlesen von C-Strings ja wohl doch etwas schwierig zu sein scheint, hier mal der Ausbau meiner o.g. Variante diesbezüglich:

    enum {SLEN=20};
    char me[SLEN]; /* Definition von Speicherplatz für einen max. 19 Zeichen langen C-String */
    printf("Wie heissen sie?");
    {
      char ftmp[40];
      sprintf(ftmp,"%%%d[^\n]",SLEN-1);
      scanf(ftmp, me); /* liest max. 19 Zeichen, '\0' wird immer angehängt */
    }
    while( getchar()!='\n' ); /* leert alle nicht gelesenen Zeichen inkl. des bei scanf immer terminierenden vorhandenen '\n' aus stdin, damit folgende stdin-Operationen keinen Schaden nehmen */
    

    Und für ständigen Gebrauch packt man das ist eine Funktion:

    char *liesStr_(char *s,int n)
    {
      char ftmp[40];
      sprintf(ftmp,"%%%d[^\n]",n-1);
      if( scanf(ftmp, s)!=1 ) return 0;
      while( getchar()!='\n' );
      return s;
    }
    
    #define liesStr() liesStr_((char[100]){0},100)
    
    ...
    char *str1 = liesStr();
    ...
    char *str2 = liesStr();
    ...
    puts(str2);
    ...
    puts(str1);
    

    Wegen automatic storage duration des compound literals sollte man aber die "Default" Größe im Makro nicht unnötig hoch ansetzen.



  • Oder man benutzt doch einfach fgets... 🙄



  • scanf("%*s", size, string);
    

    Nein, das geht so nicht.


Log in to reply