C ++输入操作符重载“>>”

时间:2012-12-05 14:12:08

标签: c++ input operator-overloading cin rational-numbers

我有一个有理数字类由两个整数组成:num,提名者,den,分母。

以下运算符应该从流中读取有理数。

istream& operator >> (istream& Is, rational& r) {
  char c; //Test char.
   double n; //Could be either the numerator of the fraction or the antiperiod of the repeating decimal number.
    Is >> n;
    int i = 0;
    for (; n*10-pow(10, i+1) < 1 && int(n) != 0; i++) {
        n *= 10;
    }
    for (; int(n*10) % 10; i++) {
        n *= 10;
    }
    n /= pow(10, i);
    if (i == 0) {
        r.num = n;
        Is >> ws;
        c = Is.peek();
        if (c == '/') {
            c = Is.get();
            Is >> r.den;
        } else {
            r.den = 1;
        }
        r.normalize(); //This function normalizes the fraction.
    } else {
        Is >> ws;
        c = Is.peek();
        if (c == 'p' || c == 'P') {
            int p; //Period of the repeating decimal number.
            c = Is.get();
            Is >> p;
            vector<int> a = genFrac(n, p); //This function returns the fraction which express the decimal repeating number. It returns a "vector<int>" with the nominator at index 1 e denominator at index 0.
            r.num = a[1];
            r.den = a[0];
        } else {
            i = 0;
            for (; n*10-pow(10, i+1) < 1 && int(n) != 0; i++) {
                n *= 10;
            }
            for (; int(n*10) % 10 != 0; i++) {
                n *= 10;
            }
            int pot10 = pow(10, i);
            r.num = n;
            r.den = pot10;
        }
        r.normalize();
    }
    return Is;
}

我写了这段代码来实现我的“理性”类的输入。 我从我的C ++书中编写的那个修改它,以便输入十进制数,包括重复数。

它应该能够处理这些类型的输入:

  • 9/8
  • 9
  • 9.87
  • 1.p3(= 1.3333333333)

但它不起作用,甚至不是我从书中复制的部分。

任何人都可以帮助我吗?

2 个答案:

答案 0 :(得分:5)

我想我的写法有点不同 1

除非你真的需要这样做,否则我首先阅读整个输入的“大块”(即所有字符直到下一个空格),然后理清它应该如何表示一个数字,以及为每个可能的表示调用单独的函数:

std::istream &operator>>(std::istream &is, rational &r) {
    std::string temp;

    Is >> temp;
    if (temp.find('/') != std::string::npos)
        r = cvt_fraction(temp, Is);
    else if (temp.find_first_of("pP") != std::string::npos)
        r = cvt_repeating(temp, Is);
    else if (temp.find('.') != std::string::npos)
        r = cvt_float(temp, Is);
    else
        r = cvt_int(temp, Is);
    return Is;
}

我已经将istream传递给每个,原因有二:首先,如果他们在输入中发现垃圾,他们可以设置流的失败位。第二,所以如果如果他们真的需要阅读更多的输入,他们可以(但如果真的需要,我会有点惊讶)。

在我看来,每个转换函数都应该是相当简单的:如果我从字符串应该是digits "/" digits或“数字”p“数字”这一事实开始,那么进行转换通常是变得非常简单 - 具体来说,简单到足以让我认为任何人都可以浏览代码并理清每件应该做的事情。


  1. 老实说,我并不是故意讨厌,但如果我维护代码并跑过operator>>,我会有两种可能的反应之一:如果它显然有错误,请立即更换。否则,将其列入“技术债务”清单,并尽快更换。简单的事实是,就目前而言,需要进行大量的研究才能确定应该支持哪些输入格式,更不用说代码的哪个部分处理每个,或者整个事情应该如何处理共同努力,产生有意义的结果。

答案 1 :(得分:1)

评论中提到的问题(p语句中未显示c=is.peek())来自p实际存储在ws中的事实(它是is >> ws存储在ws)。

上述代码也未提及char,但我认为它是{{1}}。