Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pass a char to an int in using std::cin in C++

I am having a problem with an exercise that asks me to receive two integers and print them. But, the program ends when the user enters with the entry '|'. However, I am testing this and the program enters in an infinite loop. What is the problem?

#include <iostream>
using namespace std;

int main ()
{
  int i1 = 0, i2 = 0;

  cin >> i1;
  cin >> i2;
  while (i1 != int('|') && i2 != int('|'))
  {
     cout << i1 << endl;
     cout << i2 << endl;

     cin >> i1 >> i2; 
  } 

  return 0;
}
like image 981
Felippe Trigueiro Avatar asked Sep 06 '25 14:09

Felippe Trigueiro


2 Answers

When you std::cin the non-integer type (charector '|') inside the loop, it fails. Use std::cin.fail() check that.

For example, run the following, and you will get the idea why this happened:

while (i1 != int('|') && i2 != int('|'))
{
    std::cout << i1 << endl;
    std::cout << i2 << endl;

    std::cin >> i1 ;  // std::cin fails here, in the the case of '|'
    if(std::cin.fail()) { std::cout << "Failed"; break;}

    std::cin >> i2;  // std::cin fails here, in the the case of '|'
    if(std::cin.fail()) { std::cout << "Failed"; break;}
}

Above will fix the code. However, you can also write a code for any case of std::cin failure, by checking with std::cin::fail().

while ( std::cin >> i1 && !std::cin.fail()   // check wether i1 failed, if not continue
     && std::cin >> i2 && !std::cin.fail() ) // check wether i2 failed, if not continue
{
   std::cout << i1 << "\n" << i2 << std::endl;
}

Update: As @AJNeufeld pointed out while (i1 != int('|') && i2 != int('|')) will fail to read 124, even the inputs are integers(which is equal to the ASCII code of the vertical pipe character).

A possible solution is to read both values as strings, check for the ‘|‘ character, if not present, convert the strings to ints, or report errors or break the loop. (Credits to @AJNeufeld)

like image 76
JeJo Avatar answered Sep 08 '25 12:09

JeJo


When you use >> to extract a value from an istream, the original stream is returned from the expression. This mean you can replace this code ...

std::cin >> i1;
std::cin >> i2;

with this code:

std::cin >> i1 >> i2;

The result of that expression is again the original istream, and when used in a boolean context, returns false if the stream is in a “fail” state. Thus, we can read the two integers and test if that was successful in one simple construct:

if( std::cin >> i1 >> i2 ) {
    std::cout << i1 << "\n" << i2 << "\n";
} else {

The above stream will enter a fail state, when it is trying to read an integer and encounters a non-integer character, such as the vertical pipe. To test for this, we need to first clear the error state, then see what character was in the stream that caused the integer read to fail. We can do this by peeking at what the next character is.

} else {
    std::cin.clear();    // reset the fail state
    if (std::cin.peek() == '|') {
        std::cout << "Found end of input marker (|)\n";
    } else {
        std::cout << "Invalid input!";
    }

After determining whether it was the vertical pipe or not, it is wise to clear out all characters in the stream up to the end of the input line.

    // skip all characters in the stream up to the end of the current line.
    std::cin.ignore(std::numeric_limits<streamsize>::max(), '\n');
}

Put the above code in a loop, add a break statement when the vertical pipe is found, and you will be looping, reading integer values in pairs, until you type in the |.

while ( !std::cin.eof() ) {
    if( std::cin >> i1 >> i2 ) {
        std::cout << i1 << "\n" << i2 << "\n";
    } else {
        std::cin.clear();    // reset the fail state
        if (std::cin.peek() == '|') {
            std::cout << "Found end of input marker (|)\n";
            break;
        } else {
            std::cout << "Invalid input!";
        }
        // skip all characters in the stream up to the end of the current line.
        std::cin.ignore(std::numeric_limits<streamsize>::max(), '\n');
    }
}
like image 44
AJNeufeld Avatar answered Sep 08 '25 12:09

AJNeufeld