【问题标题】:Convert a 10 digit string to int [closed]将 10 位字符串转换为 int [关闭]
【发布时间】:2020-08-30 12:57:48
【问题描述】:

我正在尝试将字符串转换为 intlong 值 但结果并不总是一样。

这是价值:

char data[10] = "4647232508";

我试过atoiatolstrtolstroll 但它们不会产生相同的结果。

转换后的值与预期结果不同。

【问题讨论】:

  • char data[10] 没有足够的空间容纳 "4647232508"
  • @pmg 很好的观察。 data 不是 字符串
  • 您还应该发布您的尝试产生的代码和输出。
  • Ahmed Elsenbawy 5 questions 一年多没有被接受。您可能想查看What should I do when someone answers my question?
  • @chux-ReinstateMonica 它是新一代。要求但不欣赏......给我给我给我

标签: c string integer


【解决方案1】:

请注意,对于具有 10 个字符的字符串,您需要 char data[11] 第 11 个元素作为空终止符 ('\0'),没有它 data 不能被视为字符串,它只是一个字符数组,使用这个非以 null 结尾的 char 数组作为您提到的任何函数的参数都会调用 undefined behavior,这是您代码中的主要问题。

使用char data[] = "4647232508"; 更安全,因为编译器会确定字符串所需的空间,包括其空终止符。

其他注意事项:

  1. 在 32 或 64 位系统 int type size is usually 4 bytes or 32 bits 中,其最大值为 2147483647 (231-1),如果使用 atoi 将字符串转换为 int,则再次调用未定义的行为。

atoi return value:

成功时,函数将转换后的整数作为int 值返回。 如果转换后的值超出了int 的可表示值范围,则会导致未定义的行为。如果有可能,请参阅 strtol 以获得更强大的跨平台替代方案。

注意long不保证有64位或8字节,也可以有4字节,也就是说atolatoi具有相同的行为,也可以调用未定义的行为。

  1. strtol 也可能无法按预期工作,原因如上一段所述(long 可以有 4 个字节),但是,由于它是一个更强大的函数,因此溢出时的行为是明确定义的。

strtol return value:

成功时,函数将转换后的整数作为long int 值返回。 如果无法执行有效转换,则返回零值 (0L)。 如果读取的值超出了long int 可表示的值范围,则函数返回LONG_MAXLONG_MIN(在<limits.h> 中定义),并将errno 设置为ERANGE

strtoll 应该输出正确的结果,因为 long long 的大小应该至少为 8 个字节,并且最大值为 9223372036854775807 (263-1) 。 behavior of strtollstrtol 相同,但返回值超出范围,即 LLONG_MAXLLONG_MIN

【讨论】:

    【解决方案2】:

    如果是出于教育目的,也许值得自己写一个或改进这个

    #define NOSTRING    1
    #define INVSTRING   2
    #define WRONGDIGIT  3
    
    long long myatoll(const char *str, int radix, int *error)
    {
        static char digits[] = "01234567890ABCDEF";
        long long result = 0;
        int sign  = 1;
    
        if(str && *str)
        {
            if(error) *error = 0;        
            if(*str == '-') { sign = -1; str++;}
            while(*str)
            {
                char *pos = strchr(digits, *str);
    
                if(!pos || pos - digits >= radix) 
                {
                    if(error) *error = WRONGDIGIT;
                    break;
                }
                result *= radix;
                result += pos - digits;
                str++;
            }
        }
        else
        {
            if(error) *error = INVSTRING;
        }
        return result * sign;
    }
    
    
    int main(void)
    {
        int errCode;
        printf("%lld\n", myatoll("-34565-67854", 10, &errCode));
        printf("The string was: %svalid\n", errCode ? "in" : "");
    }
    

    https://godbolt.org/z/asMxf4

    【讨论】:

    • @AhmedElsenbawy:这段代码是一个好的开始:研究它以了解如何将字符串转换为它所代表的数字。然后您可以尝试改进它:与 strtoll() 不同,它不支持初始空格,也不支持 + 号,不支持小写十六进制数字,也不支持大于 16 的基数,并且在 INT_MIN 和long long 的范围。它返回错误代码的能力是对strtoll() 的简化,但它不会将"-" 检测为无效。
    猜你喜欢
    • 2019-07-16
    • 2013-11-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-11
    相关资源
    最近更新 更多