这是我在这里的第一篇文章,我对C语言相对较新(这只是我在大学的第二个单元)。
基本上,我正在尝试编写一段代码,询问用户是否希望继续。如果他们写“yes”,代码继续循环。如果他们写no,代码终止程序。如果他们写了别的东西,它只会再次询问,直到有一个可识别的输入。我正在使用scanf和printf,并试图只使用它们来创建此代码。
char userInput[4];
userInput[0] = '\0';
while ((strcmp(userInput, "yes") != 0) && (strcmp(userInput, "no") != 0))
{
printf("Do you want to continue (yes/no) :");
scanf("%3s", userInput);
}
为了简单起见,我没有包括其余的代码。
例如,我的输入是
xxx
输出为
Do you want to continue (yes/no) :
这没什么但是,如果我输入:
xxxx
输出为:
Do you want to continue (yes/no) :Do you want to continue (yes/no) :
如果我输入
xxxxxxx
我明白
Do you want to continue (yes/no) :Do you want to continue (yes/no) :Do you want to continue (yes/no) :
看起来它几乎是保存了预期长度后的其余字符,并发送他们直接输入或什么?我想在保护字符串太长,但这不是理想的,在我看来。
我很抱歉,如果这个问题结构不好,任何建设性的批评都很感激。我在任何地方都找不到这个确切的问题,所以我想我应该问问自己。
3条答案
按热度按时间62lalag41#
当你使用
scanf("%3s", userInput)
时,它只会将3
字符以'\0'
结束到userInput
缓冲区。但是,如果您键入的字符超过3
,则其余字符仍存在于输入缓冲区中,等待scanf
读取。您可以在每scanf
之后耗尽缓冲区,以避免这种意外。bxjv4tth2#
看起来它几乎是保存了预期长度后的其余字符,并发送他们直接输入或什么?
是的,就是这样。
这些字符就在那里,坐在输入缓冲区中,等待被消费,就像前三个字符在一个时间点一样。
你从你的键盘发送字符,通过你的操作系统,进入你的终端。你的程序,按照你写的,将接受文本,直到宇宙的尽头(尽管一次三个字符)。只要有更多的字符可用,它就会吃掉它们,而不管你的击键在时间上分布得有多远。C++无法知道你想让它做什么。
也就是说,通过调整语义(如其他答案所示),可以获得更直观的调用/响应提示行为。
ltqd579y3#
欢迎了解使用
scanf
进行用户输入的陷阱。fgets
或POSIXgetline
是更好的选择,因为它们避免了许多问题(“输入缓冲区中还剩下什么?“)scanf
固有的问题。因此,了解如何正确使用scanf
是很重要的。使用
scanf
只不过是一个考虑以下问题的练习:(1)实际读取了哪些字符?以及(2)输入缓冲区中哪些字符未被读取?为了处理不。2,您需要某种方法来清空在调用scanf
之间保留在输入缓冲区中的任何字符,以确保您不会被任何剩余的字符咬到。您还必须知道至少有一个字符仍然存在,否则您将简单地阻止等待输入清除。清空stdin
的标准方法是循环遍历所有剩余的字符,直到读取尾随的"\n'
(用户按下“Enter”的结果)或EOF
。例如,(you也可以将其写成单个
for
语句,例如:for (int c = getchar(); c != '\n' && c != EOF; c = getchar()) {}
,但while通常更具可读性。)这不仅仅是正确处理输入的问题。由于您希望强制用户输入“yes”或“no”,因此通常的方法是不断循环,直到满足输入条件。一些你在正确的轨道上,但没有完全到达那里。相反,您可以执行以下操作:
如果以这种方式进行读取,则可以控制输入缓冲区中剩余的内容,不仅可以控制循环中的每次读取,还可以确保在离开时,没有来自用户输入的字符留在缓冲区中。
如上所述,正确使用scanf只是一个会计问题,一旦你知道每个 * 格式说明符 * 的行为,以及 * 输入 * 或 * 匹配 * 失败在失败时停止读取的影响,你就可以回答下面的问题:(1)实际读取了哪些字符?以及(2)输入缓冲区中哪些字符未被读取?
一个简短的例子可能会有所帮助:
(**注:**上述
"yes"
和"no"
响应分别进行比较,以允许在"yes"
或exit
上继续处理"no"
)示例使用/输出