Quick Reference
문자열 작업은 연결·탐색·분리·포맷·변환으로 나눕니다. destination capacity 또는 원본 수정 여부가 선택의 기준입니다.
| 필요한 일 | 함수 | 반드시 확인할 것 |
|---|---|---|
| 남은 공간에 연결 | strncat | 남은 capacity에서 \0 한 칸 제외 |
| 위치를 찾음 | strstr, strchr, strrchr | NULL이면 찾지 못함 |
| 버퍼에 포맷 | snprintf | 반환값으로 잘림 확인 |
| 숫자로 변환 | strtol, strtod | errno·end pointer·범위 확인 |
| 토큰 분리 | strtok | 원본을 수정하고 상태를 공유 |
char buf[64] = "Hello";
strncat(buf, ", World", sizeof(buf) - strlen(buf) - 1);
char *pos = strstr(buf, "World");
if (pos) printf("found at offset %td\n", pos - buf);문법
문자열 함수는 이름을 하나씩 외우기보다 작업을 다섯 종류로 나누면 정리가 됩니다. 연결, 탐색, 토큰 분리, 포맷팅, 숫자 변환입니다.
char path[64] = "/tmp";
strncat(path, "/data.txt", sizeof(path) - strlen(path) - 1);
char out[64];
snprintf(out, sizeof(out), "%s/%s", "tmp", "data.txt");strcat은 남은 공간을 모르면 위험하고, sprintf는 목적지 크기를 모르기 때문에 버퍼 기반 작업에서는 strncat이나 snprintf가 먼저 떠올라야 합니다.
strncat(dst, src, n)의 n은 destination 전체 크기가 아니라 source에서 추가할 최대 문자 수입니다. 호출 전 dst가 널 종료된 문자열인지와 capacity - strlen(dst) - 1이 0보다 작아지지 않는지를 보장해야 합니다. 여러 조각을 합칠 때는 전체 capacity를 한 번에 전달하는 snprintf가 읽기 쉽습니다.
작업별 선택
탐색 함수는 결과를 인덱스가 아니라 원본 문자열 안의 위치 포인터로 돌려준다고 읽는 편이 맞습니다.
char text[] = "user@example.com";
char *at = strchr(text, '@');
char *domain = strstr(text, "example");strtok는 토큰을 잘라내는 대신 원본 버퍼를 직접 바꿉니다.
구분자를 '\0'로 바꿔 토큰을 나누는 방식이므로, 원본 문자열을 보존해야 하는 상황에는 바로 쓰면 안 됩니다.
또 내부 상태를 쓰므로 멀티스레드나 중첩 파싱에서 주의가 필요합니다.
char line[] = "red,green,blue";
char *token = strtok(line, ",");그래서 문자열 리터럴에 바로 strtok를 쓰는 건 위험합니다.
포맷과 변환
문자열 버퍼에 형식 문자열을 써 넣을 때는 크기 제한이 있는 snprintf가 기본입니다.
반환값으로 잘렸는지도 판단할 수 있습니다.
char out[32];
int written = snprintf(out, sizeof(out), "id=%d", 42);snprintf의 반환값이 음수면 인코딩 오류이고, 0 이상이면서 sizeof(out) 이상이면 출력이 잘렸습니다. 반환값만 확인하지 말고 destination capacity와 함께 판단합니다.
숫자 변환은 실패 여부와 남은 문자열을 같이 볼 수 있어야 합니다. 그래서 atoi보다 strtol/strtod가 더 실전적입니다.
char *end = NULL;
long value = strtol("123x", &end, 10);strtol 전에는 errno = 0으로 두고, 호출 뒤 end == input(숫자를 못 읽음), *end != '\0'(남은 문자), errno == ERANGE(범위 오류), 목적 타입 범위를 모두 검사합니다. strtok의 내부 상태가 맞지 않는 파싱에는 범위를 직접 걷거나, POSIX 전용 strtok_r의 지원 조건을 명시합니다.
int n = atoi("123x"); /* 123, 실패 구분 어려움 */이런 경우 atoi는 어디까지 읽었는지 알기 어려워서, 검증이 필요한 입력에서는 strtol 쪽이 낫습니다.
선택 기준
- 문자열을 이어 붙인다:
strncat또는snprintf - 부분 문자열을 찾는다:
strstr - 문자 위치를 찾는다:
strchr,strrchr - 토큰 분리한다:
strtok(원본 수정 주의) - 포맷 문자열을 버퍼에 쓴다:
snprintf - 숫자로 바꾼다:
strtol,strtod
주의할 점
strtok는 원본 문자열을 수정하고 내부 상태를 사용합니다. 보존해야 하는 문자열이나 복잡한 파싱 흐름에서는 그대로 쓰면 의도와 달라질 수 있습니다.
char line[] = "apple,banana";
char *token = strtok(line, ",");또한 숫자 변환에서 atoi는 실패와 0을 구분하기 어렵습니다. 실패를 감지해야 하면 strtol을 우선하는 편이 낫습니다.
참고 링크
2 sources