Problem mit fgets



  • Guten Tag,

    ich habe ein Problem, für das ich einfach nicht die Lösung finde. Auch meine Tutoren an der Uni konnten mir nicht helfen und da mein Dozent in der vorlesungsfreien Zeit nicht erreichbar ist versuche ich hier mein Glück.

    Codeausschnitt:

    Spieler SpielerEinlesen()
    {
    Spieler b;

    printf("Bitte geben Sie den Namen eines Spielers ein.\n");
    fgets(b.NameSpieler, 30, stdin);
    b.NameSpieler[sizeof(b.NameSpieler)-1]='\0';
    printf("Wie alt ist er?\n");
    scanf("%d", &b.Alter);
    .....

    b.Spieler ist wie folgt deklariert:

    typedef struct Spieler
    {
    char NameSpieler[30];
    int Alter;
    char Position[4];
    double MarrktwertSpieler;
    } Spieler;

    typedef struct Kader[code="c"]

    Problem:

    Fgets beantwortet sich dirkekt selbst mit einem Zeilenumbruch, den ich weder direkt vor fgets noch nach fgets mit einem getchar o.Ä abfangen kann.
    Jemand eine Lösung parat?


  • Mod

    Idee 1:
    Ruf so lange fgets auf, bis das Ergebnis nicht leer ist.

    Idee 2:
    Benutz nicht fgets, sondern scanf. scanf ist optimal für Eingabeoperationen dieser Art, wo man eine gewisse Formatierung der Daten erwartet. Sieh dir mal sämtliche Formatstringparameter von scanf genau an. Es ist zum Beispiel relativ einfach, die Anweisung "überspring allen Whitespace (inklusive Newlines!), dann lies bis zum nächsten newline oder maximal 29 Zeichen" in einen Formatstring zu packen: " %29[^\n]"



  • Das liegt an der Mischung von fgets und scanf .

    scanf lässt das '\n' von der Entertaste im Eingabestrom stehen.
    Für fgets bedeutet das jedoch "Eingabe ist fertig"

    Wenn mehr als ein Zeichen im Eingabestrom steht, nützt dir das getchar auch nichts.

    Probier mal die while -Schleife aus https://www.c-plusplus.net/forum/p1146014#1146014 nach dem scanf

    Ubrigens: fgets macht das mit dem '\0' schon korrekt.
    Statt der 30 wäre dort das sizeof(b.NameSpieler) geeigneter.



  • Die erste Idee hat funktioniert. Wenn ich den Code so anpasse:

    Spieler SpielerEinlesen()
    {
    Spieler b;
    char c[5];

    printf("test1 fgets puffer:\n");
    fgets(c, 5, stdin);

    printf("Bitte geben Sie den Namen eines Spielers ein.\n");
    fgets(b.NameSpieler, 30, stdin);
    b.NameSpieler[sizeof(b.NameSpieler)-1]='\0';
    printf("Wie alt ist er?\n");
    ......

    funktioniert es, aber das ist vermutlich nicht Sinn der Sache und unschön sieht es auch aus. 😃

    Edit:

    Es klappt auch, wenn ich ein getchar() davor setze:

    printf("Bitte geben Sie den Namen eines Spielers ein.\n");
    getchar();
    fgets(b.NameSpieler, 30, stdin);
    b.NameSpieler[sizeof(b.NameSpieler)-1]='\0';

    @DirkB, wenn das zutrifft, würde mich das freuen, mag es nämlich nicht Fehlerursachen nicht zu finden. 😃 Was mich bei dem Erklärungsansatz stutzig macht ist, dass der Fehler auch als erstes Funktionsargument auftritt, bevor es ein scanf gegeben hat.

    Edit2:

    Es muss natürlich strlen() anstatt sizeof() heißen, um die letzte Stelle des Strings mit \0 zu ersetzten. 😃



  • Tristan95 schrieb:

    Die erste Idee hat funktioniert. Wenn ich den Code so anpasse:....

    funktioniert es, aber das ist vermutlich nicht Sinn der Sache und unschön sieht es auch aus. 😃

    Das 'so lange' in "Ruf so lange fgets auf, bis das Ergebnis nicht leer ist." verlangt eigentlich nach einer Schleife.

    Tristan95 schrieb:

    Edit:
    Es klappt auch, wenn ich ein getchar() davor setze:

    printf("Bitte geben Sie den Namen eines Spielers ein.\n");
    getchar();
    fgets(b.NameSpieler, 30, stdin);
    b.NameSpieler[sizeof(b.NameSpieler)-1]='\0';

    Dann gib mal nach dem Alter noch ein (oder mehr) Leerzeichen ein.

    Tristan95 schrieb:

    @DirkB, wenn das zutrifft, würde mich das freuen, mag es nämlich nicht Fehlerursachen nicht zu finden.

    Fehlersuche gehört zum programmieren dazu.

    Tristan95 schrieb:

    😃 Was mich bei dem Erklärungsansatz stutzig macht ist, dass der Fehler auch als erstes Funktionsargument auftritt, bevor es ein scanf gegeben hat.

    Wenn du eine einfaches Programm, nur mit fgets als Eingabe machst, dann auch?

    Tristan95 schrieb:

    Edit2:

    Es muss natürlich strlen() anstatt sizeof() heißen, um die letzte Stelle des Strings mit \0 zu ersetzten. 😃



  • Nein ein einfaches Programm, dass nur mittels fgets einließt produziert keinen Fehler.
    Gut, da dein erster Tipp aus https://www.c-plusplus.net/forum/p1146014#1146014 am besten klappt und auch am elegantesten aussieht, werde ich mir das angewöhnen.
    Vielen Dank für deine schnelle Hilfe. 🙂


  • Mod

    Ich würde sagen, die scanf-Variante ist die beste und ist genau was du suchst. Keinerlei Gehacke, um die Eigenarten einzelner Funktionen. Alles einfache, kurze Formatstrings, die jeweils genau ausdrücken, was du möchtest.



  • SeppJ schrieb:

    Ich würde sagen, die scanf-Variante ist die beste und ist genau was du suchst. Keinerlei Gehacke, um die Eigenarten einzelner Funktionen. Alles einfache, kurze Formatstrings, die jeweils genau ausdrücken, was du möchtest.

    Damit ist Idee 2 gemeint.


Log in to reply