您的位置:首页 > 编程语言 > C语言/C++

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

2017-10-23 20:05 176 查看
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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: