Fehler nur wo und warum??



  • Ich brauche Hilfe, wie der Titel schon sagt , und zwar habe ich einmal diesen quellcode:

    #include <iostream>

    using namespace std;

    // Hauptprogramm
    //
    int main ()
    {
    // Strukturen
    //
    struct S_Spieler
    {
    int Team;
    char Name[30];
    };

    // Variablen
    //
    S_Spieler SpielerListe[4];
    int Auswahl = 0;

    // Abfrage der einzelnen Spielerdaten
    for (int i=0; i<4; i++)
    {
    SpielerListe[i].Team = 0;

    // Name abfragen
    cout << "Spieler " << i+1 << endl;
    cout << "Dein Name: ";
    cin.get (SpielerListe[i].Name, 29);

    // Team abfragen
    do
    {
    cout << "In welchem Team willst Du spielen (1 oder 2): ";
    cin >> SpielerListe[i].Team;

    } while (SpielerListe[i].Team != 1 && SpielerListe[i].Team != 2);

    cout << endl;
    cin.ignore ();
    }

    // Ausgabe aller Teilnehmer eines Teams
    do
    {
    cout << "Welches Team soll angezeigt werden (0 fuer Ende): ";
    cin >> Auswahl;

    // Nur ausgeben, wenn ein gültiges Team gewählt wurde
    if (Auswahl == 1 || Auswahl == 2)
    {
    cout << "Team " << Auswahl << " besteht aus:" << endl;

    // Alle Spieler durchlaufen
    for (int j=0; j<4; j++)
    {
    // Ist der Spieler im anzuzeigenden Team?
    if (SpielerListe[j].Team == Auswahl)
    {
    cout << "Spielername: " << SpielerListe[j].Name;
    cout << endl;
    }
    }

    cout << endl;
    }

    } while (Auswahl != 0);

    return 0;
    }

    der funktioniert auch ohne probleme so wie er soll
    und dann nochmal den geleichen:

    #include <iostream>

    using namespace std;

    // Hauptprogramm
    //
    int main ()
    {
    // Strukturen
    //
    struct S_Spieler
    {
    int Team;
    char Name[30];
    };

    // Variablen
    //
    S_Spieler SpielerListe[4];
    int Auswahl = 0;
    int D;
    cin >> D;

    // Abfrage der einzelnen Spielerdaten
    for (int i=0; i<4; i++)
    {
    SpielerListe[i].Team = 0;

    // Name abfragen
    cout << "Spieler " << i+1 << endl;
    cout << "Dein Name: ";
    cin.get (SpielerListe[i].Name, 29);

    // Team abfragen
    do
    {
    cout << "In welchem Team willst Du spielen (1 oder 2): ";
    cin >> SpielerListe[i].Team;

    } while (SpielerListe[i].Team != 1 && SpielerListe[i].Team != 2);

    cout << endl;
    cin.ignore ();
    }

    // Ausgabe aller Teilnehmer eines Teams
    do
    {
    cout << "Welches Team soll angezeigt werden (0 fuer Ende): ";
    cin >> Auswahl;

    // Nur ausgeben, wenn ein gültiges Team gewählt wurde
    if (Auswahl == 1 || Auswahl == 2)
    {
    cout << "Team " << Auswahl << " besteht aus:" << endl;

    // Alle Spieler durchlaufen
    for (int j=0; j<4; j++)
    {
    // Ist der Spieler im anzuzeigenden Team?
    if (SpielerListe[j].Team == Auswahl)
    {
    cout << "Spielername: " << SpielerListe[j].Name;
    cout << endl;
    }
    }

    cout << endl;
    }

    } while (Auswahl != 0);

    return 0;
    }
    nur das ich diese beiden Zeilen dazugeschrieben habe
    int D;
    cin >> D;
    die sollten eigentlich nichts mit dem programm zutun haben und nur da stehen und es nicht beeinflussen, aber Kompiliert man es jetzt und führ es dann aus entsteht ein riesiges Chaos (ich weiß nicht wie ich es besser beschreiben soll ihr könnts ja einfach mal ausprobieren)
    jetzt meine frage wieso funktioniert das Programm mit den 2 eingefügten Zeilen nicht mehr und wie beeinflussen sie das Programm? oO

    Bitte um Antwort


  • Mod

    Ich helfe mal anderen, dir zu helfen:

    #include <iostream>
    
    using namespace std;
    
    // Hauptprogramm
    //
    int main ()
    {
      // Strukturen
      //
      struct S_Spieler
      {
        int Team;
        char Name[30];
      };
    
      // Variablen
      //
      S_Spieler SpielerListe[4];
      int Auswahl = 0;
      int D;
      cin >> D;
    
      // Abfrage der einzelnen Spielerdaten
      for (int i=0; i<4; i++)
        {
          SpielerListe[i].Team = 0;
    
          // Name abfragen
          cout << "Spieler " << i+1 << endl;
          cout << "Dein Name: ";
          cin.get (SpielerListe[i].Name, 29);
    
          // Team abfragen
          do
            {
              cout << "In welchem Team willst Du spielen (1 oder 2): ";
              cin >> SpielerListe[i].Team;
    
            } while (SpielerListe[i].Team != 1 && SpielerListe[i].Team != 2);
    
          cout << endl;
          cin.ignore ();
        }
    
      // Ausgabe aller Teilnehmer eines Teams
      do
        {
          cout << "Welches Team soll angezeigt werden (0 fuer Ende): ";
          cin >> Auswahl;
    
          // Nur ausgeben, wenn ein gültiges Team gewählt wurde
          if (Auswahl == 1 || Auswahl == 2)
            {
              cout << "Team " << Auswahl << " besteht aus:" << endl;
    
              // Alle Spieler durchlaufen
              for (int j=0; j<4; j++)
                {
                  // Ist der Spieler im anzuzeigenden Team?
                  if (SpielerListe[j].Team == Auswahl)
                    {
                      cout << "Spielername: " << SpielerListe[j].Name;
                      cout << endl;
                    }
                }
    
              cout << endl;
            }
    
        } while (Auswahl != 0);
    
      return 0;
    }
    


  • Kann es sein, daß nach cin>>D; zwar die Ziffern alle weggelesen wurden, das folgende \n aber noch im cin steckt und dann ausgelesen wird und den ersten Namen kaputtmacht?



  • -.-



  • Du musst mit diesen "Streams" immer etwas aufpassen, d.h. beachten welche Konsequenzen die Eingaben haben könnten.

    In deinem Fall bleibt nach dem cin >> D noch ein '\n' Zeichen im Stream, welches auch durch das get() nicht entfernt wird. In der do-while Schleife geht der Stream dann in einen Fehlerzustand, weil cin ein Integerwert erwartet aber durch das immer noch vorhandene '\n'-Zeichen keinen findet. Da du die Schleife erst beendest, wenn ein gültiger Wert (1 oder 2) eingegeben wurde ensteht das Chaos.

    Das '\n' Zeichen bekommst du ebenfalls mit einem cin.ignore() weg. Also:

    //...
    int D;
    cin >> D;
    cin.ignore ();
    //...
    


  • OK, war zu spät. 🙂


  • Mod

    Ich habe es mir mal angeschaut. Allgemein: Tu dir selbst einen großen Gefallen und nimm string anstatt char-Arrays.

    Dein Problem liegt an der Mischung von formatierten Eingabeoperationen (Operator >>) und unformatierten Eingaben (get). Die beiden Methoden vertragen sich nicht so gut. Wenn nämlich am Anfang eine Zahl mit cin >> D eingelesen wird, dann wird deren Eingabe üblicherweise mit der Eingabetaste abgeschlossen. Der Operator >> liest dann die Zahl von der Eingabe, lässt aber das Zeilenendzeichen noch da. Bei der nächsten Benutzung von >> würden führende Zeilenendzeichen dann einfach ignoriert, so dass dies kein Problem ist. Deine nächste Eingabeoperation ist aber eine unformatierte Eingabe: get. Dem macht das schon etwas aus, denn es liest bis zum nächsten Zeilenendzeichen ein. Dies ist nun aber direkt das nächste Zeichen. Das heißt es wird gar nichts eingelesen!
    Und nun guckt man in die Referenz von get und sieht, dass im Falle, dass nichts gelesen wird, das failbit des Streams (cin) gesetzt wird, um diesen Fehler anzuzeigen. Solange aber der Stream im Fehlerzustand ist, kann nichts weiter eingelesen werden, alle Eingabeoperationen schlagen automatisch fehl. Das heißt in deiner darauf folgenden Schleife zur Teamabfrage wird der Wert von SpielerListe[i].Team nie geändert. Und da die Schleife so lange läuft bis der Wert 1 oder 2 ist, läuft sie ewig weiter. Und das ist es was du siehst.

    Abhilfe: Du könntest nur formatierte Eingaben verwenden, also auch bei der eingabe des Spielernamens. Der Nachteil ist, dass du dann nur Namen ohne Leerzeichen eingeben könntest (weil der Operator >> beim Erreichen von Whitespace die Eingabe als Beendet ansieht).
    Noch eine Alternative wäre, immer nur unformatierte Eingabeoperationen zu benuzten (aber bitte getline aus dem string-Header, nicht get.). Der Nachteil hier wäre, dass du die Zahlen hinterher noch mühsam aus der eingegebenen Zeile extrahieren müsstest, was ich nicht anraten würde.
    Und die letzte und wohl auch beste Alternative die mir gerade einfällt: Bevor du get (oder besser getline) benutzt, guckst du ob das nächste Zeichen im Stream (peek()) ein Zeilenendzeichen ('\n') ist. Wenn es eines ist, benutzt du ignore(), um es zu überspringen.

    edit: Viel zu spät. Kein Wunder, ich habe ja auch einen kleinen Roman geschrieben 😃



  • Irgendwie scheint mein Gesülze nicht recht zu stimmen. Denn zwei hintereinder ausgeführte cin >> D würden ja auch funktionieren. Hab aber jetzt keine Lust nochmal über dieses Streamzeug nachzudenken. 😞



  • SeppJ schrieb:

    edit: Viel zu spät. Kein Wunder, ich habe ja auch einen kleinen Roman geschrieben 😃

    Danke für den Hinweis auf die Entfernung der führenden Zeilenendezeichen in deinem Roman. Da ist mir doch glatt wieder ein Licht aufgegangen. 🙂



  • wie kann ich das denn nachgucken "guckst du ob das nächste Zeichen im Stream (peek()) ein Zeilenendzeichen ('\n')"
    tut mir leid wenn das eine dumme frage ist 😃

    achja und schonmal danke an alle 🙂


  • Mod

    MaikBae schrieb:

    wie kann ich das denn nachgucken "guckst du ob das nächste Zeichen im Stream (peek()) ein Zeilenendzeichen ('\n')"
    tut mir leid wenn das eine dumme frage ist 😃

    achja und schonmal danke an alle 🙂

    if (cin.peek() == '\n')  // ...
    

    😃



  • Nun habe ich nochmal ein Problem 😃
    folgendes also bei dem "\n" Problem war cin.peek() = 10
    und dann konnte man das immer mit cin.ignore() wieder loeschen
    aber jetzt ist cin.peek() = -1 und nach cin.ignore() ist das immer noch -1 gibt es noch eine möglichkeit das wieder zurückzusetzen?

    Ich hoffe ihr konntet mir folgen :p



  • Du bekommst EOF angezeigt.

    http://www.cplusplus.com/reference/iostream/istream/peek/

    Mit cin.clear() wird das Objekt cin wieder eingabebereit.

    http://www.cplusplus.com/reference/iostream/ios/clear/



  • Du bekommst EOF angezeigt.

    http://www.cplusplus.com/reference/iostream/istream/peek/

    Mit cin.clear() wird das Objekt cin wieder eingabebereit.

    http://www.cplusplus.com/reference/iostream/ios/clear/



  • ok danke jetzt sind alle fragen von mir beantwortet 🙂


Log in to reply