Эта функция должна читать дробь и помещать ее в массив. Если пользователь вводит «0», функция должна завершиться. Я пытаюсь сделать это с помощью функции cin.peek (), но выполнение всегда входит в оператор if и не позволяет пользователю выйти.
Как мне правильно написать код (я открыт для того, чтобы не использовать peek (), я подумал, что это самый простой способ сделать это.)
Спасибо!
void enterFrac(Fraction* fracs[], int& index)
{
int n, d;
char c, slash;
cout << "Enter fractions (end by entering a 0): ";
c = cin.peek();
if ( c != '0')
{
cin >> n >> slash >> d;
Fraction* f = new Fraction();
f->num = n;
f->den = d;
fracs[index] = f;
index++;
}
}
Этот тест peek () работает, однако:
#include <iostream>
using namespace std;
int main () {
char c;
int n;
char str[256];
cout << "Enter a number or a word: ";
c=cin.peek();
if ( (c >= '0') && (c <= '9') )
{
cin >> n;
cout << "You have entered number " << n << endl;
}
else
{
cin >> str;
cout << " You have entered word " << str << endl;
}
return 0;
}
Есть две проблемы с вашим использованием std::istream::peek()
:
std::ws
: (std::cin >> std::ws).peek()
,std::istream::peek()
это не char
, Вместо этого это std::char_traits<char>::int_type
(который является причудливым написанием int
). Результат может быть, например, std::char_traits<char>::eof()
и если значение '0'
бывает отрицательным (я не знаю ни о какой платформе, где она находится; однако, например, забавный персонаж от моего имени 'ü'
является отрицательным значением на платформах, где char
подписан) вы также не получите правильный результат. То есть вы обычно сравниваете результат std::istream::peek()
против результата std::char_traits<char>::to_int_type()
то есть вы бы использовали что-то вроде этого: std::cin.peek() == std::char_traits<char>::to_int_type('0')
Тем не менее, ваша программа не проверяет, может ли она успешно прочитать знаменатель и знаменатель, разделенные косой чертой. Вы всегда хотите убедиться, что чтение прошло успешно, например, используя что-то вроде
if ((std::cin >> nominator >> slash >> denominator) && slash == '/') {
...
}
Просто для развлечения вы можете создать манипулятор для проверки того, что персонаж — это слеш:
std::istream& slash(std::istream& in) {
if ((in >> std::ws).peek() != std::char_traits<char>::to_int_type('/')) {
in.setstate(std::ios_base::failbit);
}
return in;
}
Таким образом, вы бы инкапсулировали тест на косую черту. Если вам нужно использовать это в нескольких местах, это очень удобно.
Других решений пока нет …