十六进制到十进制转换 [K&R 练习]

发布于 2024-07-18 09:22:26 字数 516 浏览 7 评论 0原文

我正在学习 C,但我无法弄清楚 K&R 练习之一,即列表:

练习2-3,编写函数 htoi(s),将字符串转换为 十六进制数字(包括 可选的 0x0X) 转换为等效的 整数值。 允许的数字 分别是 09afA 通过F

我想我需要在这里做一些递归,我只是想我对编号类型及其各种转换方法等了解不多。

有人可以给我一些关于如何最好地理解它的指示吗?不是寻找有人握住我的手,而是引导我找到一种正确理解的方法,以便我可以尽可能以最优雅的形式编写它,而不是使用 printf("%x", Skill);printf("%x", Skill);代码>

I'm learning C and I can't figure out one of the K&R exercises, the listing:

Exercise 2-3, Write the 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.

I suppose I need to do some recursion here, I just guess that I don't know a lot about the numbering types, and their various conversion methodologies, etc.

Could someone give me some pointers on how best to understand it, I'm not looking for someone to hold my hand, but instead direct me to a means of proper understanding so I can write this in the most elegant form as possible, and not with printf("%x", skill);

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

双马尾 2024-07-25 09:22:27

米奇的基本想法是正确的,但让我们更详细地了解一下。

十六进制数字以 16 为基数,这意味着数字(从右到左)的值为

数字 × 160(即 1)
数字 × 161(即 16)
数字 × 162 (256)

等等。 例如,0xE 是 14。

您需要的是一个从字符串右端开始的循环。 假设字符串是 s,length(s) 是字符串的长度。 在伪代码中,您希望

value = 0
r = 1   // ask yourself "what values does r take as this proceeds?"
for i from length(s)-1 to 0   // Ask yourself "why length(s)-1?"
   value = value + (digitval(s[i])*r)
   // get ready for the next digit
   r = r * 16

digitval(char c) 需要是一个将“0123456789ABCDEF”中的 checract 转换为 0 到 15(含)之间的值的函数。我将其作为练习,有一个提示:“数组”。

小心一额外问题; 因为您可能有一个前导“0”或“0x”,所以您需要确保处理这些情况。

Mitch has the basic idea right, but let's take it in a little more detail.

A hex number is just base 16, which means the digits (from right to left) have the values as

digit × 160 (ie, 1)
digit × 161 (ie, 16)
digit × 162 (256)

and so on. So, 0xE is 14, for example.

What you'll want is a loop starting at the right end of the string. Let's say the string is s, length(s) is the length of the string. In pseudocode, you want

value = 0
r = 1   // ask yourself "what values does r take as this proceeds?"
for i from length(s)-1 to 0   // Ask yourself "why length(s)-1?"
   value = value + (digitval(s[i])*r)
   // get ready for the next digit
   r = r * 16

digitval(char c) needs to be a function that translates a checract in "0123456789ABCDEF" into the values between 0 and 15 (inclusive.) I'll leave that as an exercise, with one hint: "arrays".

be careful with one extra issue; since you could have a leading "0" or "0x" you need to make sure you handle those cases.

简单气质女生网名 2024-07-25 09:22:27

对于那些熟悉数学的人来说,从左到右处理字符串更简单,而且可以说更易读。 该策略是意识到,例如,1234 = (((1 x 10) + 2) x 10 + 3) x 10 + 4

换句话说,当您从左到右处理每个数字时,将先前的总数乘以基数,有效地将其“向左移动”一位,然后添加新的数字。

long decFromHexStr(const char *hexStr)
{
    int i;
    long decResult = 0;  // Decimal result

    for (i=0;  i < strlen(hexStr);  ++i)
    {
        decResult = 16 * decResult + decFromHexChar(hexStr[i]);
    }
    return decResult;
}

有经验的程序员可能会使用指针来单步执行字符串,而不是将其视为数组:

long decFromHexStr(const char *pHex)
{
    long decResult = 0;

    while (*pHex != '\0')
    {
        decResult = 16 * decResult + decFromHexChar(*pHex++);
    }
    return decResult;
}

