0

我正在尝试用 C 语言编写一个将十六进制数转换为整数的程序。我已经成功编写了一个将八进制转换为整数的程序。但是,一旦我开始使用字母 (af),问题就开始了。我对该程序的想法是广告如下:

  1. 参数必须是一个以 0x 或 0X 开头的字符串。

  2. 参数十六进制数存储在 char 字符串 s[] 中。

  3. 整数 n 被初始化为 0,然后按照规则进行转换。

我的代码如下(我只阅读了 K & R 的 p37,所以对指针不太了解):

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

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

int htoi(const char s[]) { //why do I need this to be constant??
    int i;
    int n = 0;
    int l = strlen(s);
    while (s[i] != '\0') {
        if ((s[0] == '0' && s[1] == 'X') || (s[0] == '0' && s[1] == 'x')) {
            for (i = 2; i < (l - 1); ++i) {
                if (isdigit(s[i])) {
                    n += (s[i] - '0') * pow(16, l - i - 1);
                } else if ((s[i] == 'a') || (s[i] == 'A')) {
                    n += 10 * pow(16, l - i - 1);
                } else if ((s[i] == 'b') || (s[i] == 'B')) {
                    n += 11 * pow(16, l - i - 1);
                } else if ((s[i] == 'c') || (s[i] == 'C')) {
                    n += 12 * pow(16, l - i - 1);
                } else if ((s[i] == 'd') || (s[i] == 'D')) {
                    n += 13 * pow(16, l - i - 1);
                } else if ((s[i] == 'e') || (s[i] == 'E')) {
                    n += 14 * pow(16, l - i - 1);
                } else if ((s[i] == 'f') || (s[i] == 'F')) {
                    n += 15 * pow(16, l - i - 1);
                } else {
                    ;
                }
            }
        }
    }
    return n;
}


int main(void) {
    int a = htoi("0x66");
    printf("%d\n", a);
    int b = htoi("0x5A55");
    printf("%d\n", b);
    int c = htoi("0x1CA");
    printf("%d\n", c);
    int d = htoi("0x1ca");
    printf("%d\n", d);
} 

我的问题是:

1. 如果我在 htoi(s) 的参数中不使用 const,我会从 g++ 编译器收到以下警告:

2-3.c:在函数“int main()”中:2-3.c:93:20:警告:不推荐将字符串常量转换为“char*”[-Wwrite-strings] 2-3.c:97 :22: 警告:不推荐从字符串常量转换为 'char*' [-Wwrite-strings] 2-3.c:101:21:警告:不推荐从字符串常量转换为 'char*' [-Wwrite-strings] 2 -3.c:105:21:警告:不推荐将字符串常量转换为 'char*' [-Wwrite-strings]

为什么是这样?

2.为什么我的程序需要这么长时间才能运行?我还没有看到结果。

3.为什么我在终端输入 cc 2-3.c 而不是 g++ 2-3.c 时,会出现以下错误信息:

“未定义对‘pow’的引用”

在我使用过电源功能的每一行上?

4. 请指出我的程序中的其他错误/潜在改进。

4

6 回答 6

1
  1. char[]表示const您不能在函数中更改它。从 aconst转换为 not-const给出警告。有很多话要说const。查看它的维基百科页面
  2. --
  3. 可能cc没有链接正确的库。尝试以下构建命令:cc 2-3.c -lm

改进:

  1. 不要使用pow(),它在处理时间方面相当昂贵。
  2. 对字母使用与数字相同的技巧来获取值,而不是使用固定的“魔术”数字。
  3. 你不需要最后else一部分。只需将其留空(或在此处输入错误消息,因为不允许使用这些字符)。

祝你好运!

