C和C++中标准输入中遇到的问题
2017-10-23 20:05
176 查看
C和C++中的标准输入都是库函数,在输入的时候应该注意一些问题。在控制台输入的数据都是字符串,然后通过类型转换存放到变量中。
比如scanf和cin都会有一些限制。它们会忽略在第一个非空格或者非换行符之前的空格和换行符,意思是会跳过这些字符,但是如果在非空格字符之后遇到空格或者换行符,就会停止继续读取,可以下次继续读取,而不必输入。
但是格式控制符确定了读取的字符是否可以转换想要的值,并存放到指定的变量中,如果类型转换出错,就会停止读取数据,而且会设置错误标志,以至于后面的字符不能被继续读取。
以下就举一个例子:
当我们输入不同的字符串,就会产生不同的效果:
(1)输入:hello 2 world
输出:
hello
2
world
分析:一次输入三个数据,中间用空格隔开,读取时会分别读取三组数据,只要类型正确就行。
(2)输入:hello world 2
输出:
hello
-858993460
分析:由于类型转换异常,所以后面的2并没有被读取到。
(3)
输入:helloworld
输出:helloworld
输入:2
输出:2
输入:haha
输出:haha
分析:可以一次一次的输入,只要类型正确,就可以读取到所有输入。
cin的条件状态
使用cin读取键盘输入时,难免发生错误,一旦出错,cin将设置条件状态(condition state)。条件状态标识符号有:
(1)goodbit:无错误
(2)eofbit:已到达文件尾
(3)failbit:非致命的输入/输出错误,可挽回
(4)badbit:致命的输入/输出错误,无法挽回
若在输入输出类里,需要加ios::标识符号。与这些条件状态对应的就是设置、读取和判断条件状态的流对象的成员函数。他们主要有:
(1)s.eof():若流s的eofbit置位,则返回true;
(2)s.fail():若流s的failbit置位,则返回true;
(3)s.bad():若流s的badbit置位,则返回true;
(4)s.good():若流s的goodbit置位,则返回true;
s.clear(flags):清空状态标志位,并将给定的标志位flags置为1,返回void。
s.setstate(flags):根据给定的flags条件状态标志位,将流s中对应的条件状态位置为1,返回void。
s.rdstate():返回流s的当前条件状态,返回值类型为strm::iostate。strm::iostate 是机器相关的整型名,由各个iostream类定义,用于定义条件状态。
了解以上关于输入流的条件状态与相关操作函数,下面看一个因输入缓冲区未读取完造成的条件状态位failbit被置位,再通过clear()复位的例子。
输入:12345
输出:
flag:0
flag:1
str:1234
ch :5
分析:
flag代表是否有错误,为0表示有错误,为1表示没有错误。由于输入的字符串中第5个字符不是’\0’,所以cin.good()返回值是false,即就是0。通过调用cin.clear(),清除了错误状态标志,所以cin.good()就会返回true,打印出来的结果是flag:1。这时才可以继续读取剩下的字符’5’。
可以看出,因输入缓冲区未读取完造成输入异常,通过clear()可以清除输入流对象cin的异常状态,不影响后面的cin>>ch从输入缓冲区读取数据。因为cin.getline读取之后,输入缓冲区中残留的字符串是:5[换行符],所以cin>>ch将5读取并存入ch,打印输入并输出5。
如果将clear()注释,cin>>ch;将读取失败,ch为空。
cin.clear()等同于cin.clear(ios::goodbit);因为cin.clear()的默认参数是ios::goodbit,所以不需显示传递,故而你最常看到的就是:cin.clear()。
参考:http://blog.csdn.net/k346k346/article/details/48213811
比如scanf和cin都会有一些限制。它们会忽略在第一个非空格或者非换行符之前的空格和换行符,意思是会跳过这些字符,但是如果在非空格字符之后遇到空格或者换行符,就会停止继续读取,可以下次继续读取,而不必输入。
但是格式控制符确定了读取的字符是否可以转换想要的值,并存放到指定的变量中,如果类型转换出错,就会停止读取数据,而且会设置错误标志,以至于后面的字符不能被继续读取。
以下就举一个例子:
#include <iostream> using namespace std; int main() { char str[15]; cin>>str; cout<<str<<endl; int a; cin>>a;//输入流破坏,禁止继续读。 cout<<a<<endl; //cin.clear();//清理错误状态 cin>>str; cout<<str<<endl; return 0; }
当我们输入不同的字符串,就会产生不同的效果:
(1)输入:hello 2 world
输出:
hello
2
world
分析:一次输入三个数据,中间用空格隔开,读取时会分别读取三组数据,只要类型正确就行。
(2)输入:hello world 2
输出:
hello
-858993460
分析:由于类型转换异常,所以后面的2并没有被读取到。
(3)
输入:helloworld
输出:helloworld
输入:2
输出:2
输入:haha
输出:haha
分析:可以一次一次的输入,只要类型正确,就可以读取到所有输入。
cin的条件状态
使用cin读取键盘输入时,难免发生错误,一旦出错,cin将设置条件状态(condition state)。条件状态标识符号有:
(1)goodbit:无错误
(2)eofbit:已到达文件尾
(3)failbit:非致命的输入/输出错误,可挽回
(4)badbit:致命的输入/输出错误,无法挽回
若在输入输出类里,需要加ios::标识符号。与这些条件状态对应的就是设置、读取和判断条件状态的流对象的成员函数。他们主要有:
(1)s.eof():若流s的eofbit置位,则返回true;
(2)s.fail():若流s的failbit置位,则返回true;
(3)s.bad():若流s的badbit置位,则返回true;
(4)s.good():若流s的goodbit置位,则返回true;
s.clear(flags):清空状态标志位,并将给定的标志位flags置为1,返回void。
s.setstate(flags):根据给定的flags条件状态标志位,将流s中对应的条件状态位置为1,返回void。
s.rdstate():返回流s的当前条件状态,返回值类型为strm::iostate。strm::iostate 是机器相关的整型名,由各个iostream类定义,用于定义条件状态。
了解以上关于输入流的条件状态与相关操作函数,下面看一个因输入缓冲区未读取完造成的条件状态位failbit被置位,再通过clear()复位的例子。
#include <iostream> using namespace std; int main() { char ch, str[20]; cin.getline(str, 5);//只接收5个字符的输入,最后一个是'\0' cout<<"flag:"<<cin.good()<<endl; // 查看goodbit状态,即是否有异常 cin.clear(); // 清除错误标志 cout<<"flag:"<<cin.good()<<endl; // 清除标志后再查看异常状态 cin>>ch; cout<<"str:"<<str<<endl; cout<<"ch :"<<ch<<endl; return 0; }
输入:12345
输出:
flag:0
flag:1
str:1234
ch :5
分析:
flag代表是否有错误,为0表示有错误,为1表示没有错误。由于输入的字符串中第5个字符不是’\0’,所以cin.good()返回值是false,即就是0。通过调用cin.clear(),清除了错误状态标志,所以cin.good()就会返回true,打印出来的结果是flag:1。这时才可以继续读取剩下的字符’5’。
可以看出,因输入缓冲区未读取完造成输入异常,通过clear()可以清除输入流对象cin的异常状态,不影响后面的cin>>ch从输入缓冲区读取数据。因为cin.getline读取之后,输入缓冲区中残留的字符串是:5[换行符],所以cin>>ch将5读取并存入ch,打印输入并输出5。
如果将clear()注释,cin>>ch;将读取失败,ch为空。
cin.clear()等同于cin.clear(ios::goodbit);因为cin.clear()的默认参数是ios::goodbit,所以不需显示传递,故而你最常看到的就是:cin.clear()。
参考:http://blog.csdn.net/k346k346/article/details/48213811
相关文章推荐
- C++重载输入和输出操作符以及IO标准库中的刷新输入缓冲区残留字符问题
- C++重载输入和输出操作符以及IO标准库中的刷新输入缓冲区残留字符问题
- C++重载输入和输出操作符以及IO标准库中的刷新输入缓冲区残留字符问题
- 遇到shell重定向的一个奇怪问题:'消失'的标准输入!
- C\C++中键盘输入问题
- ios下可编辑div,遇到scrollbar,无法输入的问题
- 从C++到C#,我遇到的几个问题
- C#调用C++Dll封装时遇到的一系列问题
- C++模板遇到iterator时候遇到的问题和解决方法
- 关于winodows下编程c++遇到的引用文件路径问题
- C++补漏_标准输入流
- C++编写网页控件,遇到的问题总结
- (转)c++--使用CURL库在编译时遇到的问题
- 关于流和缓冲区的理解以及一般标准输入问题的解决方法小结
- C/C++ 日常使用遇到的一些问题与解决
- Win10系统中Sublime text 3 配置完C/C++IDE后遇到的问题
- 关于MFC中数据库操作中遇到的问题:Microsoft C++ 在xxx内存处出现问题_com_error的另一解决方案
- Face Alignment at 3000FPS(C++版)工程配置遇到的小问题
- 使用标准C读取文件遇到的结构体对齐问题及其解决办法
- C++输入字符串输入问题(二)