输入
字符串输入
想要输入一个字符串到字符数组,一般有三种方法:
cin >>
1. 最常见的就是我们上一节中见到的,直接 cin >>
:
char a[30]{};
cin >> a;
但是这样存在一些问题。
- 一是遇到空格(或 Tab、换行)自动结束:输入
How are you?
的结果只能让a
存下"How"
; - 二是可能发生越界,如果输入超过字符数组大小的字符串会发生意外错误(即越界访问数组
a
)。
因此我们尽量只在有限的场合下使用它。
cin.getline()
2. 第二种用法是 cin.getline()
。你可以把 cin.getline
当成一个函数。这个函数可以接收两个参数:字符数组 和 最大长度。如:
此时,你可以自由地输入任何大小不超过 30 的字符串。cin.getline()
将一直读到换行符才会停止:
¶Reading input!↵
Reading input!
当输入的字符个数超过 最大长度 时会发生截断。比如上例中 cin.getline()
限制为 30 个,那么读取的时候只会将前 29 个字符和 '\0'
存入数组 a
,剩下的字符仍然停留在缓冲区中而不被读取。同时,会导致 cin
进入失败状态。关于失败状态的详细讨论将会在后面的章节中展开。
¶abcdefghijabcdefghijabcdefghijabcdefghij↵
abcdefghijabcdefghijabcdefghi
(相比 cin >>
,使用 cin.getline()
不会导致数组越界这种危险的事情发生。)
默认情况下,cin.getline()
遇到换行符才会终止。如果你愿意的话,你可以设置为别的字符,只需给它多提供一个参数就可以。比如我想让它读到字符 'r'
停止,那么就:
运行结果如:
¶Hello, world!↵
Hello, wo
注意,当 cin.getline()
读到终止字符的时候,会将其从缓冲区中拿走并抛弃,然后再向字符数组中存储一个空字符以示结束。
cin.get()
3. cin.get()
也可以当做一个函数,它的用法和 cin.getline()
几乎完全一致。比如:
¶Hi, C++!↵
¶How are you?↵
Hi, C++!
How a
是的,非常相似——不过为什么输出多了一个换行?这就是 cin.get()
和 cin.getline()
唯一不同的地方了:cin.get()
遇到终止字符后,并不会从缓冲区中拿走它。因此,在输入完第一行后,缓冲区内是这些字符:
缓冲区:{'H', 'i', ',', ' ', 'C', '+', '+', '!', '\n'}
由于 '\n'
是终止字符,所以读取到 '\n'
就会停止。但是 '\n'
仍然残留在缓冲区中……
数组 a:{'H', 'i', ',', ' ', 'C', '+', '+', '!', '\0', ... }
缓冲区:{'\n'}
所以执行 cin.get(b, 30, 'r')
的时候,首先会把这个 '\n'
读取出来,直到遇到 'r'
才会停止:
数组 b:{'\n', 'H', 'o', 'w', ' ', 'a', '\0', ...}
缓冲区:{'r', 'e', ' ', 'y', 'o', 'u', '?', '\n'}
同样地,'r'
及后面的字符全部滞留在了缓冲区中。之后在输出 b
的时候,会输出最开始的换行符,所以多了一个换行。
字符输入
下面我们来学习如何输入一个字符类型的变量。(当然了,这里就是指 char
类型。)
cin >>
1. cin >>
是最简单的输入到 char
的方法。我们在第一、二章中就已经很频繁地使用了。
char a;
cin >> a;
但是问题仍然存在,就是 cin >>
会忽略空格、Tab 和换行符(它们称为空白字符)。因此想把空格输入到一个 char
型变量是不能这样做的:
输入的空格会被跳过:
¶@ #$↵
@
#
$
这个时候就需要换一种方法了。
cin.get()
2. 你可以用 cin.get()
来替换 cin >>
,从而允许输入空格、Tab 和换行到 char
型变量中。它的用法是这样的:
这个时候空格就可以存入变量中:
¶@ #$↵
@
#
除此之外,cin.get()
还有另一种形式,它的效果是完全相同的:
这种形式的输入在某些场合特别有用。
输入其它
我们也知道 cin >>
还可用于输入整数、浮点数等。这里面并没有太多新知识,唯需了解空白字符是这类输入的终止字符,即当 cin >>
读取数时遇到空格、Tab和换行就会终止此次读取。同样地,cin >>
读取数时遇到空白字符也会忽略,所以
¶42 56↵
和
¶42↵
¶↵
¶↵
¶↵
¶↵
¶ 56↵
的效果是一致的:这些空白字符都会被忽略。
注意事项
cin.get()
在输入字符串的时候会残留终止字符,这件事情上文已经细致地说明了。因此这样的代码会让 b
“空手而归”:
¶First string!Second string!↵
a is: First string
b is:
因为第 6 行输入完成之后残留 '!'
在缓冲区中,当第 7 行再次 cin.get()
时,一上来就是终止字符,所以会直接向 b
中输入表示结束的空字符并停止读入。接下来再多的 cin.get()
,只要它读取字符串的终止字符还是 '!'
,它仍然无济于事,啥也读不到。
这个时候,你可以通过读入字符的 cin.get()
,将残留的 !
“吃掉”,打破这一僵局。
对于 cin >>
,也有同样的问题。比如这段代码输入 Hello @
后,b
并没有读入 '@'
,而是读入了之前那个空格。因为 cin >>
也不会处理残留的空格、Tab 和换行符,所以这个时候你可能需要再加入一个临时的 cin.get()
来消除影响。
在处理残留字符时,也可以用
cin.ignore()
来代替cin.get()
。它的作用是抛弃缓冲区的下一个字符,和cin.get()
的区别是返回值不同。