C++循环洞察请求

C++ while loop insight request

本文关键字:请求 洞察 循环 C++      更新时间:2023-10-16

基本上,我在程序开头附近的while循环遇到了奇怪的问题,该程序检查用户对他们选择的活动的验证。当他们选择第一个活动并完成它时,它工作正常,但是当他们完成第二个活动时,它将进入运行时并不断请求用户输入有效的选择,即使他们甚至没有机会输入选项。有什么提示吗?

#include <iostream>
using namespace std;
int main()
{
const int DIGITS_CHOICE = 1, IDENTIFIER_CHOICE = 2, DOUBLE_CHOICE = 3, EXIT_CHOICE = 4;
int choice;
int userNumber, storedNumber, factor = 10, digitCounter = 0, subtractor;
char ch;
do
{
cout << "nnttPlease choose an option:nn"
<< "1. How many digits?n"
<< "2. Is this a valid C++ Identifer?n"
<< "3. Is this a double letter word?n"
<< "4. Exitn";
cout << endl << "Choice: ";
cin >> choice;
while (choice < DIGITS_CHOICE || choice > EXIT_CHOICE)
{
cout << endl << "Please enter a valid menu option: ";
cin >> choice;
}
if (choice != EXIT_CHOICE)
{
switch (choice)
{
case DIGITS_CHOICE:
cout << "Please enter an integer: ";
cin >> userNumber;
storedNumber = userNumber;
if (userNumber < 10)
{
digitCounter = 1;
}
else
{
while (userNumber != 0)
{
subtractor = userNumber % factor;
if (subtractor > 0)
{
userNumber = userNumber - subtractor;
factor *= 10;
digitCounter++;
}
else
{
userNumber = 0;
}
}
}
cout << storedNumber << " has " << digitCounter << " digit(s)." << endl;
factor = 10;
digitCounter = 0;
break;
case IDENTIFIER_CHOICE:
cout << "Please enter an identifier and press [Enter] immediately after.  ";
cin >> ch;
if (ch >= 0 || ch <= 9 || ch <= 'a' || ch >= 'z' || ch <= 'A' || ch >= 'Z' || ch != '_')
{
if (ch >= 0 || ch <= 9)
{
cout << "Not a valid identifier." << endl;
cout << "Identifiers cannot start with a digit." << endl;
ch = 'n';
}
else
{
cout << "Not a valid identifier." << endl;
cout << "Inavlid character." << endl;
ch = 'n';
}
}
while (ch != 'n')
{
if (ch >= 'a' || ch <= 'z' || ch >= 'A' || ch <= 'Z')
{
cin.get(ch);
}
}
break;
case DOUBLE_CHOICE:
break;
}
}
} while (choice != EXIT_CHOICE);
return 0;
}

此外,该程序尚未完成。 第三个选项什么都没有,第二个选项几乎完成。 第一个活动虽然是完整的:)

您对有效字符的检查过于宽泛,并且没有实际意义:

if (ch >= 0 || ch <= 9 || ch <= 'a' || ch >= 'z' || ch <= 'A' || ch >= 'Z' || ch != '_')

ch的每个可能值都将大于或等于零,因此此表达式等效于(true || a || b || c || ... || z)并且始终解析为 true。

相反,查看它是否低于'A',介于'Z''a'之间或超出'z'之间,如果是,则无效。

此外,在检查它是否是数字时,您需要检查它是否≥'0''9'字符。将其与 0 和 9 的字符表示进行比较很重要,因为字符的值实际上'0'0(事实证明它实际上是48(,同样'9'

if ( ch < 'A'  
|| (ch > 'Z' && ch < 'a')
|| ch > 'z')
{
if (ch >= '0' && ch <= '9')
{
cout << "Not a valid identifier." << endl;
cout << "Identifiers cannot start with a digit." << endl;
ch = 'n';
}
else
{
cout << "Not a valid identifier." << endl;
cout << "Invalid character." << endl;
ch = 'n';
}
}

目前还不清楚之后的检查是要做什么的?它只是为了允许字母吗?在说"标识符不能以数字开头"之后,这似乎很奇怪。

if (ch >= 'a' || ch <= 'z' || ch >= 'A' || ch <= 'Z')

这基本上具有相同的问题,即每个字符都将高于"a"或低于"z"或两者兼而有之,因此这将始终解析为 true。相反,请使用&&来检查是否在范围内:

if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'))

希望这能解决您的问题。

逻辑不是很好;i是有效的,但你的代码说它不是。它至少可以很好地回到菜单。您的代码的行为也像在键入字母时立即响应一样。事实并非如此。在用户按 Enter 之前,它不会打印任何内容。

似乎问题是你的变量ch是一个char.如果我键入的任何内容都超过单个字符,则会发生的情况是评估单个字符,而我键入的其余字符仍保留在输入流中。看起来您正在尝试处理它,但它不起作用。我不会花时间深入研究原因,部分原因是因为它很复杂,部分原因是我不知道istream行为的全部复杂性。

我要说的是,如果你想处理多字符输入,请在任何地方使用 cin.get((,而不仅仅是有时。您可以对每个字符进行处理,但同样,在用户按 Enter 之前,不会有任何内容进入屏幕。

但这是似乎有效的代码:

#include <cctype>  // isalpha() and isalnum()
#include <string>  // ch is now a std::string
// ...
case IDENTIFIER_CHOICE:
cout << "Please enter an identifier and press [Enter] immediately after.  ";
std::cin.ignore(256, 'n');  // needed because of getline behavior
std::getline(std::cin, ch);
if (!(isalpha(ch[0]) || ch[0] == '_')) {
cout << "Not valid.n";
break;
}
for (int i = 1; i < ch.size(); ++i) {
if (!isalnum(ch[i])) {
cout << "Not valid.n";
break;
}
}
cout << "Valid.n";
break;
// ...

使用cin时,当您按 Enter 时,该击键将保存在输入流中。getline()的行为方式不符合我们的预期,因为虽然cin通常会忽略该击键,但getline不会。所以我只是告诉cin忽略流中任意数量的字符(但在这种情况下足够(,包括 Enter 击键(Mac 和 Linux,应该仍然适用于 Windows(我认为((。

这离无懈可击的输入验证还很远(这是不可能的(,但我认为它足以满足您正在做的事情。