cin对象在抽取过程中会进行类型转换,这应该是根据字节数来的,对于每一种类型,都会有相应的指令合集,也就是cpu会按字节进行转换,区别在于大端模式或者是小端模式,cin对象从在了<<相应的函数被称为格式化输入函数,他们将数据转化为指定的格式;除此之外cin会检查输入;
流状态——cin的异常机制
cin,cout都包含一个描述流状态的数据成员,流状态是一种枚举或常量,他有三个成员:
eofbit,badbit,failbit每个元素都是一位,可设置为1或0,cin操作到文件尾时,他将设置eofbit,未能读取到预期的字符时,他将设置failbit,当破坏流的失败无法预测时,他将设定badbit,当三个状态全部为0时,那就是一切顺利,这就是异常机制,程序可以检查流状态,利用这种信息来决定下一步做什么:
CPP有专门的方法来报告流状态或改变流状态:
设置状态的函数:
clear(),setstate();他们将重置状态;clear清除围在形参列表里的状态值,setstate()则指影响形参的位;
IO状态和异常:
clear()或者setstate()设置流状态后不一定会引发异常,需要与exceptions()返回值进行比较,若返回值的某一位被设置,当前状态的对应位也被设置,那么clear()将引发ios_base::failure异常,例如两个都是badbit,如果exceptions()返回goodbit,那么将不会引发异常,ios_base::failure是从std::exception类派生而来,因此它包含一个what()方法;
使用exceptions(iostate)将表示设置哪些流状态会引发异常,这里使用OR位运算符可以指定多个参数:
cin.exceptions(badbit|eofbit|failbit);
此时这三个位任何一个被设置都将引发异常
用cin.exceptions(iostate)指出哪个位被设置会引发异常,我们回顾一下,eofbit指的是读到文件尾时,failbit未读到预期的字符时,badbit指无法诊断的失败破坏流时,将他们传入exceptions后,读入过程中位被设置则引发异常;
cin.exceptions(ios_base::failbit);
这段代码指出,当流读到与预期字符不符的类型时将引发异常;
int input;
int sum = 0;
try {
while (cin >> input)
{
sum += input;
}
}
catch (ios_base::failure& bf)
{
cout << bf.what();
cout << "O!the error\n";
}
cout << "Last value entered=" << input<<endl;
cout<<"Sum = "<<sum<<endl;
流状态的影响:
设置流状态位后,流将对后面的输入输出关闭,知道位被清除(用clear()),此后为了继续读入,必须跳过错误,对于failbit,使用isspace(cin.get())跳过字符一直到空白字符处,即两步:
1.用clear()重置状态;
2.跳过错误,(对于failbit使用isspace(cin.get())到达空白字符处)
cin.exceptions(ios_base::failbit);
while (cin >> input) {
sum += input;
}
cin.clear();
重置位
while (!isspace(cin.get())) {
continue;
}
跳过非空白字符;
cin >> input;
与上边的while循环效果相同
while (cin.get()!='\n') {
continue;
}
下边是包含异常后的程序代码:
cin.exceptions(ios_base::failbit);
这段代码指出,当流读到与预期字符不符的类型时将引发异常;
int input;
int sum = 0;
while (cin >> input) {
sum += input;
}
cout << "Last value entered=" << input << endl;
cout << "Sum = " << sum << endl;
if (cin.fail() && !cin.eof()) {
cin.clear();
while (!isspace(cin.get())) { continue; }
}
else {
cout << "i can not go on!\n";
exit(1);
}
cout << "Now enter a new number: ";
cin >> input;
其他istream方法:get()和getline();
他们被称为非格式化函数,因为他们只是读取字符输入,并不进行数据类型转换;
get(char*,int ,char)和getline(char*,int,char)在默认情况下读取的是一整行(知道换行符\n)而不是一个单词;
get(char&)和get(void)提供不跳过空白的单字符输入功能;
单字符输入:
get()读取下一个输入字符,他们只能通过模拟文件尾来终止,cin可以通过上边的异常设置终止;
字符串输入:getline(),get(),ignore();
第一个参数是字符串首地址,第二个参数比要读取的最大字符数大1,(留一个位存放空字符,以存放C风格的字符串),第三个参数指定用作分界符的字符,只有两个参数的版本将换行符用作分界符,上述函数都在读取最大数目的字符或遇到换行符后为止,get()与getline()的区别是getline()将不保留换行符;get()将保存;对于分界符两个函数的方法是一样的;
ignore(int,char),第一个是能读取的最大字符数,第二个是分界符,ignore读取分界符之后的字符,之前的全部丢弃,除非达到最大字符数值,
istream&ignore(int =1,int =EOF);默认参数EOF将导致函数读取指定数目的字符或者读取到文件尾;
//ignore()