微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为什么我不能在 c 中将字符串转换为 int

如何解决为什么我不能在 c 中将字符串转换为 int

假设我们有一个字符数组input = "12345678987654321",为什么我不能用atoi()把它转换成整数12345678987654321?我试过了,它返回了一些我无法理解的数字。

代码如下:

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

int main() {
    char num[20];
    scanf("%s\n",num);
    printf("%d",atoi(num));
    return 0;
}

解决方法

“12345678987654321”对于int通常太大,并且atoi不提供错误检测。

您可以使用 strto… 函数将字符串中的数字转换为整数类型。下面是一个使用 strtoimax 的示例,用于 C 实现支持的最宽有符号整数类型。还有其他类型的版本,例如 strtolllong long

strto… 函数提供错误检查功能,因此您可以检测数字是否过大并将其报告给用户或以其他方式处理。

#include <ctype.h>      // For isdigit and isspace.
#include <errno.h>      // For errno.
#include <inttypes.h>   // For stroimax and PRIdMAX.
#include <stdint.h>     // For intmax_t.
#include <stdio.h>      // For printf,fprintf,getchar,and ungetc.
#include <stdlib.h>     // For exit.


int main(void)
{
    // Read string.
    char string[20];
    int n = 0; // Number of characters read so far.
    while (1)
    {
        int c = getchar();

        // When we see the end of the input stream,leave the loop.
        if (c == EOF)
            break;

        /* When we see a white-space character (including new-line),put it
           back into the stream and leave the loop.
        */
        if (isspace(c))
        {
            ungetc(c,stdin);
            break;
        }

        /* If we see character that is not a space or a digit,complain,unless
           it is the first character and is a sign,"+" or "-".
        */
        if (!isdigit(c) && !(n == 0 && (c == '+' || c == '-')))
        {
            fprintf(stderr,"Error,non-digit seen:  \"%c\".\n",c);
            exit(EXIT_FAILURE);
        }

        // Record the digit.
        string[n++] = c;

        if (sizeof string / sizeof *string <= n)
        {
            fprintf(stderr,too many digits,can handle only %zu.\n",sizeof string / sizeof *string - 1);
                /* ("sizeof *string" is one for ordinary "char" arrays,but
                   using it allows changing to wide character types if
                   desired.)
                */
            exit(EXIT_FAILURE);
        }
    };
    // Finish string with a null character.
    string[n] = '\0';

    // Attempt to convert string to an intmax_t.
    char *end;
    errno = 0; // Initialize error indicator.
    intmax_t number = strtoimax(string,&end,0);

    /* Test whether the string failed to match the form for a numeral,because
       it was empty or was just a sign with no digits.
    */
    if (end == string)
    {
        fprintf(stderr,numeral has no digits.\n");
        exit(EXIT_FAILURE);
    }

    // Check for error.
    if (errno != 0)
    {
        fprintf(stderr,number is too large for intmax_t.\n");
        exit(EXIT_FAILURE);
    }

    /* Test whether the whole string was used in the conversion. It should have
       been,considering we ensured each character was a digit,but a check
       like this can be useful in other situations,where we are parsing a
       numeral from a more general string.
    */
    if (*end != 0)
    {
        fprintf(stderr,unexpected character in numeral,\"%c\".\n",*end);
        exit(EXIT_FAILURE);
    }

    // Print the number.
    printf("The number is %" PRIdMAX ".\n",number);
}
,

您得到奇怪输出的原因是输入的数字超出了 int 类型可表示的值范围。 atoi() 函数不一定执行错误检查,如果数字不能表示为 int,它实际上具有未定义的行为。您应该改用 strtol()

您的程序还有另一个潜在的未定义行为:如果用户输入的字符超过 19 个,则 scanf("%s\n",num) 可能会写入超出 num 数组的末尾,这会带来可怕的后果。您应该编写 scanf("%19s",num) 并测试潜在转换错误的返回值。

这是修改后的版本:

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

int main() {
    char num[20];

    if (scanf("%19s",num) != 1) {
        printf("no input\n");
        return 1;
    }
    int c = getchar();
    if (c != '\n' && c != EOF) {
        printf("too many characters\n");
        ungetc(c,stdin);
    }
    char *end;
    errno = 0;
    long value = strtol(num,10);
    if (end == num) {
        printf("input is not a number: %s",num);
    } else {
        if (errno != 0) {
            printf("number %s is too large for type long\n",num);
        } else
        if (value < INT_MIN || value > INT_MAX) {
            printf("number %ld is too large for type int\n",value);
        } else {
            printf("value is %d\n",(int)value);
        }
        if (*end != '\0') {
            printf("extra characters after the number: %s",end);
        }
    }
    return 0;
}
,

您输入的“12345678987654321” atoi 在 int 中,int 的范围从 -2,147,483,648 - 2,647 开始,因此为了修复它,请使用 atol() l-long,这只是因为范围或如果您使用的是 32 位机器,那么您需要使用 long long int 即 atoll() 而不是 atol() data size

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
    char num[20];
    scanf("%s",num);
    //printf("\n%s",num);
    printf("\n%ld",atol(num)); //<- atoi(num) to atol(num)
    return 0;
}

atol() 查看更多atoi()atol()atoll()

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。