Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ input operator overload ">>"

I have a rational number class is made up of two integers: num, the nominator, and den, the denominator.

The following operator is supposed to read the rational number from a stream.

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;
}

I wrote this code to implement the input of my "rational" class. I modified it from the one written in my C++ book in order to make possible the input of decimal numbers, including repeating ones.

It should be able to handle these types of input:

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

But it doesn't work, not even the part I copied from the book.

Can anyone help me?

like image 912
fpiro07 Avatar asked Dec 05 '12 14:12

fpiro07


1 Answers

I think I'd write this somewhat differently1.

Unless you really need to do otherwise, I'd start by reading an entire "chunk" of input (i.e., all the characters up to the next white space), then sort out how that's supposed to represent a number, and call a separate function for each possible representation:

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;
}

I've passed the istream to each for two reasons: first, so if they find garbage in the input, they can set the stream's fail bit. Second, so if they really do need to read more input, they can (but I'd be a little surprised if that's ever really needed).

It seems to me that each of those conversion functions should be fairly trivial: if I'm starting from the fact that a string should be digits "/" digits or `digits "p" digits", doing a conversion is generally going to be pretty simple -- specifically, simple enough that I think just about anybody can probably glance at the code and sort out what each piece is supposed to do.


  1. I honestly don't mean to be nasty, but if I was maintaining code, and ran across your operator>>, I would have one of two possible reactions: if it apparently had a bug, replace it immediately. Otherwise, put it on the "technical debt" list, and replace it as soon as possible. The simple fact is that as it stands right now, it takes a fair amount of study to even be sure what input formats are supposed to be supported, not to mention which part of the code handles each, or how the whole thing is supposed to work together to produce a meaningful result.
like image 173
Jerry Coffin Avatar answered Sep 28 '22 00:09

Jerry Coffin