4

我是 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

到底是怎么回事?我很生气试图在算法中找到错误,直到我发现错误出现在我没有费心去看的那部分代码中。

提前致谢!

4

5 回答 5

7

问题在这里:

char tmpchar;
cin >> tmpchar;
cout << atoi(&tmpchar) << endl;

atoi期望一个以NUL 结尾的 string,这不是你给它的(没有 NUL 字符,除了你有时可能会偶然得到一个)。

一个可能的(丑陋的)修复是:

char tmpchar[2] = {0};
cin >> tmpchar[0];
cout << atoi(tmpchar) << endl;

如果您正在处理多字符串,那么 usingstd::string将是要走的路:

std::string str;
cin >> str;
cout << atoi(str.c_str()) << endl;
于 2011-09-01T17:01:59.567 回答
5
atoi(&tmpchar)

我认为这只会调用未定义的行为。因为类型&tmpcharchar*正确的 c 字符串类型,但不是以空字符结尾的字符串。

你为什么不简单地这样做:

int i = tmpchar - '0';
cout << i << endl; //prints whatever single-digit you enter for tmpchar

或者,如果您想打印 的 ASCII 值tmpchar,请执行以下操作:

int i = tmpchar;
cout << i << endl; //prints the ASCII value of tmpchar

或者更简单:

cout << (int) tmpchar << endl; //prints the ASCII value of tmpchar
于 2011-09-01T17:02:02.727 回答
2

to 的参数atoi必须是一个以空字符结尾的字符数组,而不仅仅是指向一个字符的指针。

char tmpchar[2] = {0};
cin >> tmpchar[0];
cout << atoi(&tmpchar) << endl;

这里 {0} 将所有数组元素设置为 0,cin读取第一个元素,第二个字符保持为空,因此&tmpchar创建一个指向以空字符结尾的字符数组的指针。

于 2011-09-01T17:02:27.600 回答
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;
}
于 2011-09-01T17:04:01.280 回答
2

atoi以空字符结尾的字符串作为参数。那是一个以空字符('\0')结尾的字符数组。

+---+---+---+
|'1'|'0'|\0 | = "10"
+---+---+---+

您正在传递单个字符的地址。但是没有终止空字符!

+---+---+---+
|'3'| ? | ? | = ?
+---+---+---+

这是未定义的行为,这就是为什么你会得到奇怪的结果。

您可以像这样安全地从单个数字字符中获取数字:

int number = digit - '0';
于 2011-09-01T17:05:43.907 回答