14.5.2 输入流与格式状态字

    在前面提到的格式状态字中,只有4项是和输入有关的,如下所述。


    skipws=0x0001,//in,跳过输入中的空白 dec=0x0200,//input&output,转换为十进制 oct=0x0400,//input&output,转换为八进制 hex=0x0800,///input&output,转换为十六进制

    1.skipws

    在高层I/O中曾介绍过,除了%c外,诸如%d、%f等读数操作和%s字符串读入都会自动跳过前导空格,直到遇到非空字符才开始进行匹配性检查,对%c读操作,即使是空白,也会将其存入字符变量中。

    C++流类库机制与高层I/O基本相同,诸如对int、double、float等读数操作和C风格字符数组的读入同样会自动跳过前导空格,直到遇到非空字符才开始进行匹配性检查,但在对单个字符的读入处理中,两者有些细微的不同,C++对单字符输入(char)同样默认跳过前导空白,直到非空字符开始抽取,并进行匹配性检查。

    这是由格式状态字中的枚举常量skipws决定的,默认时skipws有效,其在格式状态字中的对应位为1,如示例代码14.15所示。

    代码14.15 cin和skipws格式化常量InputSample


    <———————————-文件名:example1415.cpp———————————————-> 01 #include<iostream> 02 using namespace std; 03 int main() 04 { 05 char x; 06 cin>>x;//输入x 07 cout<<x<<endl;//输出x 08 cin. unsetf(ios_base:skipws);//设置skipws失效 09 cin>>x; 10 cout<<x<<endl; 11 return 0; 12 }

    输出结果如下所示。


    5(注:键盘输入) 5

    【代码解析】代码的结果看似有些奇怪,用户只输入了一个5,回车后程序就结束了,这和代码14.3所讲的缓冲区垃圾有相似之处。默认状态下,cin对char型变量输入同样跳过前导空格,因此,即使用户输入了“5”,字符'5'还是成功地赋值给了char型变量x,但第8行的语句“cin.unsetf(ios_base:skipws);”使得skipws失效,cin对char型变量的输入不再跳过前导空白,只要是字符,都会被赋值给x,而提取了字符'5'后,输入缓冲区中尚存有一个回车符,这个回车符便赋值给了x,所以用户还未来得及输入,程序便结束了。

    istream类中提供了sync成员函数清空输入缓冲区,在上例中只要在第2个“cin>>x”之前插入语句“cin.sync();”即可解决问题。

    注意

    对代码14.15来说,还有一种更简洁的方式便是用skipws和noskipws控制符。

    再看一段失败的代码,如下所示。


    char c1='A'; while(c1!='\n') { cin>>c1; cout<<c1; }

    表面看来,该代码没有问题,但实际上这是个死循环,因为>>操作将会跳过空白符,也就是说c1永远不可能等于换行符'\n'。

    2.dec、oct和hex

    默认情况下,dec有效而oct和hex无效,即系统采用十进制的形式输入输出,但实际上,可以通过使用诸如“cin.setf(ios_base:hex,ios_base:basefield);”的指令将输入基制转变为十六进制,这样当用户通过键盘输入11时,编译器解释为十六进制的0x11,实际上等价于十进制下的11。

    除了格式化常量外,还可使用iomanip或iostream中定义的控制符,例如,下述语句可将输入进制更改为十六进制。


    cin>>hex;

    如示例代码14.16所示。

    代码14.16 改变输入数的基ChangeBase


    <————————————文件名:example1416.cpp———————————————> 01 #include<iostream> 02 using namespace std; 03 int main() 04 { 05 int x; 06 cin>>hex>>x;//改变输入的基 07 cout<<x<<endl; 08 return 0; 09 }

    输出结果如下所示。


    ff(注:键盘输入) 255

    【代码解析】代码中第6行语句“cin>>hex>>x;”将输入的数解释为十六机制,因此,用户输入的ff实际上等价于十进制的255,从“cout<<x”的结果255可以看出,输入和输出维护着两套不同的格式状态字,对输入流的设置不会影响输出流,反之亦成立。