在下面的程序中,如果我在第一个提示符后按回车键,后面的cin语句就会被跳过,有人知道为什么吗?
这段代码是C++,我用Visual Studio 2022运行它。
#include <iostream>
using namespace std;
int main()
{
char string[21];
cout << "Enter a string: ";
cin.get(string, 20);
cin.ignore(80, '\n');
cout << "\nPress Enter to continue.\n";
cin.get(string, 20);
cin.ignore(80, '\n');
cout << "\nPress Enter to continue.\n";
cin.get(string, 20);
cin.ignore(80, '\n');
cout << "\nPress Enter to continue.\n";
cin.get(string, 20);
cin.ignore(80, '\n');
}
字符串
这段代码来自1998年的教科书。我知道有更现代的方法可以做到这一点,但我想知道为什么这段代码会出现故障。
1条答案
按热度按时间wlp8pajw1#
显示
iostate
的函数在下面的程序中,如果我在第一个提示符后按回车键,后面的cin语句就会被跳过,有人知道为什么吗?
我已经修改了你的程序,使它在每次调用
std::cin
之后显示badbit
、failbit
和eofbit
的状态。字符串
正如您在输出中看到的,当在第一个“Press Enter to continue”请求之后调用
std::cin.get
时,std::cin
被置于失败状态。这是因为在输入任何字符并存储在变量string
中之前就遇到了'\n'
。一旦
std::cin
被置于失败状态,就不能输入或忽略任何字符,直到failbit
被清除。通常这是通过调用std::cin.clear()
来完成的。因为std::cin
没有被清除,所以对std::cin.get
和std::cin.ignore
的后续调用不会尝试输入(或忽略)任何字符。型
如果在按Enter之前按一次空格键,则空格存储在变量
string
中,std::cin
不会失败。using namespace std;
的程序中使用string
作为你自己的变量是多么容易出错。iostate_info
的替代实现@大卫C.兰金在下面的评论中指出,如果函数
iostate_info
不使用rdstate
和随之而来的位掩码等低级结构,它可能更容易理解。很公平。我想我使用流太久了,因为rdstate
对我来说似乎是合理的!我忽略了一个明显的事实,即函数bad
、fail
和eof
可以相对容易地实现相同的结果。大卫还指出了
std::format
的缺点,因为它需要一个C20环境(或更高版本)才能编译iostate_info
。这里有一个解决这两个问题的重写。为了更好地衡量,我放弃了
std::string_view
,以防依赖C17也有问题。型
处理“按回车继续..”的一种方法
我比大多数人都严格。当我的程序要求你“按回车”时,你在按回车之前输入了一些垃圾字符,它会抱怨,让你再试一次。你必须在一个空白行(或只包含空格的行)上按回车。我这样做是因为我担心这些垃圾字符实际上可能是下一个提示符的输入。
函数
press_enter_to_continue
使用std::getline
来输入一个空白行。它是一套处理控制台输入的函数的一部分,其中所有的函数都使用std::getline
。(例如,参见StackOverflow answer中的函数get_int
。)如果将
press_enter_to_continue
与std::cin >> value;
等操作混合使用,则必须小心std::cin >> value;
在输入流上留下的挂起'\n'
。您必须在调用press_enter_to_continue
之前将其清除,可能是通过调用std::cin.ignore
。型
这里是函数
trim_whitespace
。型