web-dev-qa-db-ja.com

yesまたはnoで終わるdo whileループのifステートメント

私はコーディングが初めてで、長い間やろうとしていますdo whileネストされたifステートメントでループしますが、ループを実際にループさせるのに問題があります。

非常に長いコードを持つプロジェクトで直接ヘルプを取得する代わりに、そのようなバージョンのような単純な種類を作成しました。また、ループしません。最後までやり直して、ユーザーに再試行するかどうかを尋ねますが、「y」を入力すると、ifステートメントは無視されます。

#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;
}

If文のdoループ内にdoループが必要かもしれないと思ったのですが、どうすればいいのかわかりませんでした。任意の助けをいただければ幸いです。私はそれを理解しようとして多くの時間を費やしました。

私は先生に聞いてみましたが、私の大学は学部長が​​彼女の本に基づいて書いたいくつかの一般的なカリキュラムから教えています。彼は、援助や指導にあまり熱心ではありません。

編集:答えてくれてありがとう!これが重複する質問であることに関しては、私はまだcin.ignoreを学んでいないので、それが私の問題に関連していることを知りませんでした。教えてくれてありがとう!

15
JKisa

cin >> answer;

正確にone文字を読み取ります。問題は、答えを書くときに少なくともtwo文字を入力したことです。実際の'y'または'n'plus Enter キー。入力バッファに改行として追加されます。

この改行は、次のgetline呼び出しで空行として読み取られます。

この問題にはいくつかの解決策があります。たとえば、ignoreを読み込んだ後に answer を使用します。または、1ワードの入力のみが必要な場合は、sodaChoiceにも>>を使用した書式付き入力を使用できます。これは、デフォルトで先頭の空白(改行など)をスキップするためです。

13

ユーザーが適切に動作し、「y」または「n」に続けて改行を入力した場合、既存の回答は正しいです。

次の改行を含むまでのすべての文字を無視するように要求することにより、.ignore()呼び出しに変更を加えることで、少し安全性を追加できます。

翻訳ユニットの上部にこのヘッダーインクルードを追加する必要があります。

#include <limits>

そして、cin >> answerの前にこの行を追加する必要があります:

// 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');

テスト入力付きの完全なプログラムはこちら:

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

残念ながら、コンピューターサイエンスの教師がコンピューターサイエンスについて何も知らないことは珍しいことではありません。これについて心配する必要はありません。または、ソフトウェアの作成方法を習得しなくても構いません。これは、優秀なソフトウェアエンジニアが優秀な教師よりも多くの報酬を受け取っているという事実の単なる兆候です。

ここにいくつかの有用な参考資料があります: https://en.cppreference.com/w/cpp/io/basic_istream/ignore

7
Richard Hodges

私は、他の答えとはまったく反対の何かを提案します。 cin.ignoreを使用して読んだ後の余分な文字をスキップする代わりに、getline()ですべての読書を行い、cin >> somevarを完全に忘れた方が良いと思います。

2つの理由があります。

  1. cin >> somevarで取得した書式付き入力は、改行を含む先頭の空白を無視します。ユーザーがヒットした場合 Enter 空の行では、プログラムは何もしませんが、さらに入力が必要です。これは、CLIプログラムのユーザーが期待するものではありません!通常の期待は Enter 入力を完了します。入力が空の場合は、プログラムでデフォルト値を使用するか、無効な入力について文句を言う必要があります。 cin >> somevarでは、どちらもできません。

  2. フォーマットされた入力では、一致しない入力はバッファに残ります。この例では、単一の文字を読み取ると少なくとも次の改行が残りますが、他の種類の入力でも同じことが起こります。 (int i; cin >> i;を使用して)数値を読み取ると、数値が次の入力操作を待機するため、123 abcを入力すると123が返され、abcが表示されます。次の入力操作。

    この根本的な原因は、デフォルトでは、コマンドライン端末が行ベースモードになっていることです。プログラムまたはライブラリ関数は、完全な行が入力されるまでオペレーティングシステムからの入力を認識しません。 (cin.ignore()はもちろんこれに対処するのに役立ちますが、最初のポイントには対処できません。)

getline()を使用すると、基礎となるメカニックと正確に一致し、空の入力を処理できます(また、intを読み取るときにゼロと非数値の違いを認識できます)。末尾のゴミで。ただし、読み取り文字列を実際に必要なものに手動で変換する必要があります。

あなたの場合、ループ条件を次のように簡単に変更できます。

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

番号が必要な場合は、たとえばint num = std::stoi(str)


(Cでは、ユーザー入力にscanf()を使用した場合も同じことが起こります。同様に、fgets()を使用してsscanf()で文字列を解析すると、同じオプションが得られます。私はC++にあまり詳しくないので、getline()によって読み取られる完全な行でcin >> somevarの正確な同等物をどのように持つかを知ることはできません。)

5
ilkkachu

タイプcharのユーザーから入力を取得しているが、すべてのEnterキーがヒットするため、改行(\n)を変数answerに。

入力行の直後に行を追加することでこれを無視できます

cin.ignore();

詳細については this を参照してください。

0
Shravan40