C에서 Hex를 Integer로 변환하는 방법은 소문자를 얻을 수 없습니다!

StackOverflow https://stackoverflow.com/questions/1416571

  •  06-07-2019
  •  | 
  •  

문제

안녕하세요 여러분, 잠깐만요. 16진수를 정수로 변환하는 작업을 수행하고 있지만 숫자를 소문자로 가져와야 합니다.내가 가진 것은 다음과 같습니다. A부터 F까지 대소문자를 구분하지 않는 방법에 대한 아이디어가 있습니까?

int htoi(char f[]) {
    int  z, n;
    n = 0;

    for (z = 0; f[z] >= '0' && f[z] <= 'F'; ++z) 
        if (f[z] >= 'A' && f[z] <= 'F')
            n = 10 + 16 * n + (f[z] - 'A');
        else
            n = 16 * n + (f[z] - '0');
}

아마도 작은 것일 수도 있지만 a-f와 A-F를 포함하고 싶습니다.당신의 도움을 주셔서 감사합니다!

도움이 되었습니까?

해결책

이 작업을 수행하기 위해이 작업을 수행하는 경우이 게시물을 무시하십시오. 이 기능을 사용하는 경우 16 진수 문자열을 int, 당신은 표준 라이브러리를 산책해야합니다. 표준 기능 strtol() 문자열을 a로 변환합니다 long, 이것은 캐스트 될 수 있습니다 int (또는 an unsigned int 그것에있는 동안). 세 번째 인수는 전환 할 기반입니다.이 경우 16 진수를 16 진수로 원할 것입니다. 또한 기본 0이 주어지면 문자열이 시작되면 16 진수를 가정합니다. 0x, 시작하면 10 월 0, 그렇지 않으면 소수점. 매우 유용한 기능입니다.


편집 : 방금 이것을 알아 차렸다. 그러나 우리가 여기있는 동안, 당신은 일반적으로 int 인덱스 어레이. C 표준은 호출 된 유형을 정의합니다 size_t, 배열 지수를 저장하도록 설계되었습니다. 그것은 일반적으로입니다 unsigned int 또는 unsigned long 또는 무언가이지만 사용할 수있는 배열 또는 포인터 오프셋을 저장하기에 충분히 큰 것으로 보장됩니다.

단지 사용하는 문제 int 이론적으로, 어쩌면 언젠가 누군가가 줄을 더 길게 통과 할 수 있습니다. INT_MAX, 그리고 당신의 int 오버플로, 아마도 감싸고 아마도 메모리를 읽기 시작합니다. 메모리가 부정적인 색인을 사용하고 있기 때문일 것입니다. 이것은 특히 이와 같은 기능에 대해서는 거의 가능하지 않습니다. int 당신이 반환하는 가치는 당신의 오랫동안 오버플로됩니다 int 카운터 오버 플로우이지만 ~이다 명심해야 할 중요한 것.

기술적으로 정확하기 위해서는 만 사용해야합니다 size_t 인덱스 어레이에 변수 유형 또는 최소한 사용 만 사용합니다. unsigned 유형, 당신이 실제로 부정적인 요소에 접근하려고하지 않는 한 (이것은 당신이하고있는 일을 모르는 경우에 보통 나쁜 생각입니다). 그러나 여기는 큰 문제가 아닙니다.

다른 팁

16 진수를 정수로 바꾸는 다른 함수를 만듭니다.

int hex_digit_to_integer(char digit) {
    if (digit >= 'A' && digit <= 'F') {
        return digit - 'A' + 10;
    } else if (digit >= 'a' && digit <= 'f') {
        return digit - 'a' + 10;
    } else if (digit >= '0' && digit <= '9') {
        return digit - '0';
    }

    return -1; // Bad input.
}

4 가지 사례를 어떻게 처리하는지 주목하십시오. * digit 상류 문자입니다 A..F, * digit 소문자 편지입니다 a..f, * digit 소수점 숫자입니다 0..9, 그리고 * digit 위의 어느 것도 아닙니다.

이제 원래 기능에서 새 기능을 사용하십시오.

int htoi(char f[]) {
    int z, n;
    n = 0;

    /* Loop until we get something which isn't a digit (hex_digit_to_integer returns something < 0). */
    for (z=0; hex_digit_to_integer(f[z]) >= 0; ++z) {
        n = 16 * n + hex_digit_to_integer(f[z]);
    }
}

새로운 기능이 얼마나 깨끗해 보이는지 주목하십시오.

모험심이라면이 마법 기능을 사용할 수 있습니다 (잘못된 입력을 처리하지 않으므로 미리 확인해야합니다).

int hex_digit_to_integer(char digit) {
    return digit - (digit & 64 ? 55 : 48) & 15;
}

