cin、cin.get()、getline()详解
int main()
{
char str[8];
cin.getline(str, 5);
cout << str << endl;
cin.getline(str, 5);
cout << str << endl;
return 0;
}
程序执行情况:
测试一:abcd (回车)abcd (输出)efgh(回车)efgh (输出)当用户第一次输入的字符串字符数小于4时,程序执行正常!
测试二:abcdefgh (回车)abcd (输出) (输出-换行)当用户第一次输入的字符数字符数大于4时,第一个字符串接受输入的前四个字符,而第二次的输入操作没有执行,第二个字符串输出为空。(getline超长检测,不会执行之后的cin)
1、cin >>
cin>>该输入操作符是根据后面变量的类型读取数据。输入结束条件 :遇到Enter、Space、Tab键。(这个很重要!)对结束符的处理 :当第一个字符为分隔符时丢弃缓冲区中的结束符,当还存在其他cin输入时,会输出下一个非结束符字符串数据。
重要:当cin>>从缓冲区中读取数据时,若缓冲区中第一个字符是空格、tab或换行这些分隔符时,cin>>会将其忽略并清除,继续读取下一个字符,若缓冲区为空,则继续等待。但是如果读取成功,字符后面的分隔符是残留在缓冲区的,cin>>不做处理。(理解)
int main()
{
char str1[10], str2[2];
cin >> str1;
cin >> str2;
cout << str1 << endl;
cout << str2 << endl;
return 0;
}
注意:
- 在测试用例的时候发现一个问题,就是当输入长度大于实际数组长度的时候,’\0’的位置并不在str[length-1]的位置,会在(str+输入字符长度-1)的位置,所以在输出str的时候,str的字符数组长度并不是定义的length,而是输入字符长度reallentth。
当输入两字符数组时,输入长度小于数组定义长度,两数组正常输出。但是当输入长度大于数组定义长度时,遇到一个问题就是str1数组内的数据被重写了。根究发现,系统分配的地址空间str1在后,而 str2在前,当str读取的数据长度使得str2数据地址和str1的数据地址重叠,就有可能导致str1数据重写。以下是分析代码:
int main()
{
char str1[10], str2[2];
for (int i = 0; i < 10; i++)
{
cout << (void*)(str1+i) << endl;
}
for (int j = 0; j < 2; j++)
{
cout << (void*)(str2 + j) << endl;
}
cin >> str1;
cin >> str2;
cout << str1 << endl;
cout << str2 << endl;
return 0;
}
输出:
:
2、cin.get()
该函数有三种格式:无参,一参数,二参数即cin.get(),cin.get(char ch), cin.get(array_name, Arsize) 读取字符的情况:输入结束条件:Enter键对结束符处理:不丢弃缓冲区中的Enter、space和TAB(重要)。cin.get()与cin.get(char ch)用于读取字符,他们的使用是相似的,即:ch=cin.get()与cin.get(ch)是等价的。
cin.get(array_name, Arsize)是用来读取字符串的,可以接受空格字符,遇到Enter结束输入,按照长度(Arsize)读取字符, 会丢弃最后的Enter字符(重要,但是不丢弃SPACE和TAB)。
3、cin.getline()
cin.getline()与 cin.get(array_name,Arsize)的读取方式差不多,以Enter结束,可以接受空格字符。按照长度(Arsize)读取字符, 会丢弃最后的Enter字符。但是这两个函数是有区别的:cin.get(array_name, Arsize)当输入的字符串超长时,不会引起cin函数的错误,后面的cin操作会继续执行,只是直接从缓冲区中取数据。但是cin.getline()当输入超长时,会引起cin函数的错误,后面的cin操作将不再执行。
4、cin错误函数
cin的错误处理机制,并且学习几个重要的函数:cin.fail(), cin.bad(), cin.good(), cin.clear(), cin.ignore()等。
ios::badbit 001 输入(输出)流出现致命错误,不可挽回
ios::eofbit 010 已经到达文件尾
ios::failbit 100 输入(输出)流出现非致命错误,可挽回
ios::goodbit 000 流状态完全正常, 各异常标志位都为0
相应的函数1 or true if rdstate & XXbit is nonzero; otherwise 0。
cin.clear()的作用是重置错误标志。
int main()
{
char ch, str[20];
cin.getline(str, 5);
cout << "flag1:" << cin.good() << endl; // 查看goodbit状态,即是否有异常
cin.clear(); // 清除错误标志
cout << "flag1:" << cin.good() << endl; // 清除标志后再查看异常状态
cin >> ch;
cout << "str:" << str << endl;
cout << "ch :" << ch << endl;
return 0;
}
重置错误标志还不够!要是能将缓冲区的残留数据清空了就好了哦!下面我们再来看一个很重要的函数!
basic_istream&ignore(streamsize _Count = 1, int_type _Delim = traits_type::eof());
这个函数用来丢弃输入缓冲区中的字符,第一参数定义一个数,第二个参数定义一个字符变量。下面解释一下函数是怎样执行的:函数不停的从缓冲区中取一个字符,并判断是不是_Delim,如果不是则丢弃并进行计数,当计数达到_Count退出,如果是则丢弃字符退出。例:cin.ignore(5, 'a'); 函数将不断从缓冲区中取一个字符丢弃,直到丢弃的字符数达到5或者读取的字符为'a'。