既然您正在学习,那么值得研究编码风格并确定它是否有帮助,因此您会尽早养成良好的习惯。

玩得开心!

Processing the string from left to right is simpler and arguably more readable for those comfortable with math. The strategy is realizing that, for example, 1234 = (((1 x 10) + 2) x 10 + 3) x 10 + 4

In other words, as you process each digit from left to right, multiply the previous total by the base, effectively "moving it left" one position, then add the new digit.

long decFromHexStr(const char *hexStr)
{
    int i;
    long decResult = 0;  // Decimal result

    for (i=0;  i < strlen(hexStr);  ++i)
    {
        decResult = 16 * decResult + decFromHexChar(hexStr[i]);
    }
    return decResult;
}

Experienced programmers would probably use a pointer to step through the string instead of treating it as an array:

long decFromHexStr(const char *pHex)
{
    long decResult = 0;

    while (*pHex != '\0')
    {
        decResult = 16 * decResult + decFromHexChar(*pHex++);
    }
    return decResult;
}

Since you're learning, it's worth studying the coding style and deciding whether you find it helpful or not, so you'll build good habits early.

Have fun!

大海や 2024-07-25 09:22:27

十六进制数的实际含义是什么? 我们以15FA为例。 这意味着请

1 * 16^3 + 5 * 16^2 + 15 * 16^1 + 10 * 16^0

注意,A 代表十,B 代表十一个,依此类推,直到 F 代表十五。 而且16^0等于1。

所以我们需要做的就是计算上面表达式的值! 最简单的方法可能是按以下顺序执行:

10 * 1
15 * 16
5  * 256   //256  = 16 * 16
1  * 4096  //4096 = 16 * 16 * 16

如果有更多数字,可以进一步继续。 您真正需要的只是一个循环和几个变量。

还有另一种方法可以通过分解上面的表达式来解释,如下所示:

((1 * 16 + 5) * 16 + 15) * 16 + 10

如果您愿意,请尝试每种方法。

更多高级信息:

基本上,计算机使用基数 2(也称为二进制)进行所有数字和计算。 甚至字符串“1A6DC0”也用 1 和 0 进行编码,最终以字母和数字的形式显示在屏幕上。

有时您可以利用计算机使用二进制的事实,但通常您不需要考虑它。

例如,当您这样做时,

x = (11 + y) * 6;

无需担心 11 和 6 在某个阶段会被表示为一系列高电压和低电压。 它就像你期望的那样工作。 在十进制(我们使用的数字系统)与二进制之间进行转换是计算机可以轻松完成的一个简单过程,因此它们会自动为我们执行此操作,以使我们的工作更轻松。

然而,在十六进制和二进制之间转换时,有一个快捷方式。 由于四个二进制数字与一个十六进制数字相同,因此您可以简单地将每个十六进制数字单独转换为二进制,然后将它们串在一起。

例如,15FA 将像这样扩展:

1 -> 0001
5 -> 0101
F -> 1111
A -> 1010
15FA -> 0001 0101 1111 1010

请注意,这通常不能直接完成,并且通常涉及逻辑或和位移位(|< ;<)。 好玩的东西。

What does a hexadecimal number actually mean? Let's take 15FA. It means

1 * 16^3 + 5 * 16^2 + 15 * 16^1 + 10 * 16^0

Note that A represents ten, B eleven and so on up to F which represents fifteen. Also 16^0 is equal to 1.

So all we need to do is calculate the value of the above expression! The simplest way is probably to do it in this order:

10 * 1
15 * 16
5  * 256   //256  = 16 * 16
1  * 4096  //4096 = 16 * 16 * 16

This can continue further if there are more digits. All you really need is a loop and few variables.

There is another method of doing it which is explained by factorising the above expression like this:

((1 * 16 + 5) * 16 + 15) * 16 + 10

If you wish, try each of these methods.

More advanced information:

Basically, computers use base 2 (also called binary) for all their numbers and calculations. Even the string "1A6DC0" is encoded with 1s and 0s, which eventually get displayed on the screen as letters and numbers.

