2

ユーザーが特定の範囲内でx座標とy座標を一度に1つずつ入力する必要があるゲームがあります。現在、私の入力コードは次のとおりです。

do {
    printf("\n");
    cout << "X: ";
    cin >> x;
    cout << "Y: ";
    cin >> y;
} while (cin.fail());

私は c++ を初めて使用しますが、ドキュメントを読むと、これがユーザー入力を検証するための受け入れ可能な方法であると確信しました。入力が有効な場合は完全に機能しますが、入力が異なるタイプの場合 (たとえば、「a」を入力する場合)、「X: Y: 」で無限ループします。行が初めて読み取られたかのようにユーザー入力を待機させるには、どうすればよいですか?

4

2 に答える 2

5

すべての入力操作を確認する必要があります。

std::cout << "X: ";
if (!(std::cin >> x)) { /* error */ }
std::cout << "Y: ";
if (!(std::cin >> y)) { /* error */ }

エラーをどのように処理するかは、あなた次第です。早く戻ったり、ループから抜けたり、例外をスローしたりできます...すべて依存します。

解析可能なものが得られるまでループすることもできますが、ユーザーが入力ストリームを閉じると危険です行ごとに読んで解析する方が良い:

std::cout << "Please enter an integer X: ";
int x;
bool success = false;

for (std::string line; std::getline(std::cin, line); )
{
    std::istringstream iss(line);
    if (iss >> x >> std::ws && iss.get() == EOF)  // #1
    {
        success = true;
        break;
    }
    std::cout << "Sorry, please try again: ";
}

if (!success)
{
    std::cerr << "Unexpected end of input stream!\n";
    std::exit(1);
}

このように、ユーザーがセッションの途中で [Ctrl]-D を押すと、プログラムはすぐにシャットダウンし、閉じられた入力ストリームからそれ以上値を読み取ろうとしません。

マークされた行の条件#1は、整数の解析が成功したことと、行の終わりに到達したこと (中間の空白を飲み込むこと) の両方をテストします。

于 2012-09-12T22:36:58.543 に答える
4

変数ごとに解析しようとする最大の問題は、ユーザーがミスをすると、入力全体が疑わしいものになることです。

無効な入力をスキップして、「3e4 40」と入力するかどうかを検討してください。私は「34 40」を意味していましたが、e をスキップすると「3 4」になり、「40」を後で残すか、「4 40」を残す可能性があります。

getlineを使用して行全体を読み取り、現在と同じようにistringstreamなどで解析することを検討してください。入力ストリームを奇妙な状態にすることなく、エラーはすべてエラーになります。

于 2012-09-12T22:41:06.047 に答える