关于我对pow()调用的评论(使用上述hexchar_to_int()函数,这就是我实现它的方式(没有错误检查):

  const char *t = "0x12ab";
  int i = 0, n = 0;
  int result = 0;
  for (i = 2; i < strlen(t); i++) {
   n = hexchar_to_int(t[i]);

   result |= n; 
   result <<= 4;
  } 

  /* undo the last shift */
  result >>= 4;
于 2012-10-22T08:34:30.097 回答
1

不要使用 C++ 编译器来编译 C 程序。这是我给你的第一个建议。

其次const,在 a 的函数参数中char *确保程序员不会意外修改字符串。

第三,您需要包含上述数学库-lm

于 2012-10-22T08:43:37.290 回答
1

如果我不在 htoi(s) 的参数中使用 const,我会从 g++ 编译器收到以下警告

const 参数应该在那里,因为它被认为是好的和正确的编程,永远不会从指针中类型转换掉 const。字符串文字 "..." 应该被视为常量,因此如果您没有 const 作为参数,编译器会认为您正在丢弃 const 限定符。

此外,您应该将不打算修改其内容的所有指针参数声明为 const,Google 术语const correctness

为什么我的程序需要这么长时间才能运行?我还没有看到结果。

我认为主要是因为您进行了初始化操作。int i;我包含垃圾。然后while (s[rubbish_value] != '\0')。这个函数也可以写得更好。首先检查字符串开头的 0x,如果它们不存在,则发出错误信号(返回 NULL?),否则丢弃它们。然后开始一个循环,你不需要2个循环。

请注意 pow() 函数处理浮点数,这将使您的程序稍微慢一点。您可以考虑使用仅整数版本。不幸的是,标准 C 中没有这样的函数,所以你必须在别处找到一个。

还要考虑函数 isxdigit(),它是 ctype.h 中的标准函数,它检查数字 0-9 以及十六进制字母 AF 或 af。但是,它可能对性能没有帮助,因为您需要对数字和字母执行不同的计算。

对于它的价值,这里有一个片段展示了如何将单个 char 转换为十六进制 int。它可能不是最优化的版本,但它利用了可用的标准功能,以提高可读性和可移植性:

#include <ctype.h>

uint8_t hexchar_to_int (char ch)
{
  uint8_t result;

  if(isdigit(ch))
  {
    result = ch - '0';
  }
  else if (isxdigit(ch))
  {
    result = toupper(ch) - 'A' + 0xA;
  }
  else
  {
    // error
  }

  return result;
}
于 2012-10-22T09:01:47.493 回答
1

我自己刚刚完成了这个练习,我认为其中一个主要想法是利用字符可以作为整数进行比较的知识(他们在第 2 章中谈到了这一点)。

这是我的功能供参考。认为这可能很有用,因为这本书不包含练习的答案。

int htoi(char s[]) {
    int i = 0;
    if(s[i] == '0') {
        ++i;
        if(s[i] == 'x' || s[i] == 'X') {
          ++i;
        }
    }

    int val = 0;

    while (s[i] != '\0') {
        val = 16 * val;
        if (s[i] >= '0' && s[i] <= '9')
            val += (s[i] - '0');
        else if (s[i] >= 'A' && s[i] <= 'F') 
            val += (s[i] - 'A') + 10;
        else if (s[i] >= 'a' && s[i] <= 'f')
            val += (s[i] - 'a') + 10;
        else {
            printf("Error: number supplied not valid hexadecimal.\n");
            return -1;
        }           
        ++i;
    }

    return val;
}
于 2012-12-23T00:08:24.027 回答
0

始终初始化您的变量int i=0,否则i将包含垃圾值,可以是任何数字,而不是您期望的 0。您在无限循环中运行 while 语句,这就是为什么要花很长时间才能得到结果,打印 i 看看为什么。此外,如果字符串不以 0x 开头,则添加一个中断,将避免在用户使用随机字符串时出现相同的循环问题。正如其他人提到的,您需要导入包含pow函数的库并声明您的字符串const以消除警告。

于 2012-10-22T08:56:43.487 回答
0

这是我针对上述问题的程序版本。它将十六进制字符串转换为十进制数字,而不考虑可选前缀(0x 或 0X)。使用的 4 个重要的库函数是 strlen(s)、isdigit(c)、isupper(c)、isxdigit(c)、pow(m,n)

欢迎提出改进代码的建议:)

/*Program  - 5d Function that converts hex(s)into dec -*/
#include<stdio.h>
#include<stdlib.h>
#include<math.h>                //Declares mathematical functions and macros
#include<string.h>              //Refer appendix in Page 249 (very useful)
#define HEX_LIMIT 10

int hex_to_dec(char hex[])      //Function created by me :)
{
   int dec = 0;                //Initialization of decimal value
   int size = strlen(hex);     //To find the size of hex array
   int temp = size-1 ;         //Pointer pointing the right element in array
   int loop_limit = 0;         //To exclude '0x' or 'OX' prefix in input

   if(hex[0]=='0' && ((hex[1]=='x')  || (hex[1]=='X')))
   loop_limit = 2;

   while(temp>=loop_limit)
   {
     int hex_value = 0;        //Temporary value to hold the equivalent hex digit in decimal

     if(isdigit(hex[temp]))
       hex_value = (hex[(temp)]-'0') ;
     else if(isxdigit(hex[temp]))
        hex_value =  (toupper(hex[temp])-'A' + 10);
     else{
        printf("Error: No supplied is not a valid hex\n\n");
        return -1;
      }

    dec += hex_value * pow(16,(size-temp-1));        //Computes equivalent dec from hex
    temp--;                    //Moves the pointer to the left of the array
   }
   return dec;
}

int main()
{
char hex[HEX_LIMIT];
printf("Enter the hex no you want to convert: ");
scanf("%s",hex);
printf("Converted no in decimal: %d\n", hex_to_dec(hex));

return 0;
}
于 2015-05-25T00:57:18.230 回答