使用C将十六进制字符串常量转换为十进制值

时间:2019-03-07 17:22:03

标签: c kernighan-and-ritchie

以下程序将结果显示为0,而不是十六进制字符串常数的预期十进制等效值。

#include <stdio.h>

int my_htoi(char[]);

int main(void) {
    printf("%d", my_htoi("0xABC"));
    return 0;
}

int my_htoi(char str[]) {
    int i, num = 0;
    for (i = 0; i != '\0'; ++i) {
        if (str[i+1] == 'x' || str[i+1] == 'X') {
            i = i + 1;
            continue;
        }
        if (str[i] >= '0' && str[i] <= '9') {
            num = num * 16 + (str[i] - '0');
        } else if (str[i] >= 'a' && str[i] <= 'f') {
            num = num * 16 + (str[i] - 'a' + 10);
        } else if (str[i] >= 'A' && str[i] <= 'F') {
            num = num * 16 + (str[i] - 'A' + 10);
        }
    }
    return num;
}

下面的程序运行正常,并输出与十六进制字符串常量正确的十进制等效项。

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

int my_htoi(char[]);

int main(void) {
    printf("%d", my_htoi("0xABC"));
    return 0;
}

int my_htoi(char str[]) {
    int i, num = 0;
    for (i = 0; i < strlen(str); ++i) {
        if (str[i+1] == 'x' || str[i+1] == 'X') {
            i = i + 1;
            continue;
        }
        if (str[i] >= '0' && str[i] <= '9') {
            num = num * 16 + (str[i] - '0');
        } else if (str[i] >= 'a' && str[i] <= 'f') {
            num = num * 16 + (str[i] - 'a' + 10);
        } else if (str[i] >= 'A' && str[i] <= 'F') {
            num = num * 16 + (str[i] - 'A' + 10);
        }
    }
    return num;
}

唯一的区别是我们找到循环的合格条件的方式。为什么它不能与空字节检查一起使用?

2 个答案:

答案 0 :(得分:2)

错误的代码:i != '\0'检查索引是否为0。

for(i = 0; i != '\0'; ++i) {

应该在下面检查元素 str[i]是否为空字符

for(i = 0; str[i] != '\0'; ++i) {

存在其他问题unneeded incrementint溢出(此处最好使用unsigned),错误的x检测-考虑“ 0x0x0x1”,导致-+char str[]-> const char str[],...

答案 1 :(得分:1)

您的代码中存在一些问题:

  • 将循环索引i'\0'而不是str[i]进行比较,从而导致循环立即终止,返回值为0

  • x的测试不正确:它将导致"1x2"转换为2而不是1

  • 您接受f之后的字母并将其转换为数字。相反,该函数应在非十六进制数字的第一个字符处停止解析。

这是更正的版本:

#include <stdio.h>

int my_htoi(const char[]);

int main(void) {
    printf("%d", my_htoi("0xABC"));
    return 0;
}

int my_htoi(const char str[]) {
    int i = 0, num = 0;
    if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
        i += 2;
    for (; str[i] != '\0'; ++i) {
        if (str[i] >= '0' && str[i] <= '9') {
            num = num * 16 + (str[i] - '0');
        } else if (str[i] >= 'a' && str[i] <= 'f') {
            num = num * 16 + (str[i] - 'a' + 10);
        } else if (str[i] >= 'A' && str[i] <= 'F') {
            num = num * 16 + (str[i] - 'A' + 10);
        } else {
            break;
        }
    }
    return num;
}