C++ 学习之十、C++ 输入总结

C++ 输入 cin 使用方式繁多,以下来总结一下至今的使用方式。

cin >> 从缓冲区读取数据

使用 cin 进行输入时,程序将输入视为一系列的字节,其中每个字节都被解释为字符编码。不管目标数据类型是什么,输入一开始都是字符数据——文本数据。然后 cin 对象负责将文本转换为其他类型。

cin >> 从缓冲区中读取数据时,若缓冲区中第一个字符是空格、tab 或换行这些分隔符时,cin >> 会将其忽略并清除,继续读取下一个字符,若缓冲区为空,则继续等待。但是如果读取成功,字符后面的分隔符是残留在缓冲区中的,cin >> 不做处理。

例如有如下示例输入行:

38.5 19.2

输入类型为 char 字符

1
2
char ch;
cin >> ch;

输入行的第一个字符也即字符 3 被赋值给 ch

输入类型为 int

1
2
int n;
cin >> n;

cin 将不断读取,直到遇到非数字字符。注意 cin 都是以字符读取,它将读取 3 和 8,这样句点将成为输入队列中的下一个字符。cin 通过计算发现,这两个字符对应的数值为 38,因此将 38 的二进制编码复制到变量 n 中。

输入类型为 double

1
2
double x;
cin >> x;

和上面类似,cin 将不断读取,直到遇到第一个不属于浮点数的字符,这里在读取到空格时停止,使得空格成为输入队列中的下一个字符。将 38.5 赋值给变量 x。

输入类型为 char []

1
2
char word[50]
cin >> word;

cin 将不断读取,直到遇到空白字符。也就是说,它读取 3、8、句点和 5,使得空格成为输入队列中的下一个字符。然后,cin 将这 4 个字符的字符编码存储到数组 word 中,并在末尾加上一个空字符。

cin.get() 用法

该函数有多种重载形式,分为四种格式:无参,一参数,二参数,三个参数。常用的函数原型如下:

1
2
3
4
int get();
istream& get(char& var);
istream& get(char *s, streamsize n);
istream& get(char *s, streamsize n, char delim);

其中 streamsize 在 VC++ 中被定义为 long long 类型。

cin.get() 读取一个字符

读取一个字符,可以使用 cin.get() 或者 cin.get(var),示例如下:

1
2
3
4
5
6
7
8
9
10
11
#include <iostream>
using namespace std;

int main()
{
char a, b;
a = cin.get();
cin.get(b);
cout << a << b << endl;
return 0;
}

Tips: cin.get() 返回值是 int 类型,成功则返回读取字符的 ASCII 码值。cin.get(char var) 成功返回的是 cin 对象。

cin.get() 读取一行

读取一行可以使用以下函数:

1
2
istream& get(char *s, streamsize n);
istream& get(char *s, size_t n, streamsize n);

二者的区别是前者默认以换行符结束,后者可指定行结束符。n 表示目标空间的大小。

示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
using namespace std;

int main()
{
char a;
char array[20] = {};
cin.get(array, 20);
cin.get(a);
cout << array << " " << int(a) << endl;
return 0;
}

输入:123456789[回车],输出如下:

1
123456789 10

cin.get(array, 20); 读取一行,遇到换行时结束读取,但没有对换行符处理,接下来 cin.get(a) 将队列中的换行符读入变量 a 中,输出换行符的 ASCII 码值 10。

cin.get(str, size) 读取一行时,只能将字符串读入 C 风格的字符串中,即 char*,但是 cin.getline() 函数可以将字符串读入 C++ 风格的字符串 string 中,所以建议使用 cin.getline() 读取行。

cin.getline() 读取一行

函数作用:从标准输入设备键盘读取一串字符串,并以指定的结束符结束。函数原型有两个:

1
2
istream& getline(char *s, streamsize count);    // 默认以换行符结束
istream& getline(char *s, streamsize count, char delim);

使用示例:

1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
using namespace std;

int main()
{
const int ArSize = 20;
char array[ArSize] = {};
cin.getline(array, ArSize);
// cin.getline(array, ArSize, '\n'); // 使用此语法指定结束符
cout << array << endl;
return 0;
}

Tips: cin.getline()cin.get() 的区别在于,前者不会将行结束符(如换行符)残留在输入缓冲区中。

cin 的条件状态

使用 cin 读取键盘输入时,可能会发生一些错误,cin 将设置条件状态(condition state)。条件状态位有:

1
2
3
4
goodbit(0x0): 无错误
eofbit(0x1): 已到达文件尾
failbit(0x2): 非致命的输入/输出错误,可挽回
badbit(0x4): 致命的输入/输出错误,无法挽回

与这些条件状态对应的就是设置、读取和判断条件状态的流对象的成员函数。它们主要有:

1
2
3
4
5
6
7
s.eof(): 若流 s 的 eofbit 置位,则返回 true
s.fail():若流 s 的 failbit 置位,则返回 true
s.bad():若流 s 的 badbit 置位,则返回 true
s.good():若流 s 的 goodbit 置位,则返回 true
s.clear(flags):清空当前状态, 然后把状态设置为 flags,返回 void
s.setstate(flags):不清空当前状态,设置给定的状态 flags,返回 void
s.rdstate():返回流 s 的当前条件状态,返回值类型为 ios_base::iostate