我正在尝试用C编写一个程序,将十六进制数转换为整数。我已经成功编写了一个将八进制转换为整数的程序。但是,一旦我开始使用字母(a-f),问题就开始了。我对该计划的想法是以下广告:
参数必须是以0x或0X开头的字符串。
参数十六进制数存储在字符串s []中。
整数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 *'[ - WRrite-strings] 2-3.c:97:22:警告:不推荐将字符串常量转换为 'char *'[-Wwrite-strings] 2-3.c:101:21:警告:弃用转换 从字符串常量到'char *'[-Wwrite-strings] 2-3.c:105:21: 警告:不推荐将字符串常量转换为'char *' [-Wwrite串]
为什么会这样?
2.为什么我的程序需要花费这么多时间才能运行?我还没有看到结果。
3.为什么当我在终端输入cc 2-3.c而不是g ++ 2-3.c时,我收到以下错误消息:
在我使用过电源功能的每一行上“对'pow'的未定义引用”
?
4。请指出我的计划中的其他错误/潜在改进。
答案 0 :(得分:1)
const
char []表示您无法在函数中更改它。从const
投射到不投注const
会发出警告。关于const
还有很多话要说。查看其Wikipedia page。cc
没有链接正确的库。请尝试以下构建命令:cc 2-3.c -lm
改进:
pow()
,就处理时间而言,这是非常昂贵的。 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;
答案 1 :(得分:1)
不要使用C ++编译器来编译C程序。这是我给你的第一个建议。
其次const
的函数参数char *
确保程序员不会意外地修改字符串。
第三,您需要将数学库包含在-lm
中,如上所述。
答案 2 :(得分: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以及十六进制字母A-F或a-f。但是它可能对性能没有帮助,因为您需要对数字和字母执行不同的计算。
对于它的价值,这里有一个片段,显示如何将单个字符转换为十六进制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;
}
答案 3 :(得分: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;
}
答案 4 :(得分:0)
始终初始化变量int i=0
,否则i
将包含垃圾值,可以是任何数字,不需要0如您所料。你在无限循环中运行while语句,这就是为什么需要永远得到结果,打印我看到原因。此外,如果字符串不以0x开头,则添加中断,当用户在随机字符串上使用时,将避免相同的循环问题。正如其他人所说,您需要导入包含pow
函数的库,并使用const
声明您的字符串以消除警告。
答案 5 :(得分: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;
}