首页 > 解决方案 > 作业,写一个将一串数字转换成整数的函数

问题描述

我知道我可以很容易地在 Internet 上找到该功能的代码页,但我想知道为什么在传递 10 位数组后,预期结果不像以前的那样。

#include <stdio.h>

int xstraylen(char *arr) {
    int len;
    
    for (len = 0; *(arr + len) != '\0'; len++) {
        //printf("%c ", *(arr + len));
    }
    return len;
}

int str_into_int(char *str) {
    int power = 10, len, number;
    long int value = 0;
    
    len = xstraylen(str);
    printf("\n%d\n", len);

    for (int index = 0; index < len; index++) {
        number = (int)(*(str + index) - 48);
        value += number;
        value *= power;
        printf("-%d- %d %d ", index, number, value);
    }

    value /= power;

    return value;
}

int main() {    
    char *str = "1234567890";  
    int value;
    
    value = str_into_int(str);
    printf("\n\n%d", value);

    return 0;
}

输出

10

-0- 1 10 -1- 2 120 -2- 3 1230 -3- 4 12340 -4- 5 123450 -5- 6 1234560 -6- 7 12345670 -7- 8 123456780 -8- 9 1234567890 -9- 0 -539222988 

-53922298

标签: cfor-loopinteger-overflowfunction-definition

解决方案


您的代码不适用于 10 位数字,因为value在添加数字后总是在循环中乘以 10 并在最后除以。对于 10 位数字,最后一个乘法会在您的平台上导致算术溢出,其中两者都int可能long有 32 位。

您应该在添加数字之前乘以value并删除最后的除法:

int str_into_int(char *str) {
    int power = 10, len, number;
    long int value = 0;
    
    len = xstraylen(str);
    printf("\n%d\n", len);

    for (int index = 0; index < len; index++) {
        value *= power;
        number = (int)(*(str + index) - 48);
        value += number;
        printf("-%d- %d %ld ", index, number, value);
    }
    return value;
}

请注意,可以进一步简化和修改代码以处理更大的值并检测溢出:

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

unsigned long long int str_into_int(const char *str) {
    unsigned long long int value = 0;

    for (int i = 0; str[i] >= '0' && str[i] <= '9'; i++) {
        unsigned int digit = str[i] - '0';
        if (value > ULLONG_MAX / 10 ||
            (value == ULLONG_MAX / 10 && digit > ULLONG_MAX % 10)) {
                printf("conversion exceeds range of unsigned long long\n");
                return ULLONG_MAX;
            }
        value = value * 10 + digit;
    }
    return value;
}

void test(const char *str) {
    printf("%s -> %llu\n", str, str_into_int(str));
}

int main() {
    test("1234567890");
    test("12345678901234567890");
    test("18446744073709551615");
    test("18446744073709551616");
    test("123456789012345678901234567890");
    return 0;
}

输出:

1234567890 -> 1234567890
12345678901234567890 -> 12345678901234567890
18446744073709551615 -> 18446744073709551615
conversion exceeds range of unsigned long long
18446744073709551616 -> 18446744073709551615
conversion exceeds range of unsigned long long
123456789012345678901234567890 -> 18446744073709551615

推荐阅读