【问题标题】:Why do I get this unexpected result using atoi() in C?为什么我在 C 中使用 atoi() 会得到这个意想不到的结果?
【发布时间】:2010-04-28 12:44:49
【问题描述】:

下面C代码的结果我看不懂。

main()
{
    char s[] = "AAA";
    advanceString(s);
}

void advanceString(p[3])
{
    int val = atoi(p);
    printf("The atoi val is %d\n",val);
}

这里atoi 的值显示为0,但我无法弄清楚确切的原因。 根据我的理解,它应该是数组中每个值的十进制等值的总和?如果我错了,请纠正我。

【问题讨论】:

  • 请粘贴实际编译的代码。
  • @Marcelo 在这种情况下真的很重要吗?
  • 也许,也许不是。但是,考虑到OP已经看到运行程序的结果,真的那么难吗?
  • @maddy,因为这不是atoi() 的本意。
  • @maddy strtol 也不会按照您的描述进行操作。没有标准库函数会;这不是人们通常会做的事情。

标签: c atoi


【解决方案1】:

atoi() 将整数的字符串表示形式转换为其值。它不会将任意字符转换为其十进制值。例如:

int main(void)
{
    const char *string="12345";

    printf("The value of %s is %d\n", string, atoi(string));

    return 0;
}

标准 C 库中没有任何内容可以将“A”转换为 65 或“Z”转换为 90,您需要自己编写,特别是对于您期望作为输入的任何字符集。

既然您知道 atoi() 做了什么,请不要使用它来处理您想出的任何数字输入。你真的应该处理不是你所期望的输入。 嗯,当我输入 65 而不是 A 时会发生什么? 老师喜欢破坏东西。

atoi() 不做任何错误检查,这使得任何依赖它来转换任意输入的东西充其量都是脆弱的。相反,请使用strtol()(以 POSIX 为中心的示例):

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>

int main(void)
{
    static const char *input ="123abc";
    char *garbage = NULL;
    long value = 0;

    errno = 0;

    value = strtol(input, &garbage, 0);

    switch (errno) {
        case ERANGE:
            printf("The data could not be represented.\n");
            return 1;
        // host-specific (GNU/Linux in my case)
        case EINVAL:
            printf("Unsupported base / radix.\n");
            return 1;
    }

    printf("The value is %ld, leftover garbage in the string is %s\n",
           // Again, host-specific, avoid trying to print NULL.
           value, garbage == NULL ? "N/A" : garbage);

    return 0;
}

运行时,会给出:

值为123,剩余垃圾在 字符串是 abc

如果您不关心保存/检查垃圾,可以将第二个参数设置为NULL。不需要free(garbage)。另请注意,如果您将 0 作为第三个参数传递,则假定输入是十进制、十六进制或八进制表示的所需值。如果您需要 10 的基数,请使用 10 - 如果输入不符合您的预期,它将失败。

您还需要检查 long int 可以处理的最大值和最小值的返回值。但是,如果返回任何一个以指示错误,则设置 errno。读者的练习是将*input123abc 更改为abc123

检查退货很重要,因为您的示例显示了如果不这样做会发生什么。 AbcDeFg 不是整数的字符串表示形式,您需要在函数中处理它。

对于您的实施,我能给您的最基本建议是一系列开关,例如:

// signed, since a return value of 0 is acceptable (NULL), -1
// means failure
int ascii_to_ascii_val(const char *in)
{
    switch(in) {
        // 64 other cases before 'A'
        case 'A':
           return 65;
        // keep going from here
        default:
            return -1; // failure

}

.. 然后循环运行。

或者,预先填充一个查找函数可以作用域的字典(更好)。您不需要哈希,只需要一个键 -> 值存储,因为您提前知道它将包含什么,其中标准 ASCII 字符是键,它们对应的标识符是值。

【讨论】:

  • 您可以使用strerror 从错误代码中获取人类可读的文本。
  • 虽然答案是正确的,但如果答案能告诉 OP 如何解决他的问题,那将更有帮助。
  • @Alex 信不信由你,我刚刚看到你的评论。编辑了一下:)
  • garbage == NULL 测试似乎没有必要。我没有看到strtol() 的指定结果会导致garbage == NULL。 FWIW EINVAL 不在 C 规范中。
  • @chux 似乎是特定于 GNU/Linux 的。已添加评论。
【解决方案2】:

它尝试将字符串转换为整数。由于 AAA 无法转换为整数,因此值为 0。请尝试给它 42 或其他值。

如果没有有效的转换可以 执行,返回零值。

http://www.cplusplus.com/reference/clibrary/cstdlib/atoi/

【讨论】:

    【解决方案3】:

    atoi() 读取为 a 到 i(ASCII 到整数)。

    atoi() 将表示十进制数的字符串转换为整数。

    char s[] = "42";
    int num = atoi(s); //The value of num is 42.
    

    【讨论】:

      【解决方案4】:

      atoi 期望它的参数是十进制(base-10)整数常量的字符串表示; AAA 不是有效的十进制整数常量,因此 atoi 返回 0,因为它没有其他方式来指示输入无效。

      请注意,atoi 将转换为不属于有效整数常量的第一个字符;也就是说,“123”和“123w”都会被转换成123。

      就像其他人所说的那样,不要使用atoi;请改用strtol

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-12-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-07-10
        • 2023-03-11
        • 1970-01-01
        相关资源
        最近更新 更多