Manually converting a char to an int - Strange behaviour - c++

I've wrote a small program to convert a char to an int. The program reads in chars of the form '1234' and then outputs the int 1234:
#include <iostream>
using namespace std;
int main(){
cout << "Enter a number with as many digits as you like: ";
char digit_char = cin.get(); // Read in the first char
int number = digit_char - '0';
digit_char = cin.get(); // Read in the next number
while(digit_char != ' '){ // While there is another number
// Shift the number to the left one place, add new number
number = number * 10 + (digit_char - '0');
digit_char = cin.get(); // Read the next number
}
cout << "Number entered: " << number << endl;
return 0;
}
This works fine with small chars, but if I try a big char (length 11 and above) like 12345678901 the program returns the wrong result, -539222987.
What's going on?

12345678901 in binary is 34 bits. As a result, you overflowed the integer value and set the sign bit.

Type int is not wide enough to store such big numbers. Try to use unsigned long long int instead of the type int.
You can check what maximum number can be represented in the given integer type. For example
#include <iostream>
#include <limits>
int main()
{
std::cout << std::numeric_limits<unsigned long long int>::max() << std::endl;
}
In C you can use constant ULLONG_MAX defined in header <limits.h>

Instead of using int, try to use unsigned long long int for your variable number.
That should solve your problem.

Overflowed integer. Use unsigned long long int.

Related

Integer literal is too large to be represented in any integer type -- C++

I'm attempting problem 8 in Project Euler, where I have to find largest product of 13 adjacent digits in a given 1000 digit number. However, I am getting the "Integer literal is too large to be represented in any integer type" during compilation. Any idea of how to fix this/work around this error?
This is the code till now:
#include <iostream>
using namespace std;
int main() {
unsigned long long double number = 7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450;
cout << number << endl;
}
Use a string:
#include <string>
int main() {
std::string number = "7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450";
}
Then use the digits to solve your problem.

Is it Normal For Chars to be Between -128 and 127? [duplicate]

