Проблемы istream класса смешанного номера

Летом я задал себе домашнее задание, и проект, который я закончил на 98%, застопорился из-за одной этой проблемы.

У меня есть класс под названием Mixed. Он содержит данные членов для целого числа, числителя и знаменателя. Мне нужно перегрузить все общие операторы, чтобы разрешить умножение, сложение, сравнение и потоковую передачу объектов типа Mixed. У меня перегружены все операторы, кроме >> (оператор извлечения).

Все смешанные числа будут прочитаны в формате целый числитель/знаменатель.

ex: 1 2/3, 0 7/8, -3 18/5, 0 -1/89

Заголовок: friend istream& operator>> (istream &, Mixed);

CPP-файл: istream& operator>> (istream &in, Mixed m) {...}

Для задания я ограничен библиотеками iostream и iomanip. Мой план состоял в том, чтобы считывать значения из потока и присваивать их временным переменным типа int (w, n, d), которые я затем использовал с конструктором Mixed для создания объекта m. К сожалению, я не могу придумать, как разделить числитель и знаменатель. Они оба целые, но между ними есть символ (/).

  • Я не могу использовать getline() с его разделителем, потому что он присваивает данные массиву char, который я не верю, что смогу преобразовать в int без другой библиотеки.
  • Я не могу использовать массив символов, а затем сегментировать его по той же причине.
  • Я не могу использовать цикл while с get() и peek(), потому что, опять же, я не думаю, что смогу преобразовать массив char в int.
  • Я не могу использовать строку или c-строку, а затем сегментировать ее, потому что для этого требуются внешние библиотеки.

Еще раз, мне нужно разделить значение типа "22/34" на 22 и 34, используя только iostream и iomanip. Есть ли какой-то довольно очевидный метод, который я пропускаю? Есть ли способ неявного преобразования с помощью указателей?


person Sithregal    schedule 20.08.2012    source источник
comment
Вы позволите себе использовать stringstream и string?   -  person jrok    schedule 20.08.2012
comment
Если посмотреть в шапке <complex>, там есть пример чтения формата (22,34). Можно использовать как вдохновение!   -  person Bo Persson    schedule 20.08.2012
comment
@jrok: Нет, я использую только iostream и iomanip. Одним из обходных путей, о котором я подумал, было бы каким-то образом дважды прочитать содержимое потока, например, при копировании объекта потока или поиске в начале после первого чтения. Я могу легко заставить программу работать, используя строки, сегментируя их и конвертируя в int. Но опять же, задание должно иметь возможность (так как оно было в инструкции) выполняться с использованием только iostream и iomanip.   -  person Sithregal    schedule 20.08.2012


Ответы (2)


Вы можете сначала извлечь числитель, затем разделительный символ, а затем знаменатель.

Пример для иллюстрации:

istream& operator>> (istream &in, Mixed &m) {
    int num, denom;
    char separ;

    in >> num;
    in.get(separ);
    if (separ != '/')
      in.setstate(ios::failbit);
    in >> denom;

    if (in) {
      // All extraction worked
      m.numerator = num;
      m.denominator = denom;
    }

    return in;
}
person sth    schedule 20.08.2012
comment
У меня сложилось впечатление, что выполнение чего-то вроде in ›› num будет считывать весь блок символов, игнорируя только пробелы, в результате чего вся дробь будет преобразована в одно целое число. - person Sithregal; 20.08.2012

Еще раз, мне нужно разделить значение типа "22/34" на 22 и 34, используя только iostream и iomanip.

Не могли бы вы просто прочитать первое целое число, использовать get для получения следующего символа, а затем прочитать второе целое число? Что-то вроде этого:

#include <iostream>

int main() {
    using std::cin;
    using std::cout;

    int num;
    int den;

    while(cin) {
        cin >> num;
        if (cin.get() != '/') {
            // handle error
        }   
        cin >> den;

        cout << num << "/" << den << std::endl;
    }   

    return 0;
}

Затем вы можете убедиться, что символ, прочитанный между двумя целыми числами, был '/', и обработать его соответствующим образом, если это не так.

person Robert Gamble    schedule 20.08.2012