C 언어에서 dec/hex 숫자를 입력으로 받기

C 언어에서 dec/hex 숫자를 문자열로 입력으로 받아서 처리할 때의 팁을 공유한다.

dec/hex 기본 처리

C에서 10진수/16진수 숫자를 문자열로 입력받아서 정수값으로 변환할 때 strtoul() 함수를 사용하면 되는 것은 C 프로그래머라면 모두가 익히 아는 사실이다.


그런데, 일부 개발자들은 이 함수에서 3번째 파라미터인 base에서 10, 16 등만 유효한 값으로 알고 있는 사람들은 아래 코드 예와 같이 10진수, 16진수를 각각 처리하는 경우가 있다.

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
    char *value_str;
    unsigned int value;

    if (argc < 2)
    {
        return 1;
    }
    value_str = argv[1];
    if (value_str[0] == '0' && value_str[1] == 'x')
    {
      value = strtoul(value_str, NULL, 16);
    }
    else
    {
      value = strtoul(value_str, NULL, 10);
    }
    printf("value: %d(0x%x)\n", value, value);

    return 0;
}

개선한 dec/hex 처리

그런데 strtoul() 함수의 3번째 파라미터인 base 값으로는 10, 16 등 뿐만 아니라, 0도 가능하다. 특히 0으로 세팅할 경우에는 base를 자동으로 판단하므로, 위 코드는 간단히 아래와 같이 작성될 수 있다.

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
    char *value_str;
    unsigned int value;

    if (argc < 2)
    {
        return 1;
    }
    value_str = argv[1];
    value = strtoul(value_str, NULL, 0);
    printf("value: %d(0x%x)\n", value, value);

    return 0;
}

dec/hex 에러 처리

그런데 위 코드들의 문제는 올바르지 않은 숫자 문자열이 입력된 경우의 처리를 못한다는 것이다.
예를 들어 숫자 뒤에 틀린 알파벳이 온 경우는 아래 예와 같이 올바른 숫자까지의 값이 얻어진다.

$ ./test 256wrong
value: 256(0x100)
$ ./test 0x100wrong
value: 256(0x100)

반면에 만약 틀린 알파벳으로 시작하면 0이 얻어진다.


보통은 이렇게 잘못 입력된 숫자 문자열인 경우에는 올바르지 않은 숫자로 얻는 것보다는 에러로 처리하는 것이 더 좋은데, 이를 디텍트하려면 strtoul의 두번째 파라미터인 endptr를 이용하면 된다.
세부적으로 endptr는 아래와 같은 리턴값을 가진다.

  • 잘못된 문자가 있는 경우: 첫번째 잘못된 문자의 주소를 가리키고, 값은 해당 문자값을 가짐
  • 잘못된 문자가 없는 경우: 입력 문자열의 마지막 문자 다음 주소값을 가리키고, 값은 0을 가짐

따라서 아래 코드 예와 같이 판단할 수 있다.

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
    char *value_str;
    unsigned int value;
    char *endptr;

    if (argc < 2)
    {
        return 1;
    }
    value_str = argv[1];
    value = strtoul(value_str, &endptr, 0);
    if (*endptr != '\0')
    {
        printf("Input string is wrong\n");
        return 1;
    }    
    printf("value: %d(0x%x)\n", value, value);

    return 0;
}

위 코드로 테스트해보면 아래 예와 같이 잘못된 문자가 있는 경우에는 기대대로 에러로 처리된다.

$ ./test 256wrong
Input string is wrong
$ ./test 0x100wrong
Input string is wrong

물론 아래 예와 같이 올바로 입력한 경우에는 정상적으로 값을 얻어온다.

$ ./test 100
value: 100(0x64)
$ ./test 0x100
value: 256(0x100)

카테고리:

업데이트: