-4

Long program short: I am reading binary file byte by byte and after each read byte I output this byte but not as a character( as I declared a variable char c and store the values in that ) but as int. When I come to binary values around 125 above I get values negative values.

For example when I read hex 89 = dec 137 and I output this char as int, I get value -119.

Another example: I read hex 83 = dec 131 and I output this char as int, I get value -125.

I read this file by bytes:

ifstream inFile;
inFile . open( srcName, ios::binary | ios::in );

char c;

while( inFile . get( c ) ){
  inFile . get( c );
  cout << (int) c << endl;
}
nhgrif
  • 61,578
  • 25
  • 134
  • 173
alik33
  • 141
  • 3
  • 13

2 Answers2

1

I suppose you wanted to ask why do you see negative values when you expected positive.

First, you should not read data from a file into a char. In C and C++, functions reading a character from files or standard input (getchar(), fgetc(), ifstream::get() and so on) return an int. The reason is the need to detect the end of file (or input). The function needs to return some value that can be checked and is different from any possible byte (char) value - in binary file, you can encounter a byte with any value.

And second, char may and may not be signed in C++ (see this question for further details). Your char seems to be a signed char. That means it can represent numbers in the (-128,127) range, and it interprets byte values over 127 as negative numbers. That is why you see them as negative (C++ will convert (char) -119 into (int) -119). If you want positive values, declare your c as unsigned char (or unsigned int).

Community
  • 1
  • 1
Honza Remeš
  • 1,193
  • 8
  • 11
  • ifstream::get() needs argument of type `char` – alik33 Mar 20 '16 at 00:46
  • You can use the `get()` signature, which returns an `int`. Then your code would be: `int c; while ((c = inFile.get()) != EOF) { cout << c << endl; }` An `int` should work, even when `signed`. – Honza Remeš Mar 20 '16 at 00:57
0

First thing to say is that char is not guaranteed to be signed or unsigned by the standard - this is system and implementation specific. Then, you shouldn't use char for such a task 'cause even if it works fine (which is not your case) it might break when you use a different compiler or a different system.

Second thing to say is that you should not use C-style casts, use static_cast instead. C-style casts are not safe and there is a lot of complexity under their simple syntax.

To fix your problem you could use unsigned char instead of char. If for some reason this is not possible - you could try casting to unsigned char before (implicitly) casting to unsigned int like this:

unsigned int val = static_cast<unsigned char>(a);
Marinos K
  • 1,779
  • 16
  • 39
  • compiler prints error.. ifstream::get() needs `char` arguments – alik33 Mar 20 '16 at 00:49
  • well, "If for some reason this is not possible - you could try casting to `unsigned char` before (implicitly) casting to `unsigned int` like this: ...". Simply `get` the numbers into a `char` and then use my code above to convert this into an `unsigned int`. It should work. – Marinos K Mar 20 '16 at 00:51