C和C++中标准输入中遇到的问题

来源:互联网 发布:软件测试简单吗 编辑:程序博客网 时间:2024/05/20 23:06

C和C++中的标准输入都是库函数,在输入的时候应该注意一些问题。在控制台输入的数据都是字符串,然后通过类型转换存放到变量中。

比如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

原创粉丝点击