Reputation: 514
I'm a total newbie to C++ and I was trying to do one of the problems from Project Euler when I had a very weird problem. I reduced the error to the following.
Consider the following simple code:
#include <iostream>
using namespace std;
int main() {
int numdigits;
cout << "digits: ";
cin >> numdigits;
char tmpchar;
cin >> tmpchar;
cout << atoi(&tmpchar) << endl;
return 0;
}
Basically if the first input (numdigits) is below 48 everything works fine but if the input is 48 or greater if have a very weird behaviour:
air:programming santi$ ./lol
digits: 30
3
3 <--- OK
air:programming santi$ ./lol
digits: 48
3
30 <--- Not OK
air:programming santi$ ./lol
digits: 49
3
31 <--- Not OK
air:programming santi$ ./lol
digits: 50
3
32 <--- Not OK
What is going on? I got mad trying to find the error in the algorithm until I found out that the error was in that part of the code where I didn't bother to look at first.
Thanks in advance!
Upvotes: 4
Views: 3273
Reputation: 24439
The argument to atoi
must be a null-terminated array of characters, not just a pointer to one character.
char tmpchar[2] = {0};
cin >> tmpchar[0];
cout << atoi(&tmpchar) << endl;
Here {0} sets all array elements to 0, cin
reads the first one, the second character remains null, so &tmpchar
makes a pointer to a character array that is terminated with null character.
Upvotes: 2
Reputation: 361612
atoi(&tmpchar)
I think this would simply invoke undefined behaviour. Because the type of &tmpchar
is char*
which is correct c-string type, but its not null-teminated string.
Why don't you simply do this:
int i = tmpchar - '0';
cout << i << endl; //prints whatever single-digit you enter for tmpchar
Or if you want to print the ASCII value of tmpchar
, then do this:
int i = tmpchar;
cout << i << endl; //prints the ASCII value of tmpchar
Or even simpler:
cout << (int) tmpchar << endl; //prints the ASCII value of tmpchar
Upvotes: 5
Reputation: 500673
The problem is here:
char tmpchar;
cin >> tmpchar;
cout << atoi(&tmpchar) << endl;
atoi
expects a NUL-terminated string, which isn't what you're giving it (there's no NUL character except that you may be sometimes getting one by chance).
A possible (ugly) fix is:
char tmpchar[2] = {0};
cin >> tmpchar[0];
cout << atoi(tmpchar) << endl;
If you're dealing with multiple-character strings, then using std::string
would be the way to go:
std::string str;
cin >> str;
cout << atoi(str.c_str()) << endl;
Upvotes: 7
Reputation: 234584
atoi
takes a null-terminated string as an argument. That is an array of characters with a null character ('\0') at the end.
+---+---+---+
|'1'|'0'|\0 | = "10"
+---+---+---+
You are passing the address of a single character. But there is no terminating null character!
+---+---+---+
|'3'| ? | ? | = ?
+---+---+---+
This is undefined behaviour, and that's why you get weird results.
You can obtain a number from a single digit character in a safe manner like this:
int number = digit - '0';
Upvotes: 2
Reputation: 21123
atoi()
takes a NUL ('\0') terminated character pointer. You're pointing it at the first character, but there is no guarantee that the second character is NUL. Try the following.
#include <iostream>
using namespace std;
int main() {
int numdigits;
cout << "digits: ";
cin >> numdigits;
char tmpchar[2];
cin >> tmpchar[0];
tmpchar[1] = '\0';
cout << atoi(tmpchar) << endl;
return 0;
}
Upvotes: 2