istream类方法 重载的抽取操作符 和 cin输入

本文详细介绍了C++中istream类如何重载抽取操作符`>>`,用于处理各种基本类型的数据输入,包括格式化输入函数的功能和用法。同时,讲解了如何与hex、oct、dec控制符配合输入不同进制的整数,以及处理字符指针类型的输入。文章还探讨了`cin`如何检查输入,流状态的管理,包括eofbit、failbit和badbit的含义及如何设置和检查。此外,还讨论了异常处理、非格式化输入函数如get()和getline()的使用,以及异常的处理和错误输入的清理方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

重载的抽取操作符 >>

     istream类(在头文件iostream中定义)重载了抽取操作符 >> ,使之能够识别下面的这些基本类型:
     signed char &                unsigned char &
     char &                           short &
     unsigned short &          int &
     unsigned int &              long &
     unsigned long &           float &
     double &                      long double &

     这些操作符函数被称为格式化输入函数(formatted input functions) ,因为它们可以将输入数据转换为目标指定的格式。

     典型的操作符函数的原型如下:
     istream & operator>> (int &);

     参数和返回值都是引用。因此cin能够直接修改用作参数的变量的值。

     可以将hex、oct和dec控制符与cin一起使用,来指定将整数输入解释为十六进制、八进制还是十进制格式。例如:
     cin >> hex;
     将输入12或0x12解释为十六进制的12或十进制的18,而将ff或FF解释为十进制的255。

     该类还为下列字符指针类型重载了>> 抽取操作符:
     signed char *        char *       unsigned char *

     对于这种类型的参数,抽取操作符将读取输入中的下一个单词,将它放置到指定的地址,并加上一个空值字符,使之成为一个字符串。

     每个抽取操作符都返回调用对象的引用,这使得能够将输入拼接起来,就像拼接输出那样:
     char name[20];
     float fee;
     int group;
     cin >> name >> fee >> group;


cin>> 如何检查输入

     cin>> 跳过空白(空格、换行符和制表符),直到遇到非空白字符。
     在单字符模式下,>>操作符将读取该字符,将它放置到指定的位置。
     在其他模式下,>>操作符将读取一个指定类型的数据。它的读取从非空白字符开始,到与目标类型不匹配的第一个字符之间的全部内容。

     当输入未满足程序的期待时,抽取操作符将不会修改参数的值,并返回0(false)。

流状态

     cin或cout对象包含一个描述流状态(stream state) 的数据成员(从ios_base类那里继承的)。

     流状态被定义为iostate 类型,而iostate是一种bitmask 类型。由3个ios_base元素组成: eofbitbadbitfailbit ,其中每个元素都是一位,可以是1(设置)或0(清除)。

     当cin操作到达文件末尾时,它将设置eofbit;

     当cin操作未能读取到预期的字符时,它将设置failbit。
     I/O失败(如试图读取不可访问的文件或试图写入受保护的磁盘),也可能将failbit设置为1。

     在一些无法诊断的失败破坏流时,badbit元素将被设置。

     当全部3个状态位都设置为0时,说明一切顺利。

     下图列出了这些位和一些报告或改变流状态的ios_base方法。

 

 

流状态

 

 

1. 设置状态

     clear() 方法将状态设置为它的参数。例如:
     clear();
     将使用默认参数0,清除全部3个状态位。

     clear(eofbit);
     将状态设置为eofbit;也就是说,eofbit将被设置,另外两个状态位被清除。

     setstate() 方法只影响其参数中已设置的位。例如:
     setstate(eofbit);
     将设置eofbit,而不会影响其他位。

2. I/O和异常

     exceptions() 方法用来控制异常如何被处理。

     exceptions()方法返回一个位字段,它包含3位,分别对应于eofbit、failbit和badbit。
     修改流状态后,clear()方法将当前的流状态与exceptions()返回值进行比较。如果在返回值中某一位被设置,而当前状态中的对应位也被设置,则clear()将引发ios_base::failbit异常。如果两个值都设置了badbit,将发生这种情况。
     如果exceptions()返回goodbit ,则不会引发任何异常。

     os_base::failbit异常类是从std::exception类派生而来的,因此包含一个what()方法。

     exceptions()的默认设置为goodbit,不会引发异常。
     重载的exceptions(iostate)函数使得能够控制其行为:
     cin.exceptions(badbit);     // setting badbit causes exception to be thrown

     位操作符OR (| )使得能够指定多位。例如:
     cin.exceptions(badbit | eofbit);
     如果badbit或eofbit随后被设置,将引发异常。

3. 流状态的影响

     只有在流状态良好(所有的位都被清除)的情况下,才能正确的返回true或false。

     设置流状态位有一个非常重要的后果: 流将对后面的输入或输出关闭,直到位被清除。
     例如下面的代码不能工作:
     while(cin >> input)
           sum += input;
     cout << "sum = " << sum << endl;
     cin >> input;  
      // won't work

     然而,仅仅使用clear()方法还不足以重新设置流状态。因为导致输入循环终止的不匹配输入仍留在输入队列中,程序必须跳过它。

     一种方法是一直读取字符,直到到达空白为止:
     while( !isspace(cin.get() ))
           continue; 
  // get rid of bad input
     isspace()函数是一个cctype函数,它在参数是空白字符时返回true。

     另一种方法是,丢弃行中的剩余部分,而不仅仅是下一个单词:
     while(cin.get() != '/n')
           continue;
   // get rid of line

     假设循环是由于到达文件尾或者由于硬件故障而终止的,则上面的错误处理代码将毫无意义。
     可以使用fail()eof()bad() 方法来判断假设是否成立。

