it-swarm.com.de

If -Anweisungen in einer do while-Schleife mit einem Ja- oder Nein-Ende

Ich bin neu im Programmieren und versuche, eine lange do while-Schleife mit verschachtelten if-Anweisungen auszuführen, aber ich habe Probleme, wenn ich meine Schleife in die eigentliche Schleife bekomme. 

Anstatt direkt Hilfe zu meinem Projekt zu bekommen, das einen sehr langen Code hat, habe ich eine einfache Version dieser Version gemacht. Es ist auch keine Schleife. Es wird zum Ende kommen und den Benutzer fragen, ob er es erneut versuchen möchte, aber wenn "y" eingegeben wird, werden die if-Anweisungen ignoriert. 

#include <iostream>
#include <string>
using namespace std;

int main()
{
    string sodaChoice;
    char answer = 'n';

    do
    {
        cout << "Please choose your favorite soda from the following: Rootbeer, Diet Coke, Coke, Sprite" << "\n";
        getline(cin, sodaChoice);

        if (sodaChoice == "Rootbeer")
        {
            cout << "Me too!" << "\n";
        }
        else if (sodaChoice == "Diet")
        {
            cout << "Not me :(" << "\n";
        }
        else if (sodaChoice == "Coke")
        {
            cout << "It's alright" << "\n";
        }
        else if (sodaChoice == "Sprite")
        {
            cout << "only if I'm sick" << "\n";

        }
        else
        {
            cout << "That was not on the list";
        }
        cout << "would you like to try again?";
        cin >> answer;



    } while (answer == 'y'|| answer == 'Y');




    return 0;
}

Ich dachte, ich brauche vielleicht eine do-Schleife in der do-Schleife um die if-Anweisungen, aber dann wusste ich nicht, wie ich damit umgehen sollte. Jede Hilfe wäre dankbar. Ich habe viele, viele Stunden damit verbracht, es herauszufinden. 

Ich habe versucht, meine Lehrerin zu fragen, aber mein College lehrt aus einem generischen Lehrplan, den ihr Dekan basierend auf ihrem Buch geschrieben hat. Er ist nicht sehr begeistert von Helfen oder Lehren. 

EDIT: Vielen Dank für die Antworten! Da es sich hierbei um eine doppelte Frage handelt, habe ich cin.ignore noch nicht gelernt, daher wusste ich nicht, dass es für mein Problem relevant war. Vielen Dank, dass Sie mich unterrichtet haben! 

15
JKisa

Mit

cin >> answer;

sie lesen genau ein Zeichen. Das Problem ist, dass Sie beim Schreiben der Antwort mindestens zwei Zeichen eingegeben haben. Der tatsächliche 'y' oder 'n' plus der Enter Taste, die als neue Zeile im Eingabepuffer eingefügt wird.

Diese neue Zeile wird dann beim nächsten Aufruf von getline als leere Zeile gelesen.

Es gibt einige Lösungen für dieses Problem, beispielsweise die Verwendung von ignore nach dem Einlesen von answer. Wenn Sie nur Ein-Wort-Eingaben wünschen, können Sie auch formatierte Eingaben mit >> für sodaChoice verwenden, da führende Leerzeichen (wie Zeilenumbrüche) standardmäßig übersprungen werden.

13

Bestehende Antworten sind korrekt, wenn der Benutzer sich nett verhält und nur ein 'y' oder ein 'n' gefolgt von einer Zeilenumschaltung eingibt. 

Wir können ein bisschen Sicherheit mit einer Änderung des Aufrufs .ignore () hinzufügen, indem wir ihn bitten, alle Zeichen bis zu einer neuen Zeile zu ignorieren:

Sie müssen dieses Header-Include oben in Ihrer Übersetzungseinheit hinzufügen:

#include <limits>

Und Sie müssen diese Zeile vor cin >> answer hinzufügen:

// consumes and ignores as many characters as necessary until a newline. 
// The newline is also consumed.
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

Volles Programm mit Testeingaben hier:

http://coliru.stacked-crooked.com/a/996e77559590ad6d

