"10\n"
当你从终端提交时,选择 Enter 或 Return 键时,输入的末尾将始终添加一个换行符。在文件中,它也用于移动到下一行。换行符会被留在缓冲区中,直到下一个 I/O 操作,然后被丢弃或读取。当控制流到达 std::getline()
时,它将看到 "\nMr. Whiskers"
,并且开头的换行符将被丢弃,但是输入操作将立即停止。这种情况发生的原因是因为 std::getline()
的作用是尝试读取字符,并在找到换行符时停止。所以剩余的输入都留在了未读的缓冲区中。
解决方法
cin.ignore()
为了解决这个问题,其中一种方案就是在进行 std::getline()
前跳过换行符。你可以在第一个输入操作后调用 std::cin.ignore()
。它将丢弃下一个字符(换行符),以便它不再妨碍后面的操作。std::cin >> age;
std::cin.ignore();
std::getline(std::cin, name);
assert(std::cin);
std::ws
使用std::ws
函数是另一种丢弃空格的方法,它是一个操纵器,旨在从输入流的开头提取和丢弃前导空格:
std::cin >> age;
std::getline(std::cin >> std::ws, name);
assert(std::cin);
std::cin >> std::ws
表达式在std::getline()
调用之前执行(并且在std::cin >> age
调用之后执行),以便删除换行符。
不同之处在于ignore()
仅丢弃1个字符(或在给定参数时丢弃N个字符),而std::ws
会继续忽略空格,直到找到非空格字符为止。因此,如果您不知道下一个标记之前将有多少空格,请考虑使用它。
匹配操作
当您遇到这样的问题时,通常是因为您将格式化输入操作与非格式化输入操作组合在一起。格式化输入操作是指将输入格式化为特定类型的操作。这就是operator>>()
的作用。非格式化输入操作是除此之外的任何操作,如std::getline()
、std::cin.read()
、std::cin.get()
等。这些函数不关心输入的格式,只处理原始文本。
如果您坚持使用单一类型的格式,则可以避免这个烦人的问题:
std::string age, name;
std::getline(std::cin, age);
std::getline(std::cin, name);
或者// Formatted I/O
int age;
std::string firstName, lastName;
std::cin >> age >> firstName >> lastName;
如果您选择使用未格式化操作将所有内容读取为字符串,那么您可以在之后将它们转换为相应的类型。
std::cin >> name && std::cin >> std::skipws && std::getline(std::cin, state)
也应该可以正常工作。 (除了下面的答案之外). - jww