>" My class of rational numbers consists of two integers: num , nominee and den , denominator. The following stat...">

C ++ input operator overload ">>"

My class of rational numbers consists of two integers: num , nominee and den , denominator.

The following statement is supposed to read a rational number from the 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 changed it from what is written in my C ++ book to make it possible to enter decimal numbers, including repeating ones.

It should be able to handle these input types:

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

But this does not work, even the part that I copied from the book.

Can anybody help me?

+6
source share
2 answers

I think I would write this a little differently 1 .

If you really do not need otherwise, I will start by reading the entire β€œpiece” of input (that is, all characters until the next space), and then figure out how this should represent the 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 passed istream to each for two reasons: firstly, so if they find garbage in the input, they can set the stream failure bit. Secondly, therefore, if they really need to read more information, they can (but I would be a little surprised if it really were necessary).

It seems to me that each of these conversion functions should be quite trivial: if I assume that the line should be digits "/" digits or `digitits" p "digitits", the conversion will usually be quite simple - in particular, simple enough that I think that someone can probably take a look at the code and figure out what each part should do.


  • I honestly don’t want to be nasty, but if I supported the code and ran through your operator>> , I would have one of two possible reactions: if it apparently had an error, replace it immediately. Otherwise, put it on the technical debt list and replace it as soon as possible. The simple fact is that since it stands right now, quite a bit of research is required to even be sure which input formats should be supported, not to mention how much of the code each processes, or how it is supposed to work together to achieve meaningful results.
+5
source

The problem mentioned in the comment ( p not shown in the c=is.peek() instruction) comes from the fact that p actually stored in ws (it is stored there in is >> ws ).

The above code also doesn't mention ws , but I assume it is a char .

+1
source

All Articles