input输入操作符>>
对类型敏感,也就是说它根据待输入的变量的类型来输入。比如
int main
{
string name; int age;
cin>>name;
cin>>age;
}
如果,键入Kathy 18
,>>
操作符会将Kathy
读入name,18
读入age。为什么不会将整个输入Kathy 18
读入name呢?这是因为对字符串的读取终止于空格,比如单个空格、换行或者Tab字符。此外,空格会被>>
忽略掉,如果你在一个输入的数字之前键入很多空格,>>
会忽略那些空格只读入数字。
如果不按照类型来输入会怎么样呢?比如我们键入18 Kathy
,18
会被作为一连串的字符读入name
,此外,由于Kathy
不是整数,将不会被读取到,age的值是一个无意义的随机数(程序执行时age所在的内存单元存储的值),这是因为,我们没有对age进行初始化赋值,也没有成功地给age读取一个值。对于由于输入格式导致的失败更详细的介绍在下一节。
修改上述程序
int main()
{
string name; int age;
cin >> name >> age;
cout << "Hello, " << name <<"(age:" << age << ")" << endl;
}
注意,我们可以在一条输入命令中输入多个变量的值,同样,我们也可以在一条输出命令中输出多个变量的值。
一个string
用>>
读取输入数据是默认把空格作为终止标志,也就是说只能读入单个单词。但是如果我们想要读入多个单词怎么办呢?比如我们想要读入完整的姓名比如Kathy Chen
,最简单的方法就是使用两次>>
,比如
string first_name, last_name;
cin >> first_name >> last_name;
此外要注意,对于数值类型,在输入时,我们可以输入表达式,比如
int age;
cin >> age;
输入5*2
,age的值会读入为10。
>>
是对变量类型敏感的,如果我们键入的类型错误的数据,比如对于待输入的整型变量,键入了字符串,就会发生错误,不能继续输入。
int main()
{
string name; int num1, num2;
cin >> name >> num1;
cout << "Name:" << name << "Num1:" << num1 << endl;
cin >> num2;
cout << "Num2:" << num2 <<endl;
}
如果输入test wrtype
,会发现num2无法输入了。因此,num1是int类型的,而wrtype是一个字符串,因此cin进入了错误状态。
在《C++ Primer Plus》的第六版第六章介绍了cin输入流的机制:
当遇到无效字符或遇到文件结束符(不是换行符,是文件中的数据已读完)时,输入流cin就处于出错状态,即无法正常提取数据。此时,对cin流的所有提取操作将终止。在 IBM PC及其兼容机中,以Ctrl + Z表示文件结束符。在UNIX和Macintosh系统中,以 Ctrl + D表示文件结束符。当输入流cin处于出错状态时,如果测试cin的值,可以发现它的值为false(假),即cin为0值。如果输入流在正常状态,cin的值为true(真),即cin为 一个非0值。可以通过测试cin的值,判断流对象是否处于正常状态和提取操作是否成功。如:
if(!cin.good()) //if表达式判断为真时cin输入流处于出错状态,无法正常提取数据
cout<<"error";
常量 | 含义 | failbit标记位的值 | eofbit标记位的值 | badbit标记位的值 | 转化为10进制 |
---|---|---|---|---|---|
ios::failbit | 输入(输出)流出现非致命错误,可挽回 | 1 | 0 | 0 | 4 |
ios::badbit | 输入(输出)流出现致命错误,不可挽回 | 0 | 0 | 1 | 2 |
ios::eofbit | 已经到达文件尾 | 0 | 1 | 0 | 1 |
ios::goodbit | 流状态完全正常 | 0 | 0 | 0 | 0 |
分别对应cin.fail(), cin.bad(), cin.eof(), cin.good()
C++将输入看作是流入程序的字符流,iostream文件定义cin为这种流的对象。对应的输入都会先存入输入缓冲区,cin从输入缓冲区中读入数据,所以当缓冲区中有数据残留时,cin直接取得残留数据而不会请求键盘输入。cin是以空格(单个空格,多个空格,tab,回车)分隔的,空格不进入缓冲区。
cin.clear() 清除cin的错误状态
cin.clear()用处在于如果输入发生错误,那么流状态被标记为错误,你必须清除这些错误状态,以使你的程序能正确适当地继续运行。
cin.ignore(int n, char c)
cin.ignore(5, ‘c’)是从数据流(cin)中提取字符,提取的字符被忽略(ignore),不被使用。每抛弃一个字符,它都要技术和比较字符,如果计数值达到5或者被抛弃的字符是’c’,则函数指定终止,否则它继续等待输入。如果你用ignore(4)而缓冲区中只有三个字符,那么接下来的输入的那个也要被ignore。==它的一个常用功能就是用来清除以回车结束的输入缓冲区的内容,消除上一次输入对下一次输入的影响。
// 把回车之前(上一次输入)的字符从输入缓冲区中清除出去
std::cin.clear() ; // to be safe, clear error flags which may be set
std::cin.ignore(std::numeric_limits<int>::max(), '\n');
cin.sync 输出与输入同步,如果这时候缓区不空就打印出来。sync时输入输出都清空,输入是丢掉,输出是打印出来。网上很多说法是用于清空输入缓冲区,但这个东西的原意是同步输入流,由于各个编译器对同步功能的实现不同,很可能无法清空缓冲区,因此,建议使用cin.ignore来完成清空缓冲区的操作。
Does cin.sync() always work?
关于cin.sync()的解释
第一步重置cin以接受新的输入是要最先做的,一般用成员函数clear();形式为cin.clear();如果省略这条语句,程序将拒绝继续读取输入。cin.clear()是用来更改cin的状态标示符的。通俗的讲就是将一个出错的“流”恢复为“好”,并设置goodbit状态位。
示例:
int main()
{
int num; int num2;
if (!(cin >> num >> num2))
{
cerr << "input error! please input again!" << endl;
cin.clear();
int len = numeric_limits<int>::max();
cin.ignore(len , '\n');
auto a = cin.good();
}
return 0;
}