kostenloser Webspace werbefrei: lima-city


[C] fgets() in einer Schleife will nur einmal?

lima-cityForumProgrammiersprachenC/C++ und D

  1. Autor dieses Themas

    ferdinand24

    Kostenloser Webspace von ferdinand24

    ferdinand24 hat kostenlosen Webspace.

    Hallo zusammen,

    folgender Code: http://nopaste.info/e0b77368f0.html
    Ist eine Übung. Es soll ein rudimentäres Telefonverzeichnis werden. Der Benutzer soll die Möglichkeit haben, eine Anzahl von Datensätzen (Name, Vorwahl, Telefonnummer) einzugeben, die jeweils durch eine struct vordefiniert sind.
    Am Ende sollen alle Datensätze ausgegeben werden.
    (Und fragt nicht nach dem Sinn der Sache.)

    Nun treten folgende Probleme auf:
    Zeile 23:
    fgets() soll eine Zeile von der STDIN lesen, also den eingegebenen Namen.
    Im ersten Schleifendurchlauf tut es das auch noch ganz brav, im zweiten wird der Name einfach übersprungen.
    Mit scanf() (siehe Zeile 22) funktioniert das Ganze, allerdings trennt er dann nach dem Leerzeichen (das in Namen gelegentlich vorkommt) und fgets() ist mir an sich eigentlich lieber.
    $ ./telefonbuch
    Name: Max
    Vorwahl: 0123
    Nummer: 4567890
    
    Weiteren Eintrag hinzufuegen? j
    Name: Vorwahl:


    Zeile 37:
    Der Benutzer soll zum Fortfahren j oder J drücken.
    Dazu muss ich ja nur dieses eine Zeichen vom Eingabestrom lesen.
    Mit scanf() (siehe Zeile 38) funktioniert das ganz gut, fgetc() wird aber einfach übergangen. Warum?



    Liegt das am Compiler, habe ich grundsätzliche Verständnisprobleme, oder sind es einfach nur irgendwelche dummen Flüchtigkeitsfehler?


    Danke und viele Grüße,
    F.
  2. Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!

    lima-city: Gratis werbefreier Webspace für deine eigene Homepage

  3. Er compiliert das bei mir nicht:
    if(list[i].name[l] == 'n') list[i].name[l] = '';

    Du kannst einem Element eines char-Arrays nicht den Wert eines leeren Strings zuweisen. Du musst an der Stelle irgendein Zeichen angeben, oder eben 0, falls du den String an der Stelle beenden willst.
  4. Autor dieses Themas

    ferdinand24

    Kostenloser Webspace von ferdinand24

    ferdinand24 hat kostenlosen Webspace.

    Hmm, nopaste ist bescheuert...
    Die Zeile heißt bei mir tatsächlich so:
    if(list[i].name[l] == '\n') list[i].name[l] = '\0';

    Hier nochmal die komplette Datei: http://localhostr.com/file/Kzcknwb/telefonbuch.c

    Beitrag zuletzt geändert: 2.12.2011 19:29:10 von ferdinand24
  5. Hallo ferdinand24,

    ich vermute mal, dass Du unter Windows programmierst. Dann haben die beiden Probleme die selbe Ursache.
    fgets() liest so lange Zeichen ein bis entweder ein Null-Byte oder ein Zeilenumbruchszeichen (\n oder \r) kommt.
    Windows ist so freundlich beim drücken der Enter-Taste ein \r und ein \n in stdin einzufügen.
    D.h. die Eingabe
    >Name: Foobar<Enter>
    wird zu
    Foobar\r\n
    im Eingabestrom. fgets() liest dann folgendes aus stdin:
    Foobar\r
    Folglich steht noch
    \n
    in stdin. Das ist das Zeichen, dass dann mit fgetc() gelesen wird, weshalb nicht auf die Eingabe gewartet wird.
    Mögliche Abhilfen sind:
    - nach jeder Eingabe ein zusätzliches fgetc() (aber nur unter Windows => nicht portabel)
    - rewind(stdin) vor jedem Einlesen (nicht Dokumentiert hat bei mir aber immer funktioniert)
  6. Autor dieses Themas

    ferdinand24

    Kostenloser Webspace von ferdinand24

    ferdinand24 hat kostenlosen Webspace.

    Danke für Deine Antwort! rewind() tut Wunder (und das macht mir Angst :lol: )

    ich vermute mal, dass Du unter Windows programmierst.
    ;-) Nee, mit gcc unter Mac OS X - aber ich dachte, dass bei sonem Unixoid kein Wagenrücklauf mitkommt - sehr interessant. :shy:


    Viele Grüße,
    F.



    Beitrag zuletzt geändert: 2.12.2011 19:42:03 von ferdinand24
  7. hackyourlife

    Moderator Kostenloser Webspace von hackyourlife

    hackyourlife hat kostenlosen Webspace.

    Der Befehl fgetc() hat auch eine Eigenheit: Wenn in der Kommandozeile eine Taste gedrückt wird (z.B. "j") wird das nicht sofort von fgetc gelesen. Erst nach einem ENTER wird alles von der aktuellen Zeile (Zeilenpuffer) an das Programm weitergegeben. Das 1. fgetc liest daher deinen Buchstaben, ein weiteres fgetc liest allerdings das '\r' oder '\n' das noch im Puffer steht. Wenn du jetzt folgendes verwendest:
    char buffer[64];
    char c = fgetc();
    fgets(buffer, 64, stdin);
    wird in c das richtige Zeichen stehen. fgets liest aber nur bis zum nächsten '\n' (was noch im Puffer steht!) und wird nichts in die Variable buffer schreiben! So einen Fall hast du indirekt in deinem Programm (jedes mal wenn die Schleife von vorne beginnt).
  8. Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!

    lima-city: Gratis werbefreier Webspace für deine eigene Homepage

Dir gefällt dieses Thema?

Über lima-city

Login zum Webhosting ohne Werbung!