Sometimes you can take advantage of the fact that computers use binary, but usually you don't need to think about it.

For instance, when you do

x = (11 + y) * 6;

you don't need to worry that 11 and 6 will be represented as a series of high and low voltages at some stage. It just works as you expect. Converting between decimal (the number system we use) to binary and back is a simple process that computers can do easily, and so they do this for us automatically to make our work easier.

However, when converting between hexadecimal and binary, there is a shortcut. Since four binary digits are identical to a single hex digit, you can simply convert each hex digit to binary individually, then string them together.

For instance, 15FA would expand like this:

1 -> 0001
5 -> 0101
F -> 1111
A -> 1010
15FA -> 0001 0101 1111 1010

Note that this generally can't be done directly, and usually involves logical-or and bit shifts (| and <<). Fun stuff.

稀香 2024-07-25 09:22:27

我可能没有做出很大的贡献,上面有很好的答案。 但我会尝试一下。

正如其他人在我之前所做的那样,我留下了一些功能供您实现。

int htoi(const char* x)
{

        unsigned int current_position;/*current position is to be defined*/
        int prefixed=0;                                                         
        int dec=0;
        char* y = x;

        if (x && x+1 && (*(x+1)=='x' || *(x+1)=='X')){  /*Is 0x or 0X prefix present?*/
                prefixed= PREFIXED;             
        }

        if (prefixed) y+=2; /*Jumps over 0x or 0X*/     


        while (*y){
                /*getPos(const char*) and singleHexToDec(const char*,unsigned int) functions to be implemented*/
                current_position=getPos(y);
                dec+=singleHexToDec(y,current_position); 
        }
        return dec;
}

I'm probably not making a great contribution, there are good answers above. But I'll give it a try.

As others did before me, I'm leaving some functionality for you to implement.

int htoi(const char* x)
{

        unsigned int current_position;/*current position is to be defined*/
        int prefixed=0;                                                         
        int dec=0;
        char* y = x;

        if (x && x+1 && (*(x+1)=='x' || *(x+1)=='X')){  /*Is 0x or 0X prefix present?*/
                prefixed= PREFIXED;             
        }

        if (prefixed) y+=2; /*Jumps over 0x or 0X*/     


        while (*y){
                /*getPos(const char*) and singleHexToDec(const char*,unsigned int) functions to be implemented*/
                current_position=getPos(y);
                dec+=singleHexToDec(y,current_position); 
        }
        return dec;
}
z祗昰~ 2024-07-25 09:22:27

