0x00 字符串输入
cin
使用空白来确定字符串的结束位置,这意味着cin
在获取字符数组输入时只读取一个单词。读取该单词后,cin
将该字符串放到数组中,并自动在结尾添加空字符\0
。
注:C风格字符串以空字符结尾,空字符被写作\0
,其ASCII码为0,用来标记字符串的结尾。
0x10 每次读取一行字符串输入
大多时候,每次读取一个单词不是最好的选择。
头文件istream
中的类(如cin
)提供了一些面向「行」的类成员函数:getline()
和get()
。这两个函数都读取一行输入,直至到达换行符。然而,随后getline()
将丢弃换行符,而get()
将换行符保留在输入序列中。
0x11 面向行的输入:getline()
getline()
函数读取整行,它使用通过回车键输入的换行符来确定输入结尾。要调用这个函数,可以使用cin.getline()
。
该函数有两个参数:
- 第一个参数是用来存储输入行的数组的名称;
- 第二个参数是要读取的字符数;
getline()
成员函数在读取指定数目的字符或遇到换行符时停止读取。
例如,在使用该函数将姓名读取到一个包含20个元素的name
数组时,可以这样使用: cin.getline(name, 20);
0x12 面向行的输入:get()
cin类还有一个名为get()的成员函数,该函数有几种变体。
其中有一种变体的工作方式与getline()类似,它们接受的参数相同,解释参数的方式也一样,并且都读到行尾。但get并不再读取并丢弃换行符,而是将其留在输入队列中。假设我们连续两次使用get():
1 | cin.get(name1, len); |
由于第一次调用后,将换行符留在了输入队列中,因此第二次调用时看到的第一个字符便是换行符,此时,因为get(name2,len)
并不能读取换行符,所以它会认为已经到达行尾了,并没有发现任何可以读取的内容。因此,如果不借助其他帮助,第二次调用将无法跨过换行符来读取内容。
而get()函数的另一种变体,使用不带任何参数的cin.get()调用可以读取下一字符(可以是换行符)。因此可以使用它来处理换行符。例如:
1 | cin.get(name1, len); |
另一种方式是将两个类成员函数变体拼接起来,如下所示:
1 | cin.get(name1, len).cin.get(); // 读取字符串后继续读取掉换行符 |
之所以可以这样使用是因为cin.get(name1, len)
返回一个cin
对象,该对象可以用来继续调用get()
函数。
0x20 混合输入字符串和数字所带来的问题
C++中混合输入面向行的字符串和数字会导致问题。例如:
1 | int age; |
这样使用会导致cin.getline()
读取到一个空字符串,原因在于当cin
在读取age
时会将回车键生成的换行符留在了输入队列,而后面的cin.getline()
在看到换行符后,将认为这是一个空行,并将一个空字符串数组赋给name
数组。
解决方法是:在使用cin.getline(name, 30)
读取整行字符串之前,先使用cin.get()
读取并丢弃换行符。