모든 f [z]를 전용 변수로 교체하십시오. 해당 변수를 toupper (f [z])로 할당하십시오.

다음은 NPS NSRL Bloom 패키지의 일부 코드입니다.

static int *hexcharvals = 0;

/** Initialization function is used solely for hex output
 */
static void nsrl_bloom_init()
{
    if(hexcharvals==0){
        /* Need to initialize this */
        int i;
        hexcharvals = calloc(sizeof(int),256);
        for(i=0;i<10;i++){
            hexcharvals['0'+i] = i;
        }
        for(i=10;i<16;i++){
            hexcharvals['A'+i-10] = i;
            hexcharvals['a'+i-10] = i;
        }
    }
}

/**
 * Convert a hex representation to binary, and return
 * the number of bits converted.
 * @param binbuf output buffer
 * @param binbuf_size size of output buffer in bytes.
 * @param hex    input buffer (in hex)
 */
int nsrl_hex2bin(unsigned char *binbuf,size_t binbuf_size,const char *hex)
{
    int bits = 0;
    if(hexcharvals==0) nsrl_bloom_init();
    while(hex[0] && hex[1] && binbuf_size>0){
        *binbuf++ = ((hexcharvals[(unsigned char)hex[0]]<<4) |
                     hexcharvals[(unsigned char)hex[1]]);
        hex  += 2;
        bits += 8;
        binbuf_size -= 1;
    }
    return bits;
}

이 코드는 초고속으로 설계되었고, 상단 및 소문 육각형을 모두 처리하며, 모든 길이의 육각 문자열을 처리합니다. NSRL_HEX2BIN () 함수는 이진 버퍼, 해당 버퍼의 크기 및 변환하려는 16 진 문자열을 취합니다. 실제로 변환 된 비트 수를 반환합니다.

오, 정수 만 원한다면 바이트 (엔디 언 독립 코드의 경우)를 곱하거나 캐스트 (엔디 어 의존적 코드)를 수행 할 수 있습니다.

당신은 시도 할 수 있습니다 SSCANF 대신에:

#include <stdio.h>

...

//NOTE: buffer overflow if f is not terminated with \0 !!
int htoi(char f[]){
  int intval = -1;
  if (EOF == sscanf(f, "%x", &intval))
    return -1; //error
  return intval;
}

두 가지 옵션 :

스캔하기 전에 대문자로 변환하십시오.

4 루프에서 소문자를 처리하는 경우 두 번째를 추가하십시오.

대신 이것을 시도해 보세요:

int htoi (char f[]) {
    int  z, n;
    n = 0;
    for (z = 0; f[z] != '\0'; ++z) { 
        if (f[z] >= '0' && f[z] <= '9') {
            n = n * 16 + f[z] - '0';
        } else {
            if (f[z] >= 'A' && f[z] <= 'F') {
                n = n * 16 + f[z] - 'A' + 10;
            } else {
                if (f[z] >= 'a' && f[z] <= 'f') {
                    n = n * 16 + f[z] - 'a' + 10;
                } else {
                    break;
                }
            }
        }
    }
    return n;
}

여전히 입력을 사용자와 동일한 방식으로 처리하지만(포인터를 사용하는 경향이 있지만 때로는 초보자가 이해하기 어렵습니다) 0-9, A-F 및 a-f의 세 가지 개별 사례를 도입하여 각각을 적절하게 처리합니다.

원래 코드에서는 실제로 잘못된 문자('9'와 'A' 사이의 6개)를 허용하고 이를 기반으로 잘못된 결과를 생성합니다.

이 새 코드는 일반적으로 문자열 끝에서만 루프를 종료합니다.유효하지 않은 16진수 문자를 찾으면 종료 조건과 기능적으로 동일하게 루프에서 벗어나게 됩니다.

strtol ()를 사용하십시오. 이것은 표준 C90 기능이며 대부분의 순진한 구현보다 훨씬 강력합니다. 또한 Dec (접두사 없음), 16 진수 (0x) 및 OCT (0으로 시작)의 원활한 변환을 지원합니다.

곱셈 대신 시프트 회전을 사용한 영향.

int HexToDec(char *Number)
{

    unsigned int val = 0;

    int i , nibble;
    for(i = strlen( Number ) - 1; i >= 0; --i, nibble += 4)
    {
        const char hex = Number[i];
        if (hex >= '0' && hex <= '9')
            val += (hex - '0')<<nibble;
        else if (hex >= 'A' && hex <= 'F')
            val += (hex - 'A' + 10)<<nibble;
        else if (hex >= 'a' && hex <= 'f')
            val += (hex - 'a' + 10)<<nibble;
        else
            return -1;
    }
    return val;
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top