ctype.h 함수는 문자 분류와 변환 함수이지만, 실제 핵심은 unsigned char 전제를 지키며 입력을 안전하게 분류하는 데 있습니다.
- 숫자/공백/알파벳 판별 함수를 다시 찾고 싶다
toupper,tolower를 문자열 전체에 적용하는 패턴을 보고 싶다- 왜
char를 그대로 넘기면 안 되는지 정확히 정리하고 싶다
숏컷 코드
if (isdigit((unsigned char)c)) { }
if (isspace((unsigned char)c)) { }
ch = (char)tolower((unsigned char)ch);문법
ctype.h 함수는 보통 두 종류로 나뉩니다.
- 분류:
isdigit,isalpha,isalnum,isspace - 변환:
toupper,tolower
반환값은 bool처럼 보여도 정확히 1이 아니라 0/비0로 읽어야 합니다.
int c = getchar();
if (c != EOF && isdigit((unsigned char)c)) {
puts("digit");
}문자열 전체를 정규화할 때는 이런 패턴이 자주 쓰입니다.
void to_lower_str(char *s) {
for (; *s != '\0'; s++) {
*s = (char)tolower((unsigned char)*s);
}
}경계 이해
이 카드의 핵심은 (unsigned char) 캐스트입니다. ctype.h 함수는 unsigned char 범위 값이나 EOF를 기대하므로, signed char가 음수로 해석되는 환경에서 그대로 넘기면 정의되지 않은 동작이 될 수 있습니다.
char ch = '\xE9';
/* if (isalpha(ch)) { } */ // 위험할 수 있음
if (isalpha((unsigned char)ch)) { } // 안전한 쪽체크포인트
- 분류 함수는 0/비0로 읽습니다.
- 인자는
(unsigned char)로 캐스트하는 습관이 안전합니다. toupper/tolower는 문자열 정규화 루프에도 그대로 씁니다.- 숫자 검사, 공백 건너뛰기, 토큰 검증, 대소문자 무시 비교 전처리에 특히 자주 나옵니다.
주의할 점
ctype.h 함수는 작고 익숙해서 대충 써도 될 것처럼 보이지만, signed char 환경에서의 UB와 == 1 같은 잘못된 반환값 비교 습관 때문에 미묘한 버그가 나오기 쉽습니다. 입력 검증 코드일수록 캐스트를 빼먹지 않는 편이 좋습니다.
참고 링크
1 sources