0

我正在使用 cin.getline() 将用户输入存储在字符数组中,并尝试解析输入以仅允许输入 1 到 4 之间的数字。在特定情况下一切正常:第一次尝试输入正确的输入,或者输入 2 个或更少的字符,然后输入正确的输入。下面是一个例子。

[Expected behavior]
Enter input: 1 [ENTER]
Input accepted

[Expected behavior]
Enter input: rw [ENTER]
Incorrect input. Please try again.
Enter input: 1 [ENTER]
Input accepted

[Unexpected behavior]
Enter Input: rtw [ENTER]
Incorrect input. Please try again.
Enter Input: 1 [ENTER]
Incorrect input. Please try again.
Enter input: 1 [ENTER]
Incorrect input. Please try again.
[This will continue indefinitely]

我已经尝试了从清除输入缓冲区到将字符数组重置为空终止符以尝试查看它是否仍然保存先前输入的值(例如在意外行为中,如果“tw”仍然在内存中) . 我想我可能有类似这个讨论的问题,但我不是 100% 确定。当我尝试清除输入缓冲区时,它会等待第二组输入,我不确定为什么。当我打印结果时inputLength,在“意外行为”运行后,显示数组中仍有 2 或 3 个字符,而我只输入了 1。删除 cin.clear()/cin.ignore() 时,不需要第二个输入,但随后会发生上述行为。我很感激任何帮助。

我在下面发布了相关代码。

char* ValidateInput() {
    const int maxInput = 25;
    char userInput[maxInput] = { "\0" };
    int inputLength = 0;
    bool correctInputBool = false;

    while (!correctInputBool) {
        // subtract 1 to allow for null terminator at end of array
        cin.getline(userInput, (maxInput - 1), '\n');


        // I have tried both versions of cin.ignore() below, but neither works
        cin.clear();
        cin.ignore(numeric_limits<streamsize>::max(), '\n');
        //cin.ignore(numeric_limits<streamsize>::max());



        // calculate how many characters user entered
        inputLength = sizeOfCharArray(userInput, maxInput);

        // I do other things here, there isn't a problem with this. For now, assume all 1-character input is acceptable
        if (inputLength == 1) {
            cout << "Correct input." << endl;
            correctInputBool = true;
        }

        if (!correctInputBool) {
            cout << "Sorry, that input is incorrect. Please try again." << endl;
            cout << "Please enter a number between 1 and 4." << endl;
        }
        return userInput;
    }

int sizeOfCharArray(char input[], int maxSize) {
    // all values in input are set to "\0", so count all characters that are not null
    int userSize = 0;
    for (int index = 0; index < maxSize; index++) {
        if (input[index] != '\0') {
            userSize++;
        }
    }
    return userSize;
}

编辑:我注意到当我输入超过 3 个字符时,下一次运行总是会inputLength降低一个值。再次要求输入时,输入 9 个字符会减少到 8 个,即使只是1输入。

4

2 回答 2

0

您的代码中有多个问题,您迟早会发现。

顺便提一句。您当前的代码无法编译。我假设您确实在 and 的右括号;之后cout << "Correct input."和之间有一个,否则您的示例将永远不会循环一次。}ifreturn

您提到的问题

您不清楚userInput(而且您sizeOfCharArray还没有为此做好准备)。

让我们一步一步地处理您的代码:

  1. userInput[maxInput] = { "\0" }; //userInput contains all null characters
  2. 用户输入rwt
  3. userInput包含"rwt\0"
  4. 您的代码正确地将其视为无效输入并再次要求输入
  5. 用户输入1
  6. userInput被用户输入的字符串覆盖,但没有事先清除。它现在包含1\0t\0
  7. sizeOfCharArray计算所有非空字符并返回 2。
  8. 您的循环继续要求输入。

您返回局部变量的地址

之后ValidateInputuserInput数组就死了。永远消失了。然后你将地址返回到一个死数组,一个编译器可以随意使用的内存。

你的代码太复杂了

这通常是一个被低估的问题,但简单的代码 = 易于阅读 = 更少的错误。

你想要一个整数,对吧?那么如何从输入中读取一个整数呢?

int GetInput() {
    int result {};
    while (true) { //infinite loop
        cin >> result;

        if(!cin.good()) {
            cout << "Input wasn't a number, please try again.\n";
            cin.clear(); //clear flags that were raised
            cin.ignore(numeric_limits<streamsize>::max(), '\n'); // skip any input remaining in the stream
        } else if (!InputIsValid(result)) {
            cout << "Input not in 1-4 range, please try again.\n";
        } else {
            return result;
        }
    }
}

bool InputIsValid(int input) {
    return input >= 1 && input <= 4;
}

std::cinfail如果它无法提取请求的类型(在这种情况下int)并且变量被归零(自 C++11 起),它将提高它的位。如果fail设置了位,good()方法将返回false(即流状态不佳)。在下一次迭代中,我们从流中清除标志和任何剩余的输入。
您还可以检查循环中整数的有效范围(此处作为单独的函数完成)。

return我们使用语句跳出循环。如果一切都正确(即流设法读取正确类型的输入并且输入在有效范围内),我们将最终值返回给用户。


与 qoutes 的问题有关:C 或 C++ 中的单引号与双引号。请为了您自己的心理健康,在编译器停止显示错误之前不要随意添加符号,这绝不是一个好主意。编译器是你的朋友,他会帮助你发现问题,但前提是你帮助它做到这一点。

于 2020-01-22T19:48:56.403 回答
0

我能够使用 Visual Studio 并同时观察inputLengthuserInput变量。inputLength确实只下降了 1 个值,因为在输入的末尾添加了一个空终止符。因为这

userInput = "asdf" // with the reminaing values being '\0'
inputLength = 4

userInput = "2'\0'df" // with the following being held in memory: 2 '\0' df '\0' '\0' . . .
inputLength = 3

当我尝试打印 userInput 的值时,我只看到了2由于 null 终止符;即使这些值仍然存在,它们也没有打印出来,因为编译器看到了'\0',并且认为之后什么都没有。结果,当我调用 时sizeOfCharArray,所有非空终止符的值都被计算在内,其中包括来自先前输入的值。

我的更新代码如下。

char* ValidateInput() {
    const int maxInput = 25;
    char userInput[maxInput] = { "\0" };
    int inputLength = 0;
    bool correctInputBool = false;

    while (!correctInputBool) {         
        // updated section
        for (int index = 0; index < maxInput; index++) {
            userInput[index] = '\0';
        }
        // subtract 1 to allow for null terminator at end of array
        cin.getline(userInput, (maxInput - 1), '\n');

        // calculate how many characters user entered
        inputLength = sizeOfCharArray(userInput, maxInput);

        // I do other things here, there isn't a problem with this. For now, assume all 1-character input is acceptable
        if (inputLength == 1) {
            cout << "Correct input."
            correctInputBool = true;
        }

        if (!correctInputBool) {
            cout << "Sorry, that input is incorrect. Please try again." << endl;
            cout << "Please enter a number between 1 and 4." << endl;
        }
        return userInput;
    }

int sizeOfCharArray(char input[], int maxSize) {
    // all values in input are set to "\0", so count all characters that are not null
    int userSize = 0;
    for (int index = 0; index < maxSize; index++) {
        if (input[index] != *"\0") {
            userSize++;
        }
    }
    return userSize;
}
于 2020-01-22T19:40:58.707 回答