在C中从十六进制转换为十进制数

时间:2015-11-13 02:55:24

标签: c

我正在C编程语言书中练习,练习2-3要求我们编写一个函数htoi来将十六进制数转换为十进制数。

这是我写的代码,但是当它运行时,它总是显示我的十六进制数字是非法的。

请帮忙!

#include<stdio.h>

#define TRUE 1
#define FALSE 0

  int htoi (char s[]);
  int main() {
      printf("The decimal number is %d\n", htoi("0x134"));
      return 0;
  }
  int htoi (char s[]) {
      int j;   /* counter for the string */
      int temp;  /* temp number in between conversion */
      int number; /* the converted number */
      int ishex;  /* if the number is a valid hexadecimal number */
      char c;

      number = 0;
      temp = 0;
      ishex = FALSE;

      if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) {
          ishex = TRUE;
      }
      else {
          ishex = FALSE;
          printf("This is not valid hexadecimal number.\n");
          return number = 0;
      }
      if (ishex == TRUE) {
          for (j = 2; (c = s[j]) != EOF; ++j) {
              if (c >= '0' && c <= '9')
                  temp = c - '0';
              else if (c >= 'a' && c <= 'f')
                  temp = 10 + c - 'a';
              else if (c >= 'A' && c <= 'F')
                  temp = 10 + c - 'A';
              else {
                  printf("This is a illegal hexadecimal number.\n");
                  ishex = FALSE;
                  return 0;
              }
              number = number * 16 + temp;
          }
      }      
      return number;
  }

1 个答案:

答案 0 :(得分:0)

字符串是终止于第一个'\0'字符的字符序列。这意味着"0x134"'\0'字符值终止,而不是EOF值。

您正在操作一系列字符,您期望以EOF值终止这些字符,但这根本不可能。我稍后会解释原因...我现在只想说,字符串"0x134"不包含EOF值。

您的循环到达字符串终止'\0',该字符串不在0..9a..fA..F范围内,因此此分支执行:

          else {
              printf("This is a illegal hexadecimal number.\n");
              ishex = FALSE;
              return 0;
          }

也许你打算像这样写你的循环:

for (j = 2; (c = s[j]) != '\0'; ++j) {
    /* SNIP */
}

我答应解释期待EOF作为字符值存在的问题。假设unsigned char为8位,getchar可以返回256个字符值中的一个,并将它们作为 unsigned char值返回... 它可以返回否定 intEOF,对应于错误或文件结尾。

困惑?在一个空文件中,没有字符......但是如果你尝试从文件中读取一个字符,每次都会得到EOF,尽管没有字符。因此,EOF不是字符值。它是一个int值,应该在之前将视为,然后尝试将值转换为字符,如下所示:

int c = getchar();
if (c == EOF) {
    /* Here, c is NOT A CHARACTER VALUE! *
     * It's more like an error code ...  *
     * XXX: Break or return or something */
}
else {
    /* Here, c IS a character value, ... *
     * so the following conversion is ok */
    char ch = c;
}

另一方面,如果c是范围c >= '0' && c <= '9'中的一个数字,0..9将真实地评估......这是C标准的要求

然而,在任何情况下,都不需要c >= 'a' && c <= 'f'c >= 'A' && c <= 'F'进行真实评估。它碰巧适用于您的系统,因为您使用的ASCII包含一个连续块中的所有小写字母,以及另一个连续块中的所有大写字母。 C不要求ASCII是字符集。

如果您希望此代码能够移植,您可能会考虑以下内容:

char alpha_digit[] = "aAbBcCdDeEfF";
if (c >= '0' && c <= '9') {
    c -= '0';
}
else if (strchr(alpha_digit, c)) {
    c = 10 + (strchr(alpha_digit, c) - alpha_digit) / 2;
}
else {
    /* SNIP... XXX invalid digit */
}