Core Programming/C Standard Library: Resource & Performan

C언어 문자열 자르기와 복제: strtok, strdup 완벽 가이드 (메모리 관리 팁)

임베디드 친구 2025. 2. 13. 09:13
반응형

C언어에서 CSV 데이터나 명령어 포맷을 처리할 때 특정 기호를 기준으로 문자열을 나누는 작업은 필수입니다. 이때 가장 많이 쓰이는 함수가 문자열 분할의 strtok과 동적 복제의 strdup입니다.

오늘은 이 두 함수의 상세한 동작 원리와 함께, 실무에서 주의해야 할 메모리 관리 방법을 정리해 보겠습니다.

Generated by Gemini AI.


1. strtok: 구분자로 문자열 자르기 (Tokenization)

strtok 함수는 문자열을 특정 구분자(Delimiter)를 기준으로 나누어 토큰(Token) 단위로 분할합니다.

1.1 함수 원형

C
 
char *strtok(char *str, const char *delim);

1.2 동작 원리 (중요!)

strtok은 단순히 문자열을 찾는 것에 그치지 않고 원본 문자열을 직접 수정합니다.

  1. 구분자를 찾으면 그 위치에 널 문자(\0)를 삽입하여 문자열을 끊습니다.
  2. 첫 번째 호출 시에는 대상 문자열(str)을 인자로 주지만, 두 번째 호출부터는 NULL을 전달하여 이전 위치 다음부터 탐색을 이어갑니다.

1.3 예제 코드

C
 
#include <stdio.h>
#include <string.h>

int main() {
    char str[] = "C,Python;Java:JavaScript";
    const char *delim = ",;:"; // 여러 개의 구분자 지정 가능
    char *token;

    // 첫 번째 호출: 대상 문자열 전달
    token = strtok(str, delim);
    while (token != NULL) {
        printf("Token: %s\n", token);
        // 두 번째 호출부터는 NULL 전달
        token = strtok(NULL, delim);
    }
    return 0;
}

⚠️ 주의사항: strtok은 원본 문자열을 변형시키므로, 원본 데이터를 보존해야 한다면 반드시 복사본을 만들어 작업해야 합니다. 또한 내부 정적 변수를 사용하므로 멀티스레드 환경에서는 안전한 strtok_r을 권장합니다.


2. strdup: 문자열 동적 복제 (Duplicate)

strdup은 원본 문자열과 똑같은 새로운 문자열을 힙(Heap) 메모리에 생성합니다.

2.1 함수 원형

C
 
char *strdup(const char *s);

2.2 특징 및 장점

  • 동적 할당: 내부적으로 malloc을 호출하여 원본 문자열 크기(+ 널 문자 1바이트)만큼 메모리를 할당합니다.
  • 독립성: 복제된 문자열은 원본과 별개의 메모리 주소를 가지므로 서로 영향을 주지 않습니다.

2.3 예제 코드

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

int main() {
    char original[] = "Hello, world!";
    char *copy = strdup(original); // 내부에서 malloc 실행

    if (copy != NULL) {
        printf("원본 주소: %p, 복제본 주소: %p\n", (void*)original, (void*)copy);
        printf("복제된 내용: %s\n", copy);
        
        free(copy); // 사용 후 반드시 메모리 해제!
    }
    return 0;
}

3. 실전 활용: 분할된 토큰 안전하게 저장하기

strtok은 원본을 훼손하므로, 분할된 각 단어를 나중에 다시 사용하려면 strdup으로 각각 복제해 두는 방식이 실무에서 자주 쓰입니다.

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

int main() {
    char str[] = "Apple,Banana,Cherry";
    char *token;
    char *saved_tokens[3];
    int i = 0;

    token = strtok(str, ",");
    while (token != NULL && i < 3) {
        // 분할된 토큰을 동적으로 복제하여 저장
        saved_tokens[i++] = strdup(token);
        token = strtok(NULL, ",");
    }

    for (int j = 0; j < i; j++) {
        printf("저장된 토큰 [%d]: %s\n", j, saved_tokens[j]);
        free(saved_tokens[j]); // 할당된 메모리 반환
    }

    return 0;
}

4. 핵심 요약 및 비교

함수 주요 기능 메모리 특징 주의사항
strtok 문자열 분할 원본 문자열 수정 멀티스레드 주의 (strtok_r 권장)
strdup 문자열 복제 힙 메모리 동적 할당 사용 후 반드시 free() 호출

마무리하며

문자열 파싱은 C언어의 강력하면서도 까다로운 부분입니다. strtok으로 데이터를 나누고, strdup으로 필요한 데이터를 안전하게 보관하는 패턴을 익히면 더 복잡한 데이터 처리도 충분히 해낼 수 있습니다.


포스팅이 도움이 되셨다면 하트(♥)와 댓글 부탁드립니다!

임베디드 소프트웨어 및 최적화 기법에 대한 전문적인 정보는 'Coding by Head' 블로그에서 계속됩니다.

https://coding-by-head.tistory.com/

반응형