6

我有一个有理数类由两个整数组成: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)

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

谁能帮我?

4

2 回答 2

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>>的 . 否则,将其列入“技术债”清单,并尽快更换。一个简单的事实是,就目前而言,甚至需要进行大量研究才能确定应该支持哪些输入格式,更不用说代码的哪一部分处理每一个,或者整个事情应该如何处理共同努力产生有意义的结果。
于 2012-12-05T15:26:28.110 回答
1

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

上面的代码也没有提到ws,但我认为它是一个char.

于 2012-12-05T14:50:37.897 回答