为什么我在C中使用atoi()得到这个意外的结果?

时间:2010-04-28 12:44:50

标签: c atoi

我不明白以下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,但我无法确定具体原因。 根据我的理解,它应该是数组中每个值的十进制等值的总和?如果我错了,请纠正我。

4 个答案:

答案 0 :(得分:53)

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

}

..然后在循环中运行它。

或者,预先填充查找功能可以范围(更好)的字典。你不需要哈希,只需要一把钥匙 - &gt;值存储,因为您知道它将提前包含什么,标准ASCII字符是键,其对应的标识符是值。

答案 1 :(得分:12)

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

  

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

请参阅http://www.cplusplus.com/reference/clibrary/cstdlib/atoi/

答案 2 :(得分:6)

atoi()读取为i(ASCII转换为整数)。

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

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

答案 3 :(得分:2)

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

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

像其他人一样,不要使用atoi;请改用strtol