Перегрузка оператора ввода C++ ">>"

У меня класс рациональных чисел состоит из двух целых чисел: 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 ответа

Решение

Я думаю, что я написал бы это несколько иначе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 или `digits "p" digits", выполнение преобразования, как правило, будет довольно простым - в частности, достаточно простым, так что я думаю, что любой может взглянуть на код и разобраться, что должен делать каждый фрагмент.


  1. Честно говоря, я не хочу быть противным, но если бы я поддерживал код и наткнулся на ваш operator>>У меня была бы одна из двух возможных реакций: если бы у нее была ошибка, немедленно замените ее. В противном случае внесите его в список "технических долгов" и замените его как можно скорее. Простой факт заключается в том, что в нынешнем виде требуется немало усилий, чтобы даже убедиться, какие входные форматы должны поддерживаться, не говоря уже о том, какая часть кода обрабатывает каждый, или как все это должно делать. работать вместе, чтобы получить значимый результат.

Проблема, упомянутая в комментарии (p не появляется в c=is.peek() заявление) исходит из того факта, что p на самом деле хранится в ws (хранится там в is >> ws).

Приведенный выше код также не содержит упоминаний ws, но я предполагаю, что это char,

Другие вопросы по тегам