我正在使用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]
我已经尝试了从清除输入缓冲区到将字符数组重置为null终止符的所有尝试,以尝试查看它是否仍保留先前输入的值(例如在意外行为中,如果仍然存在“ tw”在记忆中)。我认为我可能遇到类似于this discussion的问题,但我不确定100%。当我尝试清除输入缓冲区时,它会等待第二组输入,但我不确定为什么。当我打印inputLength
的结果时,在运行“意外行为”后,它表明当我只输入1时,数组中仍然有2或3个字符。删除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
降低一个值。即使再次输入1
,即使再次输入,输入的9个字符也会降为8。
答案 0 :(得分:0)
我能够使用Visual Studio并观看inputLength
和userInput
变量。 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
。即使值仍然存在,它们也不会打印,因为编译器看到了'\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;
}
答案 1 :(得分:0)
您的代码中有多个问题,迟早会发现。
顺便说一句。您当前的代码无法编译。我假设您在;
之后确实有cout << "Correct input."
,并且在}
和if
的右花括号之间有一个return
,否则您的示例将永远不会循环一次。>
您没有清除userInput
(并且您的sizeOfCharArray
还没有为此做好准备)。
让我们逐步介绍您的代码:
userInput[maxInput] = { "\0" }; //userInput contains all null characters
rwt
userInput
包含"rwt\0"
1
userInput
被用户输入的字符串覆盖,但是它不会事先清除。现在它包含1\0t\0
sizeOfCharArray
计算所有个非空字符并返回2。在ValidateInput
之后,userInput
数组无效。永远离开。然后,将地址返回到无效数组,该数组是编译器可以根据需要使用的内存。
这通常是一个被低估的问题,但是简单的代码=易于阅读=更少的错误。
您想要一个整数,对不对?那么从输入中读取整数怎么样?
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::cin
无法提取请求的类型(在这种情况下为fail
)并且变量为零(自C ++ 11起),它将提高其int
位。如果将fail
位置1,则good()
方法将返回false
(即流状态不佳)。在下一次迭代中,我们清除标志和流中所有剩余的输入。
您还可以在循环中检查整数的有效范围(在此处作为单独的函数完成)。
我们使用return
语句打破了循环。如果一切正确(即,流成功读取了正确的输入类型,并且输入在有效范围内),我们会将最终值返回给用户。
与qoutes有关的问题:Single quotes vs. double quotes in C or C++。为了您自己的心理健康,请不要随意添加符号,直到编译器停止显示错误为止,从不是个好主意。编译器是您的朋友,他将帮助您发现问题,但前提是您需要帮助。