使用cin获取用户的输入信息
cin(隶属于istream)是供使用者输入用的标准输入通道,对应于C的stdin。操作系统通常将它和键盘连接,用来接受用户从键盘输入进来的数据。下图描述了cin是如何从键盘获取用户数据的过程:
来自键盘的输入首先会被送到”输入缓冲区“(streambuf),接受变量然后再从”输入缓冲区“中获取数据。
“输入缓冲区” 通过以下代码获取:
streambuf* inputBuf = cin.rdbuf();
可以使用 << get() getline() 三种方式获取用户的输入信息。
说明:'\t' -- 制表符 ' ' -- 空格 '\n' -- 回车
cin的一些特点:
(1) cin可以通过 空格、制表符、回车 来界定字符串,也可以自定义界定字符。
(2)cin在某些情况下会失效(即:无法再通过cin获取用户输入到指定的接受变量中,调用cin中的”>>“、”get“、”getline“函数时,程序不会再挂起等待用户输入)。
(3)”>>“ 使用 空格、制表符、回车 来界定字符窜。
”get“ / ”getline“ 默认使用 回车 来界定字符窜(用于读取一行数据),也可自定义界定字符。
具体细节见后文分析:
【<<】
int x;
cin << x;
1. 当键入:” 56“,并回车结束输入,x将被赋值为56,且此时”输入缓冲区“中还会残留一个”\n“。
2. 当键入:” \t\t32 \t “,并回车结束输入,x将被赋值为32,且此时”输入缓冲区“中残留” \t \n“。
3. 当键入:”32 56 78“,并回车结束输入,x将被赋值为32,且此时”输入缓冲区“中残留” 56 78\n“。
【int get() / istream& get(char& c)】 /*永远都不会失效*/
如果“输入缓冲区”中有数据,就取出“输入缓冲区”的第一个字节,并返回该字节,且从“输入缓冲区”中删除该字节。
--如:当”输入缓冲区“为空,这程序会挂起,等待用户输入。
--如:当”输入缓冲区“为”\n“
int get()返回‘\n'的ASCII码值
istream& get(char& c) 返回当前cin对象,c=’\n'。
然后从“输入缓冲区”中删除‘\n’字符,则当前缓冲区变为空。
--如:当”输入缓冲区“为”\ts 56\t\n“
int get()返回‘\t'的ASCII码值
istream& get(char& c) 返回当前cin对象,c=’\t'。
然后从“输入缓冲区”中删除‘\t’字符,则当前缓冲区变为“s 56\t\n”。
【istream& get(char* s, int n) / istream& get(char* s, int n, char delim)】
istream& get(char* s, int n) 以回车来界定字符窜。
istream& get(char* s, int n, char delim) 通过'char delim' 来指定界定字符。
这两个函数均会从“输入缓冲区”中获取n-1个字符,而s[n-1]不会被用来接收数据,会被恒置为'\0'。
/* 以istream& get(char* s, int n) 举例 */
1. 如果输入缓冲区中的字符数为m(不包括最后一个的'\n'回车符),少于n-1个字符,则余下用'\0'来填充。
--如:当前的缓冲区为“\tab23\n”,执行get(chs, 10);执行完后,chs = "\tab23\0\0\0\0\0",缓冲区变为:“\n”,cin输入流的状态为有效。
2. 如果输入缓冲区中的字符数为0(不包括最后一个的'\n'回车符)。
--如:当前的缓冲区为“\n”,执行get(chs, 3);执行完后,chs="\0",缓冲区变为:“\n”,cin输入流的状态变为失效。
3. 如果输入缓冲区中的字符数为m(不包括最后一个的'\n'回车符),等于n-1个字符。
--如:当前的缓冲区为“sdrgh23\n”,执行get(chs, 8);执行完后,s = "sdrgh23\0",缓冲区变为:“\n”,cin输入流的状态为有效。
4. 如果输入缓冲区中的字符数为m(不包括最后一个的'\n'回车符),大于n-1个字符。
--如:当前的缓冲区为“c ghy4nm\n”,执行get(chs, 5);执行完后,s = "c gh\0",缓冲区变为:“y4nm\n”,cin输入流的状态为有效。
【istream& getline(char* s, int n) / istream& getline(char* s, int n, char delim)】
istream& getline(char* s, int n) 以回车来界定字符窜。
istream& getline(char* s, int n, char delim) 通过'char delim' 来指定界定字符。
这两个函数均会从“输入缓冲区”中获取n-1个字符,而s[n-1]不会被用来接收数据,会被恒置为'\0'。
/* 以istream& getline(char* s, int n) 举例 */
1. 如果输入缓冲区中的字符数为m(不包括最后一个的'\n'回车符),少于n-1个字符,则余下用'\0'来填充。
--如:当前的缓冲区为“\tab23\n”,执行getline(chs, 10);执行完后,s = "\tab23\0\0\0\0\0",缓冲区变为空,cin输入流的状态为有效。
2. 如果输入缓冲区中的字符数为0(不包括最后一个的'\n'回车符)。
--如:当前的缓冲区为“\n”,执行getline(chs, 3);执行完后,s = "\0\0\0",缓冲区变为空,cin输入流的状态为有效。
3. 如果输入缓冲区中的字符数为m(不包括最后一个的'\n'回车符),等于n-1个字符。
--如:当前的缓冲区为“sdrgh23\n”,执行getline(chs, 8);执行完后,s = "sdrgh23\0",缓冲区变为空,cin输入流的状态为有效。
4. 如果输入缓冲区中的字符数为m(不包括最后一个的'\n'回车符),大于n-1个字符。
--如:当前的缓冲区为“c ghy4nm\n”,执行getline(chs, 5);执行完后,s = "c gh\0",缓冲区变为:“y4nm\n”,cin输入流的状态变为失效。
失效 -- 可怕的噩梦
失效【failbit】意味着接收变量无法再从“输入缓冲区”中获得数据,而且程序也不会挂起以等待用户的键盘输入。
失效发生后,接收变量不会得到任何值,保持原有的值。
这种情况下,并需重置状态为【goodbit】,才能使接收变量从“输入缓冲区”中获取数据。
PS: failbit为4 goodbit为0 还有2钟状态:badbit eofbit
获取cin的状态
int state = cin.rdstate();
bool isgood = cin.good(); // 是否为goodbit状态
bool isfail = cin.fail(); // 是否为failbit状态
bool isbad = cin.bad(); // 是否为badbit状态
bool iseof = cin.eof(); // 是否为eofbit状态
设置cin的状态
int state = 0; cin.setstate(state);
清除cin的状态 // 即置为goodbit
cin.clear();
cin会在下面3种情况下发生失效:
1. 类型不匹配
初始状态:“输入缓冲区”为空
double d = 0.0;
cin >> d; // 此时从键盘键入“sdr” ,并回车。
由于双精度类型的数无法接收“sdr”,故会发生失效,且此时的“输入缓冲区”内容为“sdr\n”。
2. 空数据
初始状态:“输入缓冲区”为空
char chs[3] = {'a', 'b', 'c'};
cin.get(chs, 3); // 此时不输入任何数据,直接按回车键。
发生失效,且此时的chs = “\0bc” “输入缓冲区”内容为“\n”。
3. 接收字符窜长度不够
初始状态:“输入缓冲区”为空
char chs[3] = {0};
cin.getline(chs, 3); // 此时从键盘键入“sdrgh” ,并回车
发生失效,且此时的chs = “sd\0” “输入缓冲区”内容为“rgh\n”。
(全文完 欢迎评论)