This function is supposed to read a fraction and place it in an array. If the user enters '0' the function is supposed to exit. I am trying to do this using the cin.peek() function but execution always goes into the if statement and doesn't allow the user to exit.
How should I properly code this (I am open to not using peek(), I thought it was the simplest way of doing it.)
Thanks!
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++;
}
}
This test of peek() works however:
#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;
}
There are two issues with your use of std::istream::peek()
:
std::ws
: (std::cin >> std::ws).peek()
.std::istream::peek()
is not a char
. Instead, it is an std::char_traits<char>::int_type
(which is a fancy spelling of int
). The result may, e.g., be std::char_traits<char>::eof()
and if the value of '0'
happens to be negative (I'm not aware of any platform where it is; however, e.g., the funny character from my name 'ü'
is a negative value on platforms where char
is signed) you wouldn't get the correct result, either. That is, you normally compare the result of std::istream::peek()
against the result of std::char_traits<char>::to_int_type()
, i.e., you'd use something like this: std::cin.peek() == std::char_traits<char>::to_int_type('0')
That said, your program doesn't check whether it could successfully read the nominator and the denominator, separated by a slash. You always want to verify that reading was successful, e.g., using something like
if ((std::cin >> nominator >> slash >> denominator) && slash == '/') {
...
}
Just for entertainment, you can create a manipulator for testing that a character is a slash, indeed:
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;
}
This way, you'd encapsulate the test for slash. If you need to use this in multiple places this is quite handy.