K& R练习2-3“十六进制到整数转换器”问题

时间:2009-04-30 01:44:32

标签: c kernighan-and-ritchie kr-c

我编写的程序在仅包含单个十六进制值的人口统计数据中工作。 (可能不是最优雅的解决方案,但我是一个新的程序员)我的问题是,我将如何处理多个十六进制数字,如0xAF或0xFF等?我并不完全确定,在尝试中我似乎非常困惑自己。我不是要求有人握住我的手,而是给我一个提示我在这段代码中出错了以及如何修复它的想法。

谢谢:)

/* Exercise 2-3.  Write the function htoi(s), which converts a string of
 * hexadecimal digits (including an optional 0x or 0X) into it's equivalent
 * integer value. The allowable digits are 0...9 - A...F and a...f.
 * 
 */

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

#define NL '\n'
#define MAX 24

int htoi(char *hexd);

int
main(void)
{
    char str[MAX] = {0};
    char hex[] = "0123456789ABCDEFabcdef\0";
    int c;
    int i;
    int x = 0;

    while((c = getchar()) != EOF) {
        for(i = 0; hex[i] != '\0'; i++) {
            if(c == hex[i])
                str[x++] = c;
        }
        if(c == NL) {
            printf("%d\n", htoi(str));
            x = 0, i = x;
        }
    }
    return 0;
}

int
htoi(char *hexd) 
{
    int i;
    int n = 0;

    for(i = 0; isdigit(hexd[i]); i++)
        n = (16 * i) + (hexd[i] - '0');
    for(i = 0; isupper(hexd[i]); i++) /* Let's just deal with lowercase characters */
        hexd[i] = hexd[i] + 'a' - 'A';
    for(i = 0; islower(hexd[i]); i++) {
        hexd[i] = hexd[i] - 'a';
        n = (16 + i) + hexd[i] + 10;
        n = hexd[i] + 10;
    }
    return n;
}

4 个答案:

答案 0 :(得分:1)

有人已经问过这个问题(hex to int,k&amp; r 2.3)。 看一看,有很多好的答案,但你必须填补空白。

Hex to Decimal conversion [K&R exercise]

编辑:

in

char hex[] = "0123456789ABCDEFabcdef\0";

\ 0不是必需的。十六进制是alredy nul终止。是len(0 ... f)+ 1 = 17个字节长。

答案 1 :(得分:1)

我会选择一个循环,然后留给你重新考虑你的实现。特别是:

for(i = 0; isdigit(hexd[i]); i++)
    n = (16 * i) + (hexd[i] - '0');

不会做你认为它做的事情......

  • 它仅处理isdigit()为TRUE的第一个字符范围。
  • 它停在isdigit()为FALSE的第一个字符上。
  • 由于isdigit('\0')已知为FALSE,因此不会超过结束。不过,我担心这可能是偶然的错误。
  • 它确实正确转换了可以用数字0-9表示的十六进制数字。

整个计划需要考虑的事情:

  • 通常,除非修改是有价值的副作用,否则不要修改输入字符串。在您的示例代码中,您将字符串强制为小写就地。就地修改输入字符串意味着编写htoi("1234")的用户正在调用未定义的行为。你真的想要这样做。
  • 只有一个数字循环将处理非零数字。
  • 如果我将0123456789ABCDEF0123456789ABCDEF发送给stdin会怎样?
  • 您对80000000的期望是什么?你得到了什么?你感到惊讶吗?
  • 就个人而言,我不会将NL用于'\n'。 C用法非常希望在宏观不方便的很多环境中看到\n,所以现在最好习惯它...

答案 2 :(得分:0)

我认为字符串的MAX大小应该是10或18而不是24。(如果您已经检查过机器上的int并按照下面的推理,那么将其包括为您的代码中的注释。)

10:因为htoi()返回int,int通常是4个字节(也检查你的系统),所以十六进制数最多可以是8位数(4位到1位十六位数,8位)比特到一个字节),我们希望允许选择0x0X

18:如果htoi()返回一个long及其8个字节(再次检查你的系统)会更好,所以十六进制数字的长度最多可以是16位,我们想要允许对于可选的0x0X

请注意,intlong的尺寸与机器有关,请查看K&amp; R书中的练习2.1以查找它们。

答案 3 :(得分:0)

这是我的经典htoi()函数版本,用于将多个十六进制值转换为十进制整数。它是一个完整的工作程序编译并运行。

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

int htoi(const char*);
int getRawInt(char);

int main(int argc, char **argv) {
    char hex[] = "       ";
    printf("Enter a hexadecimal number (i.e 33A)\n");
    scanf("%s", hex);

    printf("Hexedecimal %s in decimal is %d\n", hex, htoi(hex)); // result will be 826
    return 0;
}

int htoi(const char *hex) {
    const int LEN = strlen(hex) -1;
    int power = 1;
    int dec = 0;

    for(int i = LEN; i >= 0; --i) {
        dec += getRawInt(hex[i]) * power;
        power *= 16;
    }

    return dec;
}

int getRawInt(char c) {
    if(isalpha(c)) {
        return toupper(c) - 'A' + 10;
    } return c-'0';
}