96

我有一个包含诸如“0x1800785”之类的值的char [],但是我想赋予该值的函数需要一个int,如何将其转换为int?我四处寻找,但找不到答案。谢谢。

4

14 回答 14

234

你试过strtol()吗?

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

例子:

const char *hexstring = "abcdef0";
int number = (int)strtol(hexstring, NULL, 16);

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

const char *hexstring = "0xabcdef0";
int number = (int)strtol(hexstring, NULL, 0);

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

于 2012-04-14T19:01:19.713 回答
26

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

/**
 * 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;
}
于 2016-08-20T10:19:07.040 回答
25

像这样的东西可能很有用:

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

sscanf(str, "%x", &num);
printf("0x%x %i\n", num, num); 

阅读man sscanf

于 2012-04-14T19:14:20.403 回答
11

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

于 2012-04-14T19:01:20.567 回答
10

如果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;
} 

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

于 2019-07-19T12:34:28.477 回答
3

试试下面的代码块,它对我有用。

char p[] = "0x820";
uint16_t intVal;
sscanf(p, "%x", &intVal);

printf("value x: %x - %d", intVal, intVal);

输出是:

value x: 820 - 2080
于 2014-09-05T08:41:57.997 回答
3

因此,经过一段时间的搜索,发现 strtol 非常慢,我编写了自己的函数。它仅适用于大写字母,但添加小写功能不是问题。

int hexToInt(PCHAR _hex, int offset = 0, int size = 6)
{
    int _result = 0;
    DWORD _resultPtr = reinterpret_cast<DWORD>(&_result);
    for(int i=0;i<size;i+=2)
    {
        int _multiplierFirstValue = 0, _addonSecondValue = 0;

        char _firstChar = _hex[offset + i];
        if(_firstChar >= 0x30 && _firstChar <= 0x39)
            _multiplierFirstValue = _firstChar - 0x30;
        else if(_firstChar >= 0x41 && _firstChar <= 0x46)
            _multiplierFirstValue = 10 + (_firstChar - 0x41);

        char _secndChar = _hex[offset + i + 1];
        if(_secndChar >= 0x30 && _secndChar <= 0x39)
            _addonSecondValue = _secndChar - 0x30;
        else if(_secndChar >= 0x41 && _secndChar <= 0x46)
            _addonSecondValue = 10 + (_secndChar - 0x41);

        *(BYTE *)(_resultPtr + (size / 2) - (i / 2) - 1) = (BYTE)(_multiplierFirstValue * 16 + _addonSecondValue);
    }
    return _result;
}

用法:

char *someHex = "#CCFF00FF";
int hexDevalue = hexToInt(someHex, 1, 8);

1 因为我们要转换的十六进制从偏移量 1 开始,而 8 因为它是十六进制长度。

速度测试(1.000.000 次调用):

strtol ~ 0.4400s
hexToInt ~ 0.1100s
于 2018-01-05T17:32:26.297 回答
3

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

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

您必须确保您的输入是正确的,不包括验证(可以说是 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;
}
于 2019-10-06T00:35:20.377 回答
1

这是一个直接将包含 char 数组的十六进制转换为不需要额外库的整数的函数:

int hexadecimal2int(char *hdec) {
    int finalval = 0;
    while (*hdec) {
        
        int onebyte = *hdec++; 
        
        if (onebyte >= '0' && onebyte <= '9'){onebyte = onebyte - '0';}
        else if (onebyte >= 'a' && onebyte <='f') {onebyte = onebyte - 'a' + 10;}
        else if (onebyte >= 'A' && onebyte <='F') {onebyte = onebyte - 'A' + 10;}  
        
        finalval = (finalval << 4) | (onebyte & 0xF);
    }
    finalval = finalval - 524288;
    return finalval;
}
于 2020-07-21T20:10:29.433 回答
1

我做了类似的事情,认为它可能会帮助你它实际上为我工作

int main(){
  int co[8];
  char ch[8];
  printf("please enter the string:");
  scanf("%s", ch);
  for (int i=0; i<=7; i++) {
     if ((ch[i]>='A') && (ch[i]<='F')) {
        co[i] = (unsigned int) ch[i]-'A'+10;
     } else if ((ch[i]>='0') && (ch[i]<='9')) {
        co[i] = (unsigned int) ch[i]-'0'+0;
  }
}

在这里,我只取了一个 8 个字符的字符串。如果你想要你可以为'a'添加类似的逻辑到'f'来给出它们等效的十六进制值,我没有这样做,因为我不需要它。

于 2016-07-02T05:14:07.413 回答
0

我做了一个库来进行十六进制/十进制转换,而不使用stdio.h. 使用非常简单:

unsigned hexdec (const char *hex, const int s_hex);

在第一次转换之前初始化用于转换的数组:

void init_hexdec ();

这里是 github 上的链接:https ://github.com/kevmuret/libhex/

于 2014-05-03T13:41:40.173 回答
0

这是基于“sairam singh”解决方案的解决方案。如果该答案是一对一的解决方案,则该解决方案将两个 ASCII 半字节组合成一个字节。

// Assumes input is null terminated string.
//
//    IN                       OUT
// --------------------   --------------------
//  Offset  Hex  ASCII         Offset Hex
//  0       0x31 1             0      0x13
//  1       0x33 3                    
//  2       0x61 A             1      0xA0
//  3       0x30 0                    
//  4       0x00 NULL          2      NULL

int convert_ascii_hex_to_hex2(char *szBufOut, char *szBufIn) {

    int i = 0;  // input buffer index
    int j = 0;  // output buffer index
    char a_byte;

    // Two hex digits are combined into one byte
    while (0 != szBufIn[i]) {

        // zero result
        szBufOut[j] = 0;

        // First hex digit
        if ((szBufIn[i]>='A') && (szBufIn[i]<='F')) {
            a_byte = (unsigned int) szBufIn[i]-'A'+10;
        } else if ((szBufIn[i]>='a') && (szBufIn[i]<='f')) {
            a_byte  = (unsigned int) szBufIn[i]-'a'+10;
        } else if ((szBufIn[i]>='0') && (szBufIn[i]<='9')) {
            a_byte  = (unsigned int) szBufIn[i]-'0';
        } else {
            return -1;  // error with first digit
        }
        szBufOut[j] = a_byte << 4;

        // second hex digit
        i++;
        if ((szBufIn[i]>='A') && (szBufIn[i]<='F')) {
            a_byte = (unsigned int) szBufIn[i]-'A'+10;
        } else if ((szBufIn[i]>='a') && (szBufIn[i]<='f')) {
            a_byte  = (unsigned int) szBufIn[i]-'a'+10;
        } else if ((szBufIn[i]>='0') && (szBufIn[i]<='9')) {
            a_byte  = (unsigned int) szBufIn[i]-'0';
        } else {
            return -2;  // error with second digit
        }
        szBufOut[j] |= a_byte;

        i++;
        j++;
    }
    szBufOut[j] = 0;
    return 0;  // normal exit
}

于 2021-09-10T13:38:24.947 回答
0

我喜欢@radhoo 解决方案,在小型系统上非常有效。可以修改将十六进制转换为 int32_t (因此,有符号值)的解决方案。

/**
* hex2int
* take a hex string and convert it to a 32bit number (max 8 hex digits)
*/
int32_t hex2int(char *hex) {
    uint32_t val = *hex > 56 ? 0xFFFFFFFF : 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;
    }

注意返回值是 int32_t 而 val 仍然是 uint32_t 不会溢出。

 uint32_t val = *hex > 56 ? 0xFFFFFFFF : 0;

不受格式错误的字符串的保护。

于 2021-08-17T12:52:27.403 回答
-7

我知道这真的很旧,但我认为解决方案看起来太复杂了。在 VB 中试试这个:

Public Function HexToInt(sHEX as String) as long
Dim iLen as Integer
Dim i as Integer 
Dim SumValue as Long 
Dim iVal as long
Dim AscVal as long

    iLen = Len(sHEX)
    For i = 1 to Len(sHEX)
      AscVal = Asc(UCase(Mid$(sHEX, i,  1)))
      If AscVal >= 48 And AscVal  <= 57 Then
        iVal  = AscVal - 48
      ElseIf AscVal >= 65 And AscVal <= 70 Then
        iVal = AscVal - 55
      End If 
      SumValue = SumValue + iVal * 16 ^ (iLen- i)
    Next i 
    HexToInt  = SumValue
End Function 
于 2018-06-21T14:53:19.367 回答