尝试用我粗鲁的英语解释:(

我的代码(假设所有输入都是正确的。避免防御性编程)

#include <stdio.h>


enum { SZ = 11 };

unsigned int htoi(const char *s);


int main()
{

  char buff[SZ];  //Max 11 char: 0x XX XX XX XX '\0' (2 + 8 + 1)

  while(fscanf(stdin, "%s", buff) != EOF)
    printf("%X\n", htoi(buff) ); 

  return 0;
}


unsigned int htoi(const char *s)
{
  unsigned int i, r = 0;

  for(i = (s[1] == 'x') ? 2 : 0; s[i] != '\0'; i++)
    r = ( r << 4 ) +  ( (s[i] > '9') ? 0x9 : 0x0 ) + ( s[i] & 0xF );

  return r;
}

好的,首先,分配r = 0。
然后,当我们启动 for-bucle 时,我们为索引变量 i 赋予一个初始值。 我们必须检查字符串是否具有 0x 格式。 我们只需要检查位置 1 即可知道我们是否正在处理具有 0x 格式的输入字符串或不具有 0x 格式的输入字符串。

现在,我们有一个指向第一个正确字符的索引! 对于每次迭代,我们向左移动 4 位。 我们得到了 4 个零。 添加新的十六进制数字的完美间隙! 示例:

Input: 0xBE1234

Is s[1] == 'x' ? true then i = 2;
r = 0;

iter 1: r = 0x0; r = 0x0; r = 0xB;
iter 2: r = 0xB; r = 0xB0; r = 0xBE;
iter 3: r = 0xBE; r = 0xBE0; r = 0xBE1;
iter 4: r = 0xBE1; r = 0xBE10; r = 0xBE12;
iter 5: r = 0xBE12; r = 0xBE120; r = 0xBE123;
iter 6: r = 0xBE123; r = 0xBE1230; r = 0xBE1234

这可能有点复杂:

 r = ( r << 4 ) + ( (s[i] > '9') ? 0x9 : 0x0 ) + ( s[i] & 0xF );

首先,我们替换 4 位,与每 16 乘法相同,但效率更高。 然后,我们查看是否有大于“9”的 ASCII 字符。 如果这是真的,我们正在使用 A、B、C、D、E、F 或 a、b、c、d、e、f。 请记住,我们假设我们有正确的输入。
好的,现在看一下 ASCII 表:

A = 0100 0001  -  a = 0110 0001
...
F = 0100 0110  -  f = 0110 0110

但是我们想要这样的东西:

A = 0000 1010  -  a = 0000 1010
...
F = 0000 1111  -  f = 0000 1111

我们如何做到这一点? 移位后,我们用掩码 s[i] & 清除 4 个最高有效位。 0xF:

s[2] == 'B' == 0100 0010
s[2] & 0xF == 0000 0010

并添加 9 以适应整数值(仅当 s[i] in { 'A'...'F', 'a' ... 'f' } 时)

s[2] & 0xF + 0x9 = 0000 0010 + 0000 1001 = 0000 1011 (0xB)

最后,我们添加到位移后的 r值并分配给 r。 第二次迭代 (s[3]) 的执行顺序:

r == 0xB, s[3] == 'E' == 0100 0101 (start iter 2)
(r << 4) == 0xB0, s[3] == 'E' == 0100 0101 (displacement r << 4 )
(r << 4) == 0xB0, (s[3] & 0xF + 0x9) == 0000 1110 == 0xE (clear most significant bits of s[3] and add 0x9)
r = (r << 4) + ( s[3] & 0xF + 0x9 ) == 0xBE == 1011 1110 (add all and assign to r)

如果我们有像 s[4] 这样的数字字符,会发生什么?

s[4] == '1' == 0011 0001
s[4] & 0xF == 0000 0001

位移 r 四个位置,加 0(无),将逻辑运算结果 s[i] & 相加; 0xF,最后分配给r。

r == 0xBE, s[4] == '1' == 0011 0001 (start iter 3)
(r << 4) == 0xBE0, s[4] == '1' == 0011 0001 (displacement r << 4 )
(r << 4) == 0xBE0, (s[4] & 0xF + 0x0) == 0000 0001 (clear most significant bits of s[4] and add 0)
r = (r << 4) + s[4] & 0xF == 0xBE1 == 1011 1110 0001 (add all and assign)

请记住,我们移位 4,这样我们就不会网格数字位,因为我们添加了具有四个零间隙的较低有效位。

PD:我保证提高我的英语水平以便更好地解释,抱歉。

try to explain with my rude english :(

My code (assume that all inputs are corrects. Avoid defensive programing)

#include <stdio.h>


enum { SZ = 11 };

unsigned int htoi(const char *s);


int main()
{

  char buff[SZ];  //Max 11 char: 0x XX XX XX XX '\0' (2 + 8 + 1)

  while(fscanf(stdin, "%s", buff) != EOF)
    printf("%X\n", htoi(buff) ); 

  return 0;
}


unsigned int htoi(const char *s)
{
  unsigned int i, r = 0;

  for(i = (s[1] == 'x') ? 2 : 0; s[i] != '\0'; i++)
    r = ( r << 4 ) +  ( (s[i] > '9') ? 0x9 : 0x0 ) + ( s[i] & 0xF );

  return r;
}

Ok, first of all, assign r = 0.
Then, when we start for-bucle, we give an init value to index variable i. We have to check if string has 0x format or not. We only need to check position 1 to know if we are treating an input string with 0x format or without it.

Now, we have an index pointing to first correct character! For each iteraion we displace 4 bits to the left. We gain 4 zeros. A perfect gap to add a new hex digit! Example:

Input: 0xBE1234

Is s[1] == 'x' ? true then i = 2;
r = 0;

iter 1: r = 0x0; r = 0x0; r = 0xB;
iter 2: r = 0xB; r = 0xB0; r = 0xBE;
iter 3: r = 0xBE; r = 0xBE0; r = 0xBE1;
iter 4: r = 0xBE1; r = 0xBE10; r = 0xBE12;
iter 5: r = 0xBE12; r = 0xBE120; r = 0xBE123;
iter 6: r = 0xBE123; r = 0xBE1230; r = 0xBE1234

May be this is a bit complicate:

 r = ( r << 4 ) + ( (s[i] > '9') ? 0x9 : 0x0 ) + ( s[i] & 0xF );

First of all, we displace 4 bits, same as multiplication per 16 but more efficient. Then, we look if we have an ASCII character bigger than '9'. If it's true, we are working with A, B, C, D, E, F or a, b, c, d, e, f. Remember, we assume that we have a correct input.
Ok, now take a look to ASCII table:

A = 0100 0001  -  a = 0110 0001
...
F = 0100 0110  -  f = 0110 0110

but we want something like this:

A = 0000 1010  -  a = 0000 1010
...
F = 0000 1111  -  f = 0000 1111

How we do it? After displacement, we clear 4 most significant bit with mask s[i] & 0xF:

s[2] == 'B' == 0100 0010
s[2] & 0xF == 0000 0010

and add 9 for adapt to an integer value ( only in case that s[i] in { 'A'...'F', 'a' ... 'f' } )

s[2] & 0xF + 0x9 = 0000 0010 + 0000 1001 = 0000 1011 (0xB)

Finally, we add to displaced r value and assign to r. Execution sequence for second iteration (s[3]):

r == 0xB, s[3] == 'E' == 0100 0101 (start iter 2)
(r << 4) == 0xB0, s[3] == 'E' == 0100 0101 (displacement r << 4 )
(r << 4) == 0xB0, (s[3] & 0xF + 0x9) == 0000 1110 == 0xE (clear most significant bits of s[3] and add 0x9)
r = (r << 4) + ( s[3] & 0xF + 0x9 ) == 0xBE == 1011 1110 (add all and assign to r)

What's happen if we have a number character like s[4]?

s[4] == '1' == 0011 0001
s[4] & 0xF == 0000 0001

Displacement r four positions, add 0 (nothing), add result of logic operation s[i] & 0xF and finally, assign to r.

r == 0xBE, s[4] == '1' == 0011 0001 (start iter 3)
(r << 4) == 0xBE0, s[4] == '1' == 0011 0001 (displacement r << 4 )
(r << 4) == 0xBE0, (s[4] & 0xF + 0x0) == 0000 0001 (clear most significant bits of s[4] and add 0)
r = (r << 4) + s[4] & 0xF == 0xBE1 == 1011 1110 0001 (add all and assign)

Remember, we shift 4 so we don't mesh digit bits because we are adding less significant bits with a gap of four zeros.

PD: I promise improve my english for explain better, sorry.

世态炎凉 2024-07-25 09:22:27

传统方法是从左到右转换。 累加器在开始时设置为零,并在将每个新数字的等效值添加到循环之前乘以 16。

对于需要带有可选前导 0x 的十六进制数字的 htoi() 函数,首先跳过这些字符(如果存在)。 直接检查 s[0] 和 s[1] 的值可能是最清晰的方法。

如果您知道数字采用 ASCII 格式,则可以使用 s[i] - '0's[i] - 'A' + 10 等表达式进行转换将第 i 位转换为其整数值。

为了保持理智,您可能想将整个东西折叠到一个箱子中。

编辑:*s更改为s[i],以便与从本练习的角度来看指针来自未来的观察结果保持一致。

请注意,还有几种其他方法可以将各个数字转换为值。 例如,您可以在所有数字的向量中查找它们(类似于 strchr("0123456789ABCDEF",s[i])),构建一个按字符代码索引的单个查找表,其值为每个位置的每个数字(int digitalvalue[256] 已适当初始化后的 digitvalue[s[i]]),使用 开关 (s[i] ) 语句,按照另一个答案中的建议,为每个可能的数字添加一个 case 标签,或者使用我上面建议的范围检查和算术。 需要考虑的是选择哪个以及为什么。 请注意,这可能不是一个明显的选择,如果 ASCII 不是您选择的字符集,则最佳答案可能会有所不同。

A conventional approach converts from left to right. An accumulator is set to zero at the beginning, and multiplied by 16 before adding the equivalent value of each new digit to the loop.

For an htoi() function that expects hexidecimal digits with an optional leading 0x, begin by skipping past those characters if present. Directly checking the values of s[0] and s[1] is probably the clearest approach there.

If you know the digits are in ASCII, then you can use expressions like s[i] - '0' and s[i] - 'A' + 10 to convert the i-th digit to its integer value.

You probably want to fold the whole thing to one case for sanity.

Edit: Changed *s to s[i] for consistency with the observation that pointers are from the future from the point of view of this exercise.

Note that there are several other ways to convert the individual digits to values. For example, you could look them up in a vector of all digits (something like strchr("0123456789ABCDEF",s[i])), build a single lookup table indexed by character code with the value of each digit at each position (digitvalue[s[i]] after int digitvalue[256] has been suitably initialized), use a switch (s[i]) statement with a case label for each possible digit as suggested in another answer, or use the range checks and arithmetic as I suggest above. Something to think about is which to choose, and why. Notice that it may not be an obvious choice, and the best answer may be different if ASCII is not your character set of choice.

懵少女 2024-07-25 09:22:27

昨天我写了一个这样的函数。 你可以在下面看到我的代码。

/* Converting a hex string to integer, assuming the heading 
   0x or 0X has already been removed and pch is not NULL */
int hex_str_to_int(const char* pch) {

    int value = 0;
    int digit = 0;

    for (; *pch; ++pch) {

        if (*pch >= '0' && *pch <= '9') {
            digit = (*pch - '0');
        } else if (*pch >= 'A' && *pch <= 'F') {
            digit = (*pch - 'A' + 10);
        } else if (*pch >= 'a' && *pch <= 'f') {
            digit = (*pch - 'a' + 10);
        } else {
            break;
        }

        // Check for integer overflow
        if ((value *= 16) < 0 || (value += digit) < 0) {
            return INT_MAX;
        }
    }

    return value;
}

这是测试代码:

int main(void) {

    printf("%d %d\n", hex_str_to_int("0"), 0x0);
    printf("%d %d\n", hex_str_to_int("A"), 0xA);
    printf("%d %d\n", hex_str_to_int("10"), 0x10);
    printf("%d %d\n", hex_str_to_int("A1"), 0xA1);
    printf("%d %d\n", hex_str_to_int("AB"), 0xAB);
    printf("%d %d\n", hex_str_to_int("100"), 0x100);
    printf("%d %d\n", hex_str_to_int("1A2"), 0x1A2);
    printf("%d %d\n", hex_str_to_int("10A"), 0x10A);
    printf("%d %d\n", hex_str_to_int("7FFFFFF"), 0x7FFFFFF);
    printf("%d %d\n", hex_str_to_int("7FFFFFF1"), 0x7FFFFFF1);
    printf("%d %d\n", hex_str_to_int("7FFFFFF2"), 0x7FFFFFF2);
    printf("%d %d\n", hex_str_to_int("7FFFFFFE"), 0x7FFFFFFE);
    printf("%d %d\n", hex_str_to_int("7FFFFFFF"), 0x7FFFFFFF);
    printf("%d %d\n", hex_str_to_int("80000000"), 0x7FFFFFFF + 1);
    printf("%d %d\n", hex_str_to_int("80000001"), 0x7FFFFFFF + 2);

    printf("%d %d\n", hex_str_to_int("10AX"), 0x10A);   
    printf("%d %d\n", hex_str_to_int("203!"), 0x203);

    return 0;
}

它输出以下值:

0 0
10 10
16 16
161 161
171 171
256 256
418 418
266 266
134217727 134217727
2147483633 2147483633
2147483634 2147483634
2147483646 2147483646
2147483647 2147483647
2147483647 -2147483648
2147483647 -2147483647
266 266
515 515

Yesterday I wrote a function like this. You can see my code below.

/* Converting a hex string to integer, assuming the heading 
   0x or 0X has already been removed and pch is not NULL */
int hex_str_to_int(const char* pch) {

    int value = 0;
    int digit = 0;

    for (; *pch; ++pch) {

        if (*pch >= '0' && *pch <= '9') {
            digit = (*pch - '0');
        } else if (*pch >= 'A' && *pch <= 'F') {
            digit = (*pch - 'A' + 10);
        } else if (*pch >= 'a' && *pch <= 'f') {
            digit = (*pch - 'a' + 10);
        } else {
            break;
        }

        // Check for integer overflow
        if ((value *= 16) < 0 || (value += digit) < 0) {
            return INT_MAX;
        }
    }

    return value;
}

Here is the testing code:

int main(void) {

    printf("%d %d\n", hex_str_to_int("0"), 0x0);
    printf("%d %d\n", hex_str_to_int("A"), 0xA);
    printf("%d %d\n", hex_str_to_int("10"), 0x10);
    printf("%d %d\n", hex_str_to_int("A1"), 0xA1);
    printf("%d %d\n", hex_str_to_int("AB"), 0xAB);
    printf("%d %d\n", hex_str_to_int("100"), 0x100);
    printf("%d %d\n", hex_str_to_int("1A2"), 0x1A2);
    printf("%d %d\n", hex_str_to_int("10A"), 0x10A);
    printf("%d %d\n", hex_str_to_int("7FFFFFF"), 0x7FFFFFF);
    printf("%d %d\n", hex_str_to_int("7FFFFFF1"), 0x7FFFFFF1);
    printf("%d %d\n", hex_str_to_int("7FFFFFF2"), 0x7FFFFFF2);
    printf("%d %d\n", hex_str_to_int("7FFFFFFE"), 0x7FFFFFFE);
    printf("%d %d\n", hex_str_to_int("7FFFFFFF"), 0x7FFFFFFF);
    printf("%d %d\n", hex_str_to_int("80000000"), 0x7FFFFFFF + 1);
    printf("%d %d\n", hex_str_to_int("80000001"), 0x7FFFFFFF + 2);

    printf("%d %d\n", hex_str_to_int("10AX"), 0x10A);   
    printf("%d %d\n", hex_str_to_int("203!"), 0x203);

    return 0;
}

It outputs the following values:

0 0
10 10
16 16
161 161
171 171
256 256
418 418
266 266
134217727 134217727
2147483633 2147483633
2147483634 2147483634
2147483646 2147483646
2147483647 2147483647
2147483647 -2147483648
2147483647 -2147483647
266 266
515 515
残月升风 2024-07-25 09:22:26

递归不是必需的。 您只需向后循环字符串(即从单位列开始),将单位数转换乘以它的基数位置乘数相加。 这是伪代码,不处理可选的 0x 前缀(并且不检查溢出的可能性):

long total = 0;
long multiplier = 1;
for (int i = string.length - 1; i >= 0 i--)
{
   digit = ConvertSingleHexDigittoInt(string[i]);
   total += digit * multiplier;
   multiplier *= 16;
}

我已将 ConvertSingleHexDigittoInt() 的简单实现留给了您:)

Recursion is not necessary. You simply need to loop backwards over the string (i.e. starting in the units column), summing the single digit conversion times it's radix position multiplier. This is pseudocode and does not handle the optional 0x prefix (and is not checking for possibility of overflow):

long total = 0;
long multiplier = 1;
for (int i = string.length - 1; i >= 0 i--)
{
   digit = ConvertSingleHexDigittoInt(string[i]);
   total += digit * multiplier;
   multiplier *= 16;
}

I've left the easy implementation of ConvertSingleHexDigittoInt() to you :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文