This question already has answers here:
Why is 'char' signed by default in C++?
(2 answers)
Is char signed or unsigned by default?
(6 answers)
Closed 5 years ago.
To find out the range of integer values for a standard 8-bit char, I ran the following code:
int counter = 0;
for (int i = -300; i <= 300; i++)
{
char c = static_cast<char> (i);
int num = static_cast<int> (c);
if (num == i)
{
counter ++;
}
else
{
cout << "Bad: " << i << "\n";
}
}
cout << "\n" << counter;
I ended up seeing a value of 256 for counter, which makes sense. However, on the list of "Bad" numbers (i.e., numbers that chars don't store), I found that the greatest Bad negative number was -129, while the smallest Bad positive number was 128.
From this test, it seems like chars only store integer values from -128 to 127. Is this conclusion correct, or am I missing something? Because I always figured chars stored integer values from 0 to 255.
Although implementation defined, for the most part - yes it is normal as your implementation defines char as a signed char. You can use the CHAR_MIN and CHAR_MAX macros to print out the minimum and maximum values of type char:
#include <iostream>
#include <cstdint>
int main() {
std::cout << CHAR_MIN << '\n';
std::cout << CHAR_MAX << '\n';
}
Or using the std::numeric_limits class template:
#include <iostream>
#include <limits>
int main() {
std::cout << static_cast<int>(std::numeric_limits<char>::min()) << '\n';
std::cout << static_cast<int>(std::numeric_limits<char>::max()) << '\n';
}
As for the 0..255 range that is the unsigned char type. Min value is 0 and max should be 255. It can be printed out using:
std::cout << UCHAR_MAX;
Whether the type is signed or not can be checked via:
std::numeric_limits<char>::is_signed;
Excerpt from the char type reference:
char - type for character representation which can be most
efficiently processed on the target system (has the same
representation and alignment as either signed char or unsigned
char, but is always a distinct type).

C++ - Getting Byte from Console

I am new to C++ and coming from a C# / Java background I feel like I am kind of spoilt.
What I am trying to achieve here is to get the data input by the user as byte (unsigned char) using cin.
#include <iostream>
using namespace std;
typedef unsigned char byte;
int main()
{
byte num = 0;
char exitKey = '0';
cout << "Type in a number between 0 and 255.\n";
cin >> num;
cout << "\nYour number multiplied by 2 is:\n" << (num * 2);
cin >> exitKey;
return 0;
}
The value returned is the ASCII decimal value of the character I typed in. How can I get the actual value, treating the value as a number?
Help is appreciated. Thanks.
It doesn't matter what type-aliases you use, when reading using cin >> a character is always a character, and will be read as a character.
The value you are getting is the ASCII code for the character '1'.
If you want to read it as a number, then use a proper numeric datatype, like int.
Since you are using char datatype here. The 1 value entered here is considered as character and ASCII value of 1 (49) is getting stored and 49 * 2 = 98 is getting printed.
Instead of char use int as datatype.

Reading 'unsigned int' using 'cin'

I am trying to read an unsigned int using cin as follows:
#include <limits.h>
#include <iostream>
using namespace std;
int main(int argc, char* argv[])
{
unsigned int number;
// UINT_MAX = 4294967295
cout << "Please enter a number between 0 and " << UINT_MAX << ":" << endl;
cin >> number;
// Check if the number is a valid unsigned integer
if ((number < 0) || ((unsigned int)number > UINT_MAX))
{
cout << "Invalid number." << endl;
return -1;
}
return 0;
}
However, whenever I enter a value greater than the upper limit of unsigned integer (UINT_MAX), the program displays 3435973836. How do I check if the input given by user falls between 0 to UINT_MAX?
Two things:
Checking if an unsigned integer is < 0 or > UINT_MAX is pointless, since it can never reach that value! Your compiler probably already complains with a warning like "comparison is always false due to limited range of type".
The only solution I can think of is catching the input in a string, then use old-fashioned strtoul() which sets errno in case of overflow.
I.e.:
#include <stdlib.h>
unsigned long number;
std::string numbuf;
cin >> numbuf;
number = strtoul(numbuf.c_str(), 0, 10);
if (ULONG_MAX == number && ERANGE == errno)
{
std::cerr << "Number too big!" << std::endl;
}
Note: strtoul returns an unsigned long; there's no function strtou(), returning an unsigned int.
Your check makes no sense (which a compiler with properly enabled warnings would tell you) as your value is never under 0 and never over UINT_MAX, since those are the smallest and biggest value a variable of the type unsigned int (which number is) can hold.
Use the stream state to determine if reading into the integer worked properly.
You could read into an unsigned long long and test that against the unsigned int limit.
When users enter a number higher than UINT_MAX, cin caps it at UINT_MAX anyway. The value cannot be negative, either.
If you need to extend the range, use unsigned long long for input, and cast to unsigned int after the check. This will not guard against numbers that are outside of range of unsigned long long, though.
For a general-purpose solution, you can read a string, and do a conversion yourself using unsigned long long as your result.
If you try to read it into an unsigned int you are going to have to limit yourself to the constraints of an unsigned int.
The most general way to do what you're asking is to read the input as a string and parse it to make sure it's in the proper range. Once you have validated it, you can convert it to an unsigned int.

How to convert long long ASCII hex values into a string?

I have a long long holding ASCII hex values and want to convert it to a string. I have this code:
char myBuffer[8];
long long myLongLong = 0x7177657274797569;
sprintf(myBuffer,"%c%c%c%c%c%c%c%c",myLongLong);
int x;
cout << myBuffer;
cin >> x;
return 0;
The hex code should be "qwertyui", but it always gives other value.
I tried with %c, %s, %X but it doesn't give me the output I need, the closest was %c but it prints out only one char.
That code is wrong in so many ways I don't know where to start...
myBuffer is too small to hold the 8 chars + the NUL terminator, ie. should be myBuffer[9].
sprintf is expecting 8 arguments, you're only passing 1. The other required arguments will be whatever's on the stack.
myLongLong is not a char
You don't take into account endianness.
You're using C functions and doing things in a C way in C++. Why don't you use std::strings as opposed to C-style strings and stringstreams as an alternative to sprintf?
The closest almost working example of what you want, as similar to your example, is something like:
#include <cstdio>
#include <iostream>
using namespace std;
int main(void)
{
char myBuffer[9];
long long myLongLong = 0x7177657274797569;
char *c_ptr = (char*)&myLongLong;
sprintf(myBuffer,"%c%c%c%c%c%c%c%c", c_ptr[0], c_ptr[1], c_ptr[2], c_ptr[3], c_ptr[4], c_ptr[5], c_ptr[6], c_ptr[7]);
int x;
cout<<myBuffer;
cin>>x;
return 0;
}
Which will output "iuytrewq" on my little-endian machine. As I mentioned, that doesn't take into account the endianness. If the machine is little-endian then you could read/print the bytes in reverse.
I really don't understand why you're trying to do this though...
You could try
union { char buf[8]; long long num; } u;
u.num = 0x7177657274797569LL;
cout << u.str << endl;
But I don't understand what you want really to do. What about endianness ?
Use a string stream
long long myLongLong = 0x7177657274797569;
std::stringstream ss;
ss << std::hex << myLongLong;
std::cout << ss << std::endl
You want to print each byte of the long-long as an ascii char?
Then you need to loop over the long long extracting one byte at a time, look at bit shifts and masking.
Hint it's generally easier (if you know the length) to work from the last byte and shift right
or - you could just memcpy the long-long into the char array - except for any byte ordering issues
Try the following code.
#include <iostream>
using namespace std;
int main(void)
{
char myBuffer[8];
long long myLongLong = 0x7177657274797569;
for(int i = 0; i<8;i++)
{
myBuffer[i] = myLongLong>>(64-(i+1)*8);
}
cout<<myBuffer<<endl;
return 0;
}