我是C ++的新手,当我遇到一个非常奇怪的问题时,我正试图从Project Euler中解决其中一个问题。我把错误减少到了以下。
考虑以下简单代码:
#include <iostream>
using namespace std;
int main() {
int numdigits;
cout << "digits: ";
cin >> numdigits;
char tmpchar;
cin >> tmpchar;
cout << atoi(&tmpchar) << endl;
return 0;
}
基本上如果第一个输入(numdigits)低于48,一切正常,但如果输入为48或更高,如果有一个非常奇怪的行为:
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
发生了什么事?我疯狂地试图找到算法中的错误,直到我发现错误出现在代码的那部分,我没有先去看看。
提前致谢!
答案 0 :(得分:7)
问题在于:
char tmpchar;
cin >> tmpchar;
cout << atoi(&tmpchar) << endl;
atoi
需要一个NUL-terminated string,这不是你给它的(没有NUL字符,除非你有时偶然得到一个)。
可能(丑陋)的修复是:
char tmpchar[2] = {0};
cin >> tmpchar[0];
cout << atoi(tmpchar) << endl;
如果您正在处理多字符字符串,那么使用std::string
将是可行的方法:
std::string str;
cin >> str;
cout << atoi(str.c_str()) << endl;
答案 1 :(得分:5)
atoi(&tmpchar)
我认为这只会调用未定义的行为。因为&tmpchar
的类型是char*
,它是正确的c-string类型,但它不是空的字符串。
你为什么不这样做:
int i = tmpchar - '0';
cout << i << endl; //prints whatever single-digit you enter for tmpchar
或者如果要打印tmpchar
的ASCII值,请执行以下操作:
int i = tmpchar;
cout << i << endl; //prints the ASCII value of tmpchar
甚至更简单:
cout << (int) tmpchar << endl; //prints the ASCII value of tmpchar
答案 2 :(得分:2)
atoi
的参数必须是以空字符结尾的字符数组,而不仅仅是指向一个字符的指针。
char tmpchar[2] = {0};
cin >> tmpchar[0];
cout << atoi(&tmpchar) << endl;
这里{0}将所有数组元素设置为0,cin
读取第一个,第二个字符保持为空,因此&tmpchar
生成一个指向以null字符结尾的字符数组的指针。
答案 3 :(得分:2)
atoi()
采用NUL('\ 0')终止字符指针。你指的是第一个字符,但不能保证第二个字符是NUL。请尝试以下方法。
#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;
}
答案 4 :(得分:2)
atoi
将以null结尾的字符串作为参数。这是一个在末尾带有空字符('\ 0')的字符数组。
+---+---+---+
|'1'|'0'|\0 | = "10"
+---+---+---+
您正在传递单个字符的地址。但是没有终止空字符!
+---+---+---+
|'3'| ? | ? | = ?
+---+---+---+
这是未定义的行为,这就是你得到奇怪结果的原因。
您可以通过以下安全方式从单个数字字符中获取数字:
int number = digit - '0';