views:

1147

answers:

5

I'm learning C++ and writing little programs as I go along. The following is one such program:

// This program is intended to take any integer and convert to the
// corresponding signed char.

#include <iostream>

int main()
{
  signed char sch = 0;
  int n = 0;
  while(true){
    std::cin >> n;
    sch = n;
    std::cout << n << " --> " << sch << std::endl;
  }
}

When I run this program and keep inputs at reasonably small absolute values, it behaves as expected. But when I enter larger inputs, e.g., 10000000000, the program repetitively spits out the same output. Some combinations of input cause erratic behavior. For example:

#: ./int2ch
10
10 --> 

10000000000
10 -->

10 -->

10 -->

10 -->

The program spits out "10 --> " until it's killed. (With this particular sequence of inputs, the program's output changes speed erratically.) I also noticed that the output of large values is determined by the previous legal input as well as the value of the current illegal input.

What's going on? (I don't care about fixing the program, that's easy. I want to understand it.)

+3  A: 

Given that you are on a 32 bit machine, 10000000000 is too big a number to be represented by an int. Also converting an int to a char will only give you from 0..255 or -128..127 depending on the compiler.

kenny
That's 0..255 or -128..127, actually. :)
unwind
+11  A: 

Basically you cin stream is in a fail state and thus returns immediately when you try to read it. rewrite your example like this:

#include <iostream>

int main()
{
  signed char sch = 0;
  int n = 0;
  while(std::cin >> n){
    sch = n;
    std::cout << n << " --> " << sch << std::endl;
  }
}

cin >> n will return a reference to cin, which you can test for "good-ness" in a conditional. So basically the the "while(std::cin >> n)" is saying "while i could still read from standard input successfully, do the following"

EDIT: the reason it repeatedly output the last good value entered is because that was the last value successfully read in n, the failed reads won't change the value of n

EDIT: as noted in a comment, you can clear the error state and try again something like this would probably work and just ignore bad numbers:

#include <iostream>
#include <climits>

int main() {
    signed char sch = 0;
    int n = 0;
    while(true) {
     if(std::cin >> n) {
      sch = n;
      std::cout << n << " --> " << sch << std::endl;
     } else {
      std::cin.clear(); // clear error state
      std::cin.ignore(INT_MAX, '\n'); // ignore this line we couldn't read it
     }
    }
}

EDIT: thanks litb, corrected.

Evan Teran
Alternatively, throw in a call to std::cin.clear() to remove the error state before the next pass of the loop.
hark
A: 

One problem here is that a char has a size of one byte, and thus can only hold a number between -127 and 128. An int on the other hand, is typically 4 bytes, and can take on much larger values. Second problem is that you are inputting a value that is too large even for an int.

Dima
first of all the printing of "some strange character" is not the cause, secondly a char is NOT signed by default, this is compiler dependent. It is *often* signed, but does not need to be.
Evan Teran
+2  A: 

Yes, Evan Teran pointed out most things already. One thing i want to add (since i cannot comment his comment yet :)) is that you must put the call to istream::clear before the call to istream::ignore. The reason is that istream::ignore likewise will just refuse to do anything if the stream is still in the fail state.

Johannes Schaub - litb
Thanks, corrected. You get an upvote for that ;)
Evan Teran
A: 

I'm having the same problem with my calculator. I tried int, float, double... all of them spit out garbage output when someone inputs too large a number. I don't understand how to fix that : /

Las Vegas realty