简体   繁体   English

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

[英]Converting from hexadecimal to decimal number in C

I am doing the exercise in the C Programming language book, and exercise 2-3 asked us to write a function htoi to convert a hexadecimal number to decimal number. 我正在C编程语言书中进行练习,练习2-3要求我们编写一个函数htoi来将十六进制数转换为十进制数。

This is the code I wrote, however when it runs, it always show that my hexadecimal number is illegal. 这是我编写的代码,但是运行时始终显示我的十六进制数字是非法的。

Please help! 请帮忙!

#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;
  }

A string is a sequence of characters that terminates at the first '\\0' character. 字符串是一个字符序列,终止于第一个'\\0'字符。 That means "0x134" terminates with a '\\0' character value, not an EOF value. 这意味着"0x134"'\\0'字符值而不是EOF值结尾。

You are operating on a sequence of characters that you expect to be terminated by an EOF value, but that is simply not possible. 您正在处理期望由EOF值终止的字符序列,但这根本不可能。 I'll explain why later... Suffice to say for now, the string "0x134" contains no EOF value. 稍后我将解释原因...足以说了,字符串"0x134"包含EOF值。

Your loop reaches the string-terminating '\\0' , which isn't in the range 0..9 , a..f or A..F and so this branch executes: 您的循环到达以字符串结尾的'\\0' ,它不在0..9a..fA..F范围内,因此该分支执行:

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

Perhaps you meant to write your loop like so: 也许您打算这样写循环:

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

I promised to explain what is wrong with expecting EOF to exist as a character value. 我答应解释期望EOF作为字符值存在的问题。 Assuming an unsigned char is 8 bits, getchar can return one of 256 character values, and it will return them as a positive unsigned char value... OR it can return the negative int value EOF , corresponding to an error or end-of-file. 假设unsigned char为8位,则getchar可以返回256个字符值之一,并将其​​作为正的 unsigned char值返回。 或者,它可以返回负的 intEOF ,对应于错误或结束符。文件。

Confused? 困惑? In an empty file, there are no characters... Yet if you try to read a character from the file, you will get EOF every time, in spite of there being no characters. 在一个空文件中,没有字符...但是,如果尝试从文件中读取字符,尽管没有字符,但每次都会得到EOF Hence, EOF is not a character value. 因此, EOF不是字符值。 It's an int value, and should be treated as such before you attempt to convert the value to a character, like so: 这是一个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;
}

On another note, c >= '0' && c <= '9' will evaluate truthfully when c is one of the digits in the range 0..9 ... This is a requirement from the C standard 另外,当c是0..9范围内的数字之一时, c >= '0' && c <= '9'将如实求值...这是C标准的要求

Neither c >= 'a' && c <= 'f' nor c >= 'A' && c <= 'F' are required to evaluate truthfully under any circumstance, however. 但是,在任何情况下都不需要c >= 'a' && c <= 'f'c >= 'A' && c <= 'F'来进行真实评估。 It happens to work on your system, because you are using ASCII which contains all of the lowercase letters in one contiguous block, and all of the uppercase letters in another contiguous block. 它恰好在您的系统上工作,因为您使用的ASCII包含一个连续块中的所有小写字母,以及另一个连续块中的所有大写字母。 C does not require that ASCII be the character set. C不需要ASCII作为字符集。

If you want this code to work portably , you might consider something like: 如果您希望此代码可移植地工作,则可以考虑以下方法:

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 */
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM