c ++奇怪的问题将char转换为int

Posted

技术标签:

【中文标题】c ++奇怪的问题将char转换为int【英文标题】:c++ weird problem converting a char to int 【发布时间】:2011-09-01 16:57:20 【问题描述】:

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

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

提前致谢!

【问题讨论】:

你想做什么?为什么输出是NOT OK?什么是预期的输出? atoi() 需要 NULL 终止的 c 样式字符串,这可能是问题所在。紧跟在tmpchar 之后的内存未初始化,可以是任何内容。 请注意,显示此行为的数字应为 48-57,但有时也应为 9-13、43、45、46。(否则可能导致程序崩溃) 【参考方案1】:

问题出在这里:

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;

【讨论】:

【参考方案2】:
atoi(&tmpchar)

我认为这只会引发未定义的行为。因为&amp;tmpchar 的类型是char*,这是正确的c 字符串类型,但它不是以null 结尾的字符串。

你为什么不干脆这样做:

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

【讨论】:

【参考方案3】:

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】:

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

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

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

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

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

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

int number = digit - '0';

【讨论】:

【参考方案5】:

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

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

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

【讨论】:

以上是关于c ++奇怪的问题将char转换为int的主要内容,如果未能解决你的问题,请参考以下文章

将 int 转换为 char* 时的奇怪输出

C# 将 int 转换为 2 个字节的数组

Arduino 串行返回奇怪的数字 + 无法将 char 数组转换为 int C++

C ++奇怪的char *参数问题(不兼容的类型)

将字符串转换为int-objective c [重复]

将 INT_MAX 转换为浮点数,然后再转换回整数。