将十六进制字符串(char [])转换为int?

kiz*_*502 74 c int char

我有一个char []包含一个值,如"0x1800785",但我想要赋值的函数需要一个int,我怎么能把它转换成一个int?我搜索过但找不到答案.谢谢.

小智 189

你试过strtol()吗?

strtol - 将字符串转换为长整数

例:

const char *hexstring = "abcdef0";
int number = (int)strtol(hexstring, NULL, 16);
Run Code Online (Sandbox Code Playgroud)

如果数字的字符串表示以0x前缀开头,则必须使用0作为基数:

const char *hexstring = "0xabcdef0";
int number = (int)strtol(hexstring, NULL, 0);
Run Code Online (Sandbox Code Playgroud)

(也可以指定一个明确的基础,如16,但我不建议引入冗余.)

  • @KelvinHu**不要相信cplusplus.com,这是废话.**如果有的话,请访问http://cppreference.com. (14认同)
  • 如果hexstring总是由问题中给出的"0x"引入,那么你应该使用`0`而不是`16`. (4认同)
  • 作为旁注,`strtol`给你输入`long`,这在处理非常大的十六进制时非常棒.对于更大的六角形,使用`strtoll`表示`long long`. (3认同)
  • 注意到“以 0x 前缀开头,必须使用 0 作为基数”和 C11 §7.22.1.4“如果基数为 16,则字符 0x 或 0X 可以选择在字母和数字序列之前”之间存在令人惊讶的差异,如下所示在 `printf("%ld\n", strtol("0x12", 0, 16));` 中。您可能希望回顾一下这一点。 (2认同)

sax*_*axi 19

这样的东西可能有用:

char str[] = "0x1800785";
int num;

sscanf(str, "%x", &num);
printf("0x%x %i\n", num, num); 
Run Code Online (Sandbox Code Playgroud)

阅读man sscanf

  • 这会导致未定义的行为,“%x”必须接收“unsigned int”的地址。即使你修复了这个问题,如果字符串表示的数字大于“UINT_MAX”,那么它又是未定义的行为 (2认同)

rad*_*hoo 14

或者如果你想拥有自己的实现,我写这个快速函数作为一个例子:

/**
 * hex2int
 * take a hex string and convert it to a 32bit number (max 8 hex digits)
 */
uint32_t hex2int(char *hex) {
    uint32_t val = 0;
    while (*hex) {
        // get current character then increment
        uint8_t byte = *hex++; 
        // transform hex character to the 4bit equivalent number, using the ascii table indexes
        if (byte >= '0' && byte <= '9') byte = byte - '0';
        else if (byte >= 'a' && byte <='f') byte = byte - 'a' + 10;
        else if (byte >= 'A' && byte <='F') byte = byte - 'A' + 10;    
        // shift 4 to make space for new digit, and add the 4 bits of the new digit 
        val = (val << 4) | (byte & 0xF);
    }
    return val;
}
Run Code Online (Sandbox Code Playgroud)

  • 对于微控制器等资源有限的平台非常有用。 (2认同)

Jam*_*lin 10

假设你的意思是它是一个字符串,strtol怎么样?

  • @JamesMcLaughlin它可以.64位IEEE双精度具有大约2 ^ 53的积分精度. (4认同)

Lim*_*Red 9

strtol如果您像最佳答案所建议的那样有可用的 libc,请使用。但是,如果您喜欢定制的东西或者使用没有 libc 左右的微控制器,您可能需要一个没有复杂分支的稍微优化的版本。

#include <inttypes.h>


/**
 * xtou64
 * Take a hex string and convert it to a 64bit number (max 16 hex digits).
 * The string must only contain digits and valid hex characters.
 */
uint64_t xtou64(const char *str)
{
    uint64_t res = 0;
    char c;

    while ((c = *str++)) {
        char v = (c & 0xF) + (c >> 6) | ((c >> 3) & 0x8);
        res = (res << 4) | (uint64_t) v;
    }

    return res;
} 
Run Code Online (Sandbox Code Playgroud)

位移魔法归结为:只使用最后 4 位,但如果它是非数字,则还要加上 9。


Sim*_*mon 6

一种快速而肮脏的解决方案:

// makes a number from two ascii hexa characters
int ahex2int(char a, char b){

    a = (a <= '9') ? a - '0' : (a & 0x7) + 9;
    b = (b <= '9') ? b - '0' : (b & 0x7) + 9;

    return (a << 4) + b;
}
Run Code Online (Sandbox Code Playgroud)

你必须确保你的输入是正确的,不包括任何验证(可以说它是 C)。好在它非常紧凑,它适用于“A”到“F”和“a”到“f”。

该方法依赖于 ASCII 表中字母字符的位置,例如让我们查看 Wikipedia ( https://en.wikipedia.org/wiki/ASCII#/media/File:USASCII_code_chart.png )。长话短说,数字位于字符下方,因此数字字符(0 到 9)可以通过减去零代码轻松转换。字母字符(A 到 F)的读取方法是,将最后三位以外的其他位清零(有效地使其适用于大写或小写),减一(因为在位屏蔽之后,字母表从位置一开始)并加十(因为A到F代表十六进制代码中的第10到15个值)。最后,我们需要组合形成编码数字的低半字节和高半字节的两个数字。

这里我们采用相同的方法(有细微的变化):

#include <stdio.h>

// takes a null-terminated string of hexa characters and tries to 
// convert it to numbers
long ahex2num(unsigned char *in){

    unsigned char *pin = in; // lets use pointer to loop through the string
    long out = 0;  // here we accumulate the result

    while(*pin != 0){
        out <<= 4; // we have one more input character, so 
                   // we shift the accumulated interim-result one order up
        out +=  (*pin < 'A') ? *pin & 0xF : (*pin & 0x7) + 9; // add the new nibble
        pin++; // go ahead
    }

    return out;
}

// main function will test our conversion fn
int main(void) {

    unsigned char str[] = "1800785";  // no 0x prefix, please
    long num;

    num = ahex2num(str);  // call the function

    printf("Input: %s\n",str);  // print input string
    printf("Output: %x\n",num);  // print the converted number back as hexa
    printf("Check: %ld = %ld \n",num,0x1800785);  // check the numeric values matches

    return 0;
}
Run Code Online (Sandbox Code Playgroud)