Leider ist es nicht ungewöhnlich, dass Informatiklehrer nichts über Informatik wissen. Machen Sie sich keine Sorgen oder lassen Sie sich davon abschrecken, wie man Software schreibt. Dies ist nur ein Symptom dafür, dass gute Software-Ingenieure viel mehr als gute Lehrer bezahlt bekommen.

Hier finden Sie nützliches Referenzmaterial: https://de.cppreference.com/w/cpp/io/basic_istream/ignore

7
Richard Hodges

Ich werde etwas ganz Gegenteiliges zu den anderen Antworten vorschlagen. Anstatt cin.ignore zu verwenden, um zusätzliche Zeichen nach dem von Ihnen gelesenen zu überspringen, ist es meines Erachtens besser, alle Lesevorgänge mit getline() durchzuführen und cin >> somevar vollständig zu vergessen.

Es gibt zwei Gründe:

  1. Die formatierte Eingabe, die Sie mit cin >> somevar erhalten, ignoriert führende Leerzeichen, einschließlich Zeilenumbrüchen. Wenn der Benutzer trifft Enter In einer leeren Zeile macht das Programm nichts, erwartet aber noch weitere Eingaben. Dies erwartet der Benutzer eines CLI-Programms nicht! Die übliche Erwartung ist das Enter Vervollständigt die Eingabe, und eine leere Eingabe sollte entweder dazu führen, dass das Programm einen Standardwert verwendet, oder sich über ungültige Eingaben beschweren. Mit cin >> somevar können Sie auch nicht.

  2. Bei der formatierten Eingabe verbleiben alle nicht übereinstimmenden Eingaben im Puffer. In Ihrem Beispiel verbleibt beim Lesen eines einzelnen Zeichens mindestens die folgende neue Zeile, das Gleiche gilt jedoch auch für andere Arten von Eingaben. Das Lesen einer Zahl (mit int i; cin >> i;) hinterlässt nach der Zahl, die auf den nächsten Eingabevorgang wartet, etwas. Wenn Sie also 123 abc eingeben, wird 123 zurückgegeben, und abc wird beim nächsten Eingabevorgang angezeigt.

    Die zugrunde liegende Ursache hierfür ist, dass sich ein Befehlszeilenterminal standardmäßig in einem zeilenbasierten Modus befindet. Das Programm oder die Bibliotheksfunktionen sehen keine Eingabe vom Betriebssystem, bis eine vollständige Zeile eingegeben wird. (cin.ignore() kann Ihnen natürlich dabei helfen, aber nicht beim ersten Punkt.)

Die Verwendung von getline() entspricht genau der zugrunde liegenden Mechanik, ermöglicht den Umgang mit leeren Eingaben (und das Erkennen des Unterschieds zwischen einer Null und einer Nicht-Zahl beim Lesen einer int) und die automatische Behandlung des nachfolgenden Abfalls. Sie müssen die gelesene Zeichenfolge jedoch manuell in die tatsächlich gewünschte konvertieren.

In Ihrem Fall können Sie die Schleifenbedingung trivial in etwas ändern:

string answer;
...
    getline(cin, answer);
} while (answer == "y" || answer == "Y");

Wenn Sie eine Nummer benötigen, können Sie z. int num = std::stoi(str).


(In C geschieht dasselbe, wenn scanf() für Benutzereingaben verwendet wird. In ähnlicher Weise ist es besser, fgets() zu verwenden und dann die Zeichenfolge mit sscanf() zu analysieren, was dieselben Optionen bietet, sich jedoch mit der Zeilenpufferung befasst. Ich bin mit C++ nicht allzu vertraut Daher kann ich nicht sagen, wie genau cin >> somevar mit einer vollständigen Zeile, die von getline() gelesen wird, verglichen werden soll.)

5
ilkkachu

Da Sie Eingaben des Benutzers vom Typ char, aber bei jedem Enter-Tastentreffer vornehmen, ordnet er der Variablen answer die Newline (\n) zu.

Sie können dies ignorieren, indem Sie direkt hinter der Eingabezeile eine Zeile hinzufügen

cin.ignore();

Sie können this für weitere Details lesen.

0
Shravan40