programing

16진수 문자열(char [])을 int로 변환하시겠습니까?

prostudy 2022. 5. 15. 23:43
반응형

16진수 문자열(char [])을 int로 변환하시겠습니까?

"0x1800785"와 같은 값을 포함하는 char[]가 있지만 값을 부여하고자 하는 함수는 int가 필요한데, 어떻게 이것을 int로 변환할 수 있을까?여기저기 찾아봤지만 답을 찾을 수가 없다.고마워요.

해봤어?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과 같은 명시적 근거는 명시하는 것도 가능하지만, 중복 도입은 권하지 않겠다.)

또는 독자적으로 구현하고 싶은 경우, 이 빠른 기능을 예로 다음과 같이 적었다.

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

이와 같은 것이 유용할 수 있다.

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

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

Read Man sscanf

사용하다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를 추가한다.

한 가지 빠르고 더러운 솔루션:

// 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 표의 알파벳 문자 위치에 따라 결정되는데, 예를 들어 위키백과(https://en.wikipedia.org/wiki/ASCII#/media/File:US ASCII_code_chart.png)를 엿보자.긴 줄거리를 줄여서 숫자가 문자보다 적기 때문에 숫자(0~9)는 코드 0을 빼면 쉽게 변환된다.알파벳 문자(A~F)는 마지막 3비트를 제외한 나머지 3비트를 0으로 설정(대소문자 중 하나에서 효과적으로 작동하도록 함), 1비트를 빼서(비트 마스킹 후 알파벳이 위치 1에서 시작되기 때문에), 10을 더하면 읽힌다(A~F는 16진수 코드로 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;
}

끈이라는 뜻이라면 스트롤은 어떠세요?

나도 비슷한 일을 했어. 그게 날 위해 일하는 데 도움이 될 것 같아.

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자의 문자열만을 취했을 뿐이다. 만약 당신이 그들의 동등한 16진수 값을 주기 위해 'a'와 'f'에 유사한 논리를 추가할 수 있기를 원한다면, 나는 그것이 필요하지 않았기 때문에 그것을 하지 않았다.

이것은 문자 배열을 포함하는 16진수를 추가 라이브러리가 필요 없는 정수로 직접 변환하는 기능이다.

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

그래서 한동안 찾아보다가 스트롤이 꽤 느리다는 것을 알게 된 후, 나는 내 자신의 기능을 암호로 만들었다.대문자만 사용할 수 있지만 소문자 기능을 추가하는 것은 문제가 되지 않는다.

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);

우리가 변환하고자 하는 16진수는 오프셋 1, 8에서 시작하기 때문에 16진수 길이 입니다.

속도 테스트(1.000.000 통화):

strtol ~ 0.4400s
hexToInt ~ 0.1100s

코드 블록 아래를 써봐, 나한테 효과가 있어.

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

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

출력:

value x: 820 - 2080

이게 정말 오래됐다는 건 알지만 해결책이 너무 복잡해 보였어.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 

헥사데시멀/십진법 변환을 위해 를 만들었다.stdio.h사용하기 매우 간단함:

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

첫 번째 변환 전에 변환에 사용되는 어레이를 초기화하십시오.

void init_hexdec ();

여기 github에 대한 링크: https://github.com/kevmuret/libhex/

나는 @radhoo 솔루션을 좋아하는데, 작은 시스템에서는 매우 효율적이다.16진수를 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;
    }

val이 넘치지 않도록 uint32_t인 동안 반환 값은 int32_t이다.

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

잘못된 형식의 문자열로부터 보호되지 않음.

여기 "사이람 싱"의 해결책이 있다.그 답이 1:1 해결책인 경우, 이 답은 두 개의 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
}

참조URL: https://stackoverflow.com/questions/10156409/convert-hex-string-char-to-int

반응형