连续 cin 输入在C++中的工作原理
How continuous cin input works in C++
很抱歉,我找不到更好的标题来回答这个问题。我正在遵循Stroustrup的编程:使用C++的原则和实践。这个示例代码引起了我的注意。我的问题是,cin 如何在一个单词中识别两种不同的类型,例如 200.40i(200.40 double 和 i char)?我的意思是,它不应该期待至少一个空白分隔的输入吗?
int main()
{
constexpr double cm_per_inch = 2.54;
double length = 1;
char unit = 0;
cout << "Please enter a length followed by a unit (c or i):n";
cin >> length >> unit;
if (unit == 'i')
cout << length << "in == " << cm_per_inch*length << "cmn";
else
cout << length << "cm == " << length/cm_per_inch << "inn";
}
如果我只是运行程序并输入:200.40i 工作正常,同样适用于:200.40 i 和:200.40 i。
这是对格式化输入提取运算符(又名)内部工作的严重过度简化。>>
用于解释您观察到的输入行为。这是>>
的工作原理:
第 1 步:跳过输入流中的任何空格。
第 2 步:将输入流的下一部分转换为>>
要使用的任何数据类型。仅从输入流中提取已转换的输入。
对每个>>
运算符执行这两个步骤。正如我所说,这过于简单化了。还有其他事情正在发生,例如用于异常处理的哨兵对象,这些事情在这里无关紧要。
重要的是,当>>
看到提取的任何内容后面的空格时,它不会"停止"。这就是在介绍性C++文本中经常解释>>
的方式,但这并不完全正确。>>
在提取完提取的任何内容后立即停止,并且不会提取随后的任何内容。现在,在"提取的任何内容"之后,您通常会有额外的空格。没关系。格式化的输入提取运算符将在该点停止。但重要的是它不会提取空格。这将通过随后的>>
提取(如果有的话)来处理。
而且它不必是空格。它可以是不再解析为提取的任何内容的任何内容。因此,在您的情况下:
cin >> length >> unit;
length
是一个double
.unit
是一个char
.您的输入是:
200.40i
前>>
仅提取"200.40"。字符i
不可能属于double
值,因此提取在该点停止,并且不会提取i
。这样,第一个>>
从中拉出的唯一东西。然后,第 2>>
提取单独的"i"字符。
出于所有实际目的,格式化提取运算符始终使用 peek() 查看输入流中的下一个字符,以决定是否将其提取为从输入流中提取的任何内容的一部分。如果它看起来不错,那么它就会被吞噬。
现在,如果有一些空格:
200.40 i
第一个>>
像以前一样将double
从中取出并停止,但它不会提取空间。第二个>>
跳过空格作为其"步骤 1"的一部分,然后提取char
。
因此,您会看到,>>
格式的提取运算符不是在提取提取的任何内容之后丢弃空格,而是在提取之前丢弃空格。
其他一些注意事项:
如果
>>
提取到一个std::string
,这将提取除空格以外的任何内容,因此这里唯一停止提取的是尾随空格。但是尾随空格本身仍然没有被提取,而只能由下一个>>
运算符提取。如果像本例一样,
>>
提取到一个孤独的char
,这个char
只能容纳一个角色,所以在这种情况下,这就是所有将被提取的内容。
http://www.learncpp.com/cpp-tutorial/5-10-stdcin-extraction-and-dealing-with-invalid-text-input/
使用提取运算符时,将执行以下过程:
- 如果输入缓冲区中已有数据,则该数据将用于提取。
- 如果输入缓冲区不包含任何数据,则会要求用户输入数据进行提取(大多数情况下都是这种情况)。当用户按 Enter 键时,输入缓冲区中将放置一个""字符。
- 运算符>> 从输入缓冲区中提取尽可能多的数据到变量中(忽略任何前导空格字符,如空格、制表符或"")。
- 任何无法提取的数据都将保留在输入缓冲区中以供下次提取时使用。
因此,在您的示例中,200.40
将被提取并转换为双精度。由于输入缓冲区仍将具有i
因此它将被提取为字符。
为了理解它是如何工作的,你需要一点面向对象编程的知识。
在C++cin
是一个对象。
但你可能会问,什么是物体?
基本上,对象是一种数据结构,可以用各种运算符进行操作:
例如+
-
*
/
%
<<
>>
等。
C++中的两种类型的对象是:built-in type
和user-defined type
。
无论您是否知道,您都在使用C++对象!
例如,变量length
是内置类型double
的对象。
现在你可以用length
做什么?
好吧,它支持+
-
*
/
等等。
这是一种非常直观的类型。
现在cin
呢?cin
是用户定义类型istream
的对象。
我们知道它支持运算符>>
,称为按位右移运算符。
这个运算符(在cin
的情况下)获取给定的输入数据并将其吐出(移动)到变量中。
此运算符的一个功能是可以链接多个变量:
例如cin >> variable1 >> variable2 >> variable3;
就像在 double 类型的对象中使用运算符+
一样:
例如length + 1 + 2 + 3;
但是链中的每个变量都必须由>>
运算符分隔。
- QSqlquery prepare()和bindvalue()不工作
- 导入库可以跨dll版本工作吗
- 以螺旋方式打印矩阵的程序.(工作不好)
- 对象指针在c++中是如何工作的
- 为什么在Windows上的VS 2019和Clang 9中"size_t"在没有标题的情况下工作
- VSOMEIP-2个设备之间的通信(TCP/UDP)不工作
- 为字符串中每 N 个字符插入空格的函数没有按照我认为的方式工作?
- C++为线程工作动态地分割例程
- 为什么我的 std::ref 无法按预期工作?
- 布尔比较运算符是如何在C++中工作的
- SampleConsensusPrerejective(ext.RANSAC)是如何真正工作的
- 不确定要在我的main中放入什么才能使我的代码正常工作
- 为什么std::condition_variable notify_all的工作速度比notify_one快(对于随机请
- <<操作员在下面的行中工作
- 有人能解释一下为什么下界是这样工作的吗C++的
- ExtractIconEx:可以工作,但偶尔会崩溃
- C++中的memset函数工作不正常
- 当我在第一个循环中使用"auto"时,它工作正常,但是使用"int"它会给出错误,为什么?
- 链表c++插入,所有情况都已检查,但没有任何工作
- 为什么stream::忽略未按预期工作