【问题标题】:c++ weird problem converting a char to intc ++奇怪的问题将char转换为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。(否则可能导致程序崩溃)

标签: c++ atoi


【解决方案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 生成一个指向以空字符结尾的字符数组的指针。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2012-06-25
            • 1970-01-01
            • 2021-05-03
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-04-05
            相关资源
            最近更新 更多