其他istream类方法

    get(char&)get(void) 方法提供不跳过空白的单字符输入功能。

    get(char*, int, char)getline(char*, int, char) 函数在默认情况下读取整行而不是一个单词。

    它们被称为非格式化输入函数(unformatted input functions)

1. 单字符输入
    使用char参数或没有参数的情况下,get()方法读取下一个输入字符,即使该字符是空格、制表符或换行符。
    get(char&) 版本将输入字符赋给其参数。
    get(void) 版本将输入字符转换为整型(通常是int),并将其返回。

    由于get(char&)版本的读取方式,便可以使用下面的判断语句:
    char ch;
    cin.get(ch);
    while(ch != '/n')
      ...

    假如改为cin >> ch 循环将不会停止。

    get(char&)成员函数返回一个指向用于调用它的istream对象的引用,这意味着可以拼接输入:
    char c1,c2,c3;
    cin.get(c1).get(c2) >> c3;


    如果cin.get(char&)到达文件尾——无论是真正的,还是通过键盘仿真的文件尾(DOS为按下<Ctrl>+<Z>;UNIX为在行首按下<Ctrl>+<D> ),它都不会给其参数赋值。该方法还调用setstate(failbit),导致cin的测试结果为false。

    get(void)成员函数也读取空白,但使用返回值来将输入传递给程序。例如:
    char ch;
    ch = cin.get();
        // use return value

    因此,试图拼接该方法来输入,将是错误的。

    如果到达文件尾后(真正的或者仿真的文件尾都一样),该方法将返回值EOF ——iostream头文件的一个符号常量。
    int ch;
    while( (ch = cin.get() ) != EOF)
        ...

    这里应将ch的类型声明为int,而不是char。因为值EOF可能无法使用char类型来表示。

    下图总结了这两个版本的特性。

 

get(ch)与get()

 

2. 字符串输入

    istream & get(char *, int, char);
    istream & get(char *, int);
    istream & getline(char *, int, char);
    istream & getline(char *, int);


    上述中的第一个参数是用于放置输入字符串的内存单元的地址。
    第二个参数比要读取的最大字符数大1,额外的一个字符用于存储结尾的空字符,以便将输入存储为一个字符串。
    第三个参数指定用作分界符的字符,只有两个参数的版本将换行符用作分界符。

    上述函数都在读取最大数目的字符或遇到分界符后为止。

    get()和getline()之间的主要区别在于,前者将分界符(默认为换行符)留在输入流中,这样接下来的输入操作首先看到的将是分界符,而getline()抽取并丢弃输入流中的分界符。

    ignore() 成员函数接受两个参数。原型如下:

    istream & ignore(int =1, int = EOF);

    第一个参数是数字,指定要读取的最大字符数。
    第二个参数是字符,用作输入分界符。例如:
    cin.ignore(255,'/n')

    上述语句将读取并丢弃接下来的255个字符或直到到达第一个换行符。

    该函数返回调用对象,这使得能够拼接函数调用,例如:
    cin.ignore(255,'/n').ignore(255,'/n');

3. 意外字符串输入

    get(char *, int)和getline()如果不能抽取字符,它们将把空值字符放置到输入字符串中,并使用setstate()设置failbit。
    如果遇到文件尾,将设置eofbit,如果遇到流被破坏(如设备故障),将设置badbit。

    对于get(char *, int)来说,如果输入了一个空行,将导致不能抽取字符,例如:
    char temp[80];
    while(cin.get(temp, 80)   // terminates on empty line
          ...


    但空行并不会导致getline()设置failbit。因为getline()仍将抽取换行符,虽然不会存储它。

    如果希望getline()在遇到空行时终止循环,则可以这样编写:
    char temp[80];
    while(cin.getline(temp,80) && temp[0] != '/0');   
// terminates on empty line

    假设队列中的字符数等于或超过了输入方法指定的最大字符数。例如:
    char tmep[30];
    while(cin.getline(temp,30) );


    如果读取了29个字符,并且输入流中的下一个字符不是分界符,则设置failbit。

    对于get(char *, int)方法,它首先测试字符数,然后检测是否为文件尾以及下一个字符是否是分界符。如果它读取了最大数目的字符,则不设置failbit标记。

    可以用peek() 来查看下一个输入字符,如果它是换行符,则说明get()已读取了整行;否则说明是在到达行尾前停止的。
    这种技术对于getline()不适用,因为该方法读取并丢弃换行符,因此查看下一个字符无法知道任何情况。

其他istream方法

    read() 函数读取指定数目的字节,并将它们存储在指定的位置中。例如:
    char gross[144];
    cin.read(gross,144);


    该方法不会在输入后加上空值字符,因此不能将输入转换为字符串。
    它常与ostream write() 函数结合使用,来完成文件输入和输出。
    该方法的返回类型为istream & 。

    peek() 函数返回输入中的下一个字符,但不抽取输入流中的字符。

    gcount() 方法返回最后一个非格式化抽取方法读取的字符数。
    这意味着字符是由get()、getline()、ignore()、read()方法读取的,而不是由抽取操作符(>>)读取的。

    putback() 函数将一个字符插入到输入字符串中,被插入的字符将是下一条输入语句读取的第一个字符。
    该方法接受一个char参数——要插入的字符。
    返回类型为istream & 。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值