How to properly use cin.peek()
c++, cin, peek, struct
Solution
There are two issues with your use of `std::istream::peek()`:
- This function access the next character and does not skip leading whitespace. You probably want to skip leading whitespace before determining what the next character is, e.g., using the manipulator `std::ws`: `(std::cin >> std::ws).peek()`.
- The result from `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.
Problem
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; } ```