C언어 문자열 추출 완전 가이드 | 표준 함수·자체 함수·멀티바이트 지원

目次

1. 서론

C 언어에서 문자열을 다루는 것은 프로그래밍을 배우는 데 있어 중요한 기술 중 하나입니다. 특히、문자열 추출(부분 문자열 추출)은 데이터 처리 및 포맷 변환을 할 때 자주 사용됩니다.

본 기사에서는、C 언어에서 문자열을 추출하는 방법에 대해、표준 라이브러리 함수를 사용하는 방법, 직접 함수를 만드는 방법, 멀티바이트 문자(일본어) 대응, 문자열 분할 방법 등을 자세히 설명합니다. 또한、응용 예시와 오류 처리에 대해서도 소개하니 꼭 마지막까지 확인해 주세요.

이 기사에서 배울 수 있는 것

본 기사를 읽음으로써 다음과 같은 스킬을 습득할 수 있습니다.

  • C 언어 문자열의 기본 개념과 종료 문자 의 역할
  • strncpystrchr표준 라이브러리 함수 를 사용한 부분 문자열 추출
  • 자작 함수
  • 멀티바이트 문자(일본어)를 고려한
  • strtok문자열 분할 방법
  • 특정 문자의 앞뒤를 가져오는 방법

초보자도 이해하기 쉽도록 코드 예제를 곁들여 설명합니다.

왜 C 언어에서 문자열 추출이 중요한가?

C 언어는문자열을「배열(char형 배열)」으로 취급하기 때문에、다른 고급 언어(Python이나 JavaScript 등)처럼 쉽게 부분 문자열을 얻을 수 없습니다. 따라서、아래와 같은 상황에서 적절한 방법을 선택하는 것이 중요합니다.

1. 입력 데이터 처리

예를 들어、로그 데이터나 CSV 파일 등의 데이터를 분석할 때 특정 항목을 추출해야 합니다.

2. 특정 키워드 검색

문자열 중에서 특정 키워드를 찾아 그 전후 정보를 얻는 것은 검색 기능 및 데이터 추출에 필수적입니다.

3. 프로그램 안전성 향상

strncpy와 같은 함수를 적절히 사용함으로써、버퍼 오버플로우(버퍼 크기를 초과하는 데이터 쓰기)을 방지할 수 있습니다. 이는、보안상의 위험을 회피하기 위해 중요합니다.

본 기사 구성

본 기사에서는 아래 흐름으로 설명을 진행합니다.

  1. C 언어의 문자열이란? 기본 개념과 종결 문자의 중요성
  2. C 언어로 부분 문자열을 추출하는 방법【표준 라이브러리 편】
  3. C 언어에서 부분 문자열을 추출하는 방법【자작 함수 편】
  4. 문자 코드별 문자열 추출 방법
  5. C 언어로 문자열을 분할하는 방법
  6. 응용 예: 특정 문자의 앞뒤를 추출하는 방법
  7. 요약
  8. FAQ

그럼, 먼저「C 언어의 문자열이란? 기본 개념과 종단 문자(널 문자)의 중요성」에 대해 자세히 살펴보겠습니다.

2. C-gengo의 문자열이란? 기본 개념과 종료 문자 중요성

2.1 C-gengo의 문자열 기본 개념

문자열은 “char의 배열”

C-gengo에서는, 문자열을 문자의 배열(char형 배열)으로 취급합니다. 예를 들어, 아래 코드는 문자열 정의와 표시의 기본적인 예시입니다。

#include <stdio.h>

int main() {
    char str[] = "Hello, World!"; // Define a string literal as an array
    printf("%s ", str); // Output the string
    return 0;
}

이 코드에서는, "Hello, World!" 라는 문자열이 char 형 배열로 저장되고, printf("%s\n", str); 에 의해 출력됩니다。

문자열의 내부 구조

문자열 "Hello" 은, 메모리 상에서 다음과 같이 저장됩니다。

인덱스012345
문자Hello\0

C-gengo에서는, 문자열의 종료를 나타내는 특수 문자(널 문자 '\0')가 마지막에 자동으로 추가되기 때문에, 문자열 길이는 “실제 문자 수 + 1”이 됩니다。

2.2 종료 문자(널 문자 '

널 문자란?

'
)의 중요성

널 문자가 없을 경우의 문제

널 문자('\0')는, 문자열의 끝을 나타내는 특수 문자입니다. C-gengo의 문자열을 올바르게 다루기 위해서는, 이 널 문자의 존재를 이해하고 있어야 합니다。

#include <stdio.h>

int main() {
    char str[6] = {'H', 'e', 'l', 'l', 'o', '\0'}; // Explicitly specify the null terminator
    printf("%s ", str);                            // Display correctly
    return 0;
}

위의 코드에서는, '\0' 가 없으면 "Hello" 의 종료가 인식되지 않아, 예기치 않은 동작이 발생할 가능성이 있습니다

2.3 문자열의 올바른 정의 방법

아래와 같이, 종료 문자를 잊어버리면, 메모리의 비정상적인 동작을 일으킬 가능성이 있습니다。

#include <stdio.h>

int main() {
    char str[5] = {'H', 'e', 'l', 'l', 'o'}; // Does not include the null terminator
    printf("%s ", str);                      // May cause unexpected behavior
    return 0;
}

오류의 원인

  • printf("%s\n", str); null 문자 '\0'을 찾을 때까지 문자를 출력하고 계속합니다
  • 만약 가 없으면, 메모리 상의 다른 데이터가 출력될 가능성이 있다。

방법① 문자열 리터럴 사용하기

방법② 명시적으로 배열 정의하기

가장 일반적인 문자열 정의 방법은, 문자열 리터럴을 사용하는 것입니다。

char str[] = "Hello";

이 방법에서는, C 컴파일러가 자동으로 널 문자 '\0' 를 추가해 주기 때문에, 별도의 처리는 필요 없습니다。

2.4 문자열 크기 확인 방법

수동으로 '\0' 를 포함하여 정의하는 경우는, 다음과 같이 기술합니다。

char str[6] = {'H', 'e', 'l', 'l', 'o', '\0'};
  • 문자수 의 크기를 지정하고, 마지막에 를 넣는 것이 중요합니다。
  • 만약 에 를 넣는 것을 깜빡하면, 예기치 않은 동작이 발생합니다。

strlen 의 동작

문자열의 길이(문자 수)를 얻기 위해서는, strlen 함수를 사용합니다。

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

int main() {
    char str[] = "Hello";
    printf("Length of the string: %lu\n", strlen(str)); // Outputs 5 (does not include the null terminator)
    return 0;
}

2.5 정리

  • strlen널 문자 '\0'가 나타날 때까지의 문자 수를 셈합니다
  • sizeof(str)

3. C 언어에서 부분 문자열을 잘라내는 방법【표준 라이브러리 편】

  1. C 언어의 문자열은 char 배열로 표현된다
  2. 종단 문자(널 문자 '\0')는 문자열의 끝을 나타내므로 반드시 포함해야 합니다
  3. 문자열의 길이를 얻으려면 strlen 를 사용합니다
  4. 적절한 방법으로 문자열을 정의하지 않으면 예기치 않은 오류가 발생할 가능성이 있습니다

3.1 strncpy 를 사용한 부분 문자열 가져오기

C 언어에서 부분 문자열을 잘라내려면, 표준 라이브러리를 활용하는 방법이 있습니다. 이 섹션에서는, strncpystrchr 등 의 표준 라이브러리 함수 를 사용하여, 문자열을 부분적으로 가져오는 방법을 설명합니다.

strncpy 의 기본 구문

strncpy문자열의 일부를 다른 버퍼에 복사하는 함수입니다.

기본 사용 예

char *strncpy(char *dest, const char *src, size_t n);
  • dest
  • src
  • n'\0'

strncpy 의 주의점

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

int main() {
    char src[] = "Hello, World!";
    char dest[6];  // Buffer to store the substring

    strncpy(dest, src, 5); // Copy the first 5 characters "Hello"
    dest[5] = '\0';        // Manually add the null terminator

    printf("Substring: %s\n", dest);  // Output "Hello"

    return 0;
}

3.2 strncpy_s 를 사용한 안전한 문자열 복사

  1. NULL 문자 '\0' 를 수동으로 추가해야 합니다 는 최대 글자를 복사하지만, 때문에 명시적으로 를 추가해야 합니다。
  2. 버퍼 오버플로우에 주의 의 크기보다 가 크면, 버퍼를 초과하여 기록할 가능성이 있습니다。

strncpy_s 의 기본 구문

strncpy_sstrncpy 의 안전성을 강화한 버전으로, 버퍼 오버플로우를 방지할 수 있습니다.

사용 예

errno_t strncpy_s(char *dest, rsize_t destsz, const char *src, rsize_t n);
  • dest
  • destszdest
  • src
  • n

strncpy_s 의 장점

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

int main() {
    char src[] = "Hello, World!";
    char dest[6];

    if (strncpy_s(dest, sizeof(dest), src, 5) == 0) {
        dest[5] = '\0';  // Add null terminator just in case
        printf("Substring: %s\n", dest);
    } else {
        printf("Copy error\n");
    }

    return 0;
}

3.3 strchr 를 사용한 특정 문자까지의 잘라내기

  • 버퍼 크기 () 를 지정하기 위해, 안전하게 복사할 수 있다。
  • destszn

하지만、strncpy_s 는 C11 규격에 추가되었기 때문에, 일부 환경에서는 사용할 수 없다는 점에 주의가 필요합니다。

strchr 의 기본 구문

strchr 를 사용하면, 특정 문자의 위치를 찾아, 그 부분까지의 문자열을 가져올 수 있습니다.

사용 예

char *strchr(const char *str, int c);
  • str
  • cchar

포인트

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

int main() {
    char str[] = "Hello, World!";
    char *pos = strchr(str, ','); // Find the position of ','

    if (pos != NULL) {
        int length = pos - str; // Calculate the number of characters up to ','
        char result[20];

        strncpy(result, str, length);
        result[length] = '\0'; // Add the null terminator

        printf("Substring: %s\n", result);  // Output "Hello"
    }

    return 0;
}

3.4 strstr 를 사용한 키워드 검색과 잘라내기

  • strchr가장 먼저 발견된 c의 주소를 반환하므로,
  • pos - strstrncpy

strstr 의 기본 구문

strstr 는 부분 문자열을 검색하고, 그 이후의 문자열을 가져오는 데 편리합니다.

사용 예

char *strstr(const char *haystack, const char *needle);
  • 헤이스택
  • 바늘

포인트

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

int main() {
    char str[] = "Hello, World!";
    char *pos = strstr(str, "World"); // Search for the position of "World"

    if (pos != NULL) {
        printf("Found substring: %s\n", pos);
    } else {
        printf("Substring not found.\n");
    }

    return 0;
}

3.5 정리

  • strstrneedle
  • NULLneedlehaystack

4. C-gengo에서 부분 문자열을 추출하는 방법【자작 함수 편】

  1. strncpy 를 사용하면, 부분 문자열을 안전하게 복사할 수 있지만, 널 문자를 수동으로 추가해야 합니다。
  2. strncpy_sdestsz를 지정할 수 있어 안전성이 향상됩니다.
  3. strchr 를 사용하면, 특정 문자까지의 부분 문자열을 얻을 수 있습니다.
  4. strstr 를 사용하면, 특정 키워드의 위치를 가져와서 그 이후를 잘라낼 수 있다.

표준 라이브러리를 활용함으로써, C 언어에서의 문자열 처리를 간단하면서도 안전하게 구현할 수 있습니다.

4.1 자작 함수를 만드는 장점

표준 라이브러리를 활용하면 기본적인 부분 문자열을 추출할 수 있지만, 경우에 따라보다 유연한 방법가 요구되는 경우가 있습니다. 따라서, 이 섹션에서는자작 함수를 사용한 부분 문자열 추출에 대해 설명합니다。

4.2 기본적인 부분 문자열 추출 함수

표준 라이브러리를 사용하면, 부분 문자열의 복사와 검색이 가능하지만, 다음과 같은 문제점이 있습니다。

  • strncpy는 null 문자 '\0'을 자동으로 추가하지 않는다
  • strchrstrstr 는 부분적인 검색만 할 수 있다
  • 더 유연한 문자열 조작이 어렵다

그렇기 때문에, 특정 용도에 맞게 커스터마이즈할 수 있는자작 함수를 만드는 것이 유효합니다。

함수 사양

우선, 지정한 위치에서 문자열을 추출하는 기본적인 함수를 작성합니다。

구현 코드

  • 인수
  • const char *source
  • int start
  • int length
  • char *dest
  • 처리 내용
  • startlengthdest
  • '\0'

요점

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

void substring(const char *source, int start, int length, char *dest) {
    int i;
    for (i = 0; i < length && source[start + i] != '\0'; i++) {
        dest[i] = source[start + i];
    }
    dest[i] = '\0'; // Add null terminator
}

int main() {
    char text[] = "Hello, World!";
    char result[10];

    substring(text, 7, 5, result); // Extract "World"
    printf("Substring: %s\n", result);

    return 0;
}

4.3 malloc을 사용한 동적 부분 문자열 획득

  • forlength
  • '\0'
  • dest[i] = '\0';반드시 널 문자를 끝에 배치

함수 사양

위의 함수에서는, dest의 크기를 사전에 확보할 필요가 있습니다. 그러나, 필요한 크기를 동적으로 확보할 수 있다면, 보다 범용적인 함수가 됩니다。

구현 코드

  • 필요한 메모리를 로 확보
  • startlength
  • 호출자에서 를 해야 한다

요점

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

char *substring_dynamic(const char *source, int start, int length) {
    char *dest = (char *)malloc(length + 1); // +1 for the null terminator
    if (dest == NULL) {
        return NULL; // Memory allocation failed
    }

    int i;
    for (i = 0; i < length && source[start + i] != '\0'; i++) {
        dest[i] = source[start + i];
    }
    dest[i] = '\0';

    return dest;
}

int main() {
    char text[] = "Hello, World!";
    char *result = substring_dynamic(text, 7, 5);

    if (result != NULL) {
        printf("Substring: %s\n", result);
        free(result); // Free allocated memory
    } else {
        printf("Memory allocation failed.\n");
    }

    return 0;
}

4.4 멀티바이트 문자(Nihongo) 대응

  • malloc동적으로 메모리를 할당하기 위해
  • 사용 후에는 에서 메모리를 해제해야 합니다.

멀티바이트 문자를 고려한 구현

Nihongo(UTF-8 등 멀티바이트 문자)를 다루는 경우, 1문자가 1바이트는 아닐 수도 있다 때문에, 단순한 substring 함수는 올바르게 동작하지 않습니다。

구현 코드(UTF-8 대응)

  • mbstowcswchar_t
  • wcsncpy
  • wcstombs

요점

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include <locale.h>

void substring_utf8(const char *source, int start, int length, char *dest) {
    setlocale(LC_ALL, ""); // Set the locale

    wchar_t wsource[256];
    mbstowcs(wsource, source, 256); // Convert UTF-8 string to wide-character string

    wchar_t wresult[256];
    wcsncpy(wresult, wsource + start, length); // Extract substring in wide characters
    wresult[length] = L'\0';

    wcstombs(dest, wresult, 256); // Convert back to multibyte string
}

int main() {
    char text[] = "こんにちは、世界!"; // UTF-8 string
    char result[20];

    substring_utf8(text, 5, 3, result); // Extract "世界"
    printf("Substring: %s\n", result);

    return 0;
}

4.5 정리

  • setlocale(LC_ALL, "");
  • mbstowcs
  • wcsncpywcstombs

5. 문자코드별 문자열 추출 방법

  1. substring 를 직접 만들면, 유연하게 부분 문자열을 가져올 수 있다。
  2. 동적 메모리 확보 (malloc) 를 이용하면, 가변 크기의 부분 문자열을 가져올 수 있다。
  3. 멀티바이트 문자(일본어)를 다룰 때는、mbstowcs / wcstombs 를 활용한다。

표준 라이브러리의 strncpystrchr로는 대응하기 어려운 경우, 자작 함수를 생성함으로써, C-gengo의 문자열 처리를 보다 강력하게 할 수 있습니다。

5.1 ASCII(1바이트 문자)의 경우

C 언어에서는、문자코드의 차이에 주의하지 않으면、문자열 추출 처리가 올바르게 동작하지 않을있을 수 있습니다。특히、日本어와 같은 멀티바이트 문자(UTF-8、Shift_JIS、EUC-JP 등)를 다룰 경우、1문자=1바이트가 아니기 때문에、단순한 strncpysubstring 함수로는 적절히 처리할 수 없습니다。

본 섹션에서는、문자코드별 문자열 추출 방법에 대해 자세히 설명합니다。

기본적인 부분 문자열 얻기

구현 예시

ASCII 문자는 1문자 = 1바이트 이므로、strncpysubstring 함수로 쉽게 처리할 수 있습니다。

5.2 UTF-8(멀티바이트 문자)의 경우

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

void substring_ascii(const char *source, int start, int length, char *dest) {
    strncpy(dest, source + start, length);
    dest[length] = '\0'; // Add null terminator
}

int main() {
    char text[] = "Hello, World!";
    char result[6];

    substring_ascii(text, 7, 5, result); // Extract "World"
    printf("Substring: %s\n", result);

    return 0;
}

포인트

  • ASCII 문자(영숫자만)의 경우는 strncpy으로 충분히 대응 가능
  • '\0'(널 문자)를 반드시 추가하세요

UTF-8의 특성

올바른 처리 방법

UTF-8에서는、1문자의 바이트 수가 1-4바이트 로 가변하기 때문에、단순히 strncpy를 사용하면 문자 중간에 잘릴 가능성이 있습니다。

UTF-8에 대응한 부분 문자열 얻기

C 언어에서는、UTF-8을 안전하게 처리하려면 mbstowcs를 사용하여 와이드 문자열(wchar_t)로 변환하고、부분 문자열을 얻는 방법이 권장됩니다。

5.3 Shift_JIS(멀티바이트 문자)의 경우

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

void substring_utf8(const char *source, int start, int length, char *dest) {
    setlocale(LC_ALL, ""); // Set the locale

    wchar_t wsource[256];
    mbstowcs(wsource, source, 256); // Convert multibyte string to wide-character string

    wchar_t wresult[256];
    wcsncpy(wresult, wsource + start, length); // Get the substring
    wresult[length] = L'\0';

    wcstombs(dest, wresult, 256); // Convert wide-character string back to multibyte
}

int main() {
    char text[] = "こんにちは、世界!"; // UTF-8 string
    char result[20];

    substring_utf8(text, 5, 3, result); // Extract "世界"
    printf("Substring: %s\n", result);

    return 0;
}

포인트

  • setlocale(LC_ALL, "");
  • mbstowcswchar_twcsncpy
  • wcstombs

Shift_JIS의 특성

Shift_JIS에 대응한 부분 문자열 얻기

Shift_JIS에서는、1문자가 1바이트 또는 2바이트가 되기 때문에、단순한 strncpy는 문자 깨짐의 원인이 됩니다。

Shift_JIS에서의 구현

Shift_JIS의 경우에도 와이드 문자열로 변환하여 처리하는 방법이 권장됩니다。

5.4 EUC-JP(멀티바이트 문자)의 경우

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

void substring_sjis(const char *source, int start, int length, char *dest) {
    setlocale(LC_ALL, "Japanese"); // Set locale to handle Shift_JIS

    wchar_t wsource[256];
    mbstowcs(wsource, source, 256); // Convert multibyte string (Shift_JIS) to wide-character string

    wchar_t wresult[256];
    wcsncpy(wresult, wsource + start, length); // Extract substring
    wresult[length] = L'\0';

    wcstombs(dest, wresult, 256); // Convert wide-character string back to multibyte (Shift_JIS)
}

int main() {
    char text[] = "こんにちは、世界!"; // Shift_JIS string (depending on environment)
    char result[20];

    substring_sjis(text, 5, 3, result); // Extract "世界"
    printf("Substring: %s\n", result);

    return 0;
}

포인트

  • Shift_JIS를 올바르게 처리하려면 를 설정합니다.
  • 안전하게 문자열을 처리하려면 와 를 사용하세요.

EUC-JP의 특성

EUC-JP에 대응한 부분 문자열 얻기

EUC-JP도 Shift_JIS와 마찬가지로、1문자의 바이트 수가 다르기 때문에、와이드 문자를 이용한 변환 처리가 필요합니다。

5.5 정리

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

void substring_eucjp(const char *source, int start, int length, char *dest) {
    setlocale(LC_ALL, "ja_JP.eucJP"); // Set locale to handle EUC-JP

    wchar_t wsource[256];
    mbstowcs(wsource, source, 256); // Convert multibyte string (EUC-JP) to wide-character string

    wchar_t wresult[256];
    wcsncpy(wresult, wsource + start, length); // Extract substring
    wresult[length] = L'\0';

    wcstombs(dest, wresult, 256); // Convert wide-character string back to multibyte (EUC-JP)
}

int main() {
    char text[] = "こんにちは、世界!"; // EUC-JP string (depending on environment)
    char result[20];

    substring_eucjp(text, 5, 3, result); // Extract "世界"
    printf("Substring: %s\n", result);

    return 0;
}

포인트

  • setlocale(LC_ALL, "ja_JP.eucJP");
  • mbstowcswcstombs

6. C언어에서 문자열을 분할하는 방법

문자 코드바이트 수권장 처리 방법
ASCII1바이트strncpy
UTF-81-4바이트mbstowcswcstombs
Shift_JIS1 or 2바이트mbstowcswcstombs
EUC-JP1 or 2바이트mbstowcswcstombs
  • ASCII 문자만이라면 strncpy 로 OK
  • UTF-8, Shift_JIS, EUC-JP의 경우는 mbstowcs / wcstombs 를 사용
  • 환경에 따라 setlocale(LC_ALL, "...");를 적절히 설정합니다

6.1 strtok 를 사용한 문자열 분할

문자열을 분할하는 처리는, CSV 데이터 분석, 명령줄 인수 처리, 로그 데이터 분석 등 많은 경우에 필요합니다. C언어에서는, strtokstrtok_r 와 같은 표준 라이브러리 함수를 사용하는 방법이나, 직접 함수를 만드는 방법이 있습니다.

이 섹션에서는, 특정 구분 문자로 문자열을 분할하는 방법에 대해 자세히 설명합니다.

기본 구문

strtok 은, 지정한 구분 문자(구분자)로 문자열을 분할하는 함수입니다.

사용 예: 콤마 , 로 문자열을 분할

char *strtok(char *str, const char *delim);
  • str
  • delim
  • 반환값
  • 주의점strtok'\0'

실행 결과

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


int main() {
    char str[] = "apple,banana,orange,grape"; // String to be split
    char *token = strtok(str, ",");            // Get the first token

    while (token != NULL) {
        printf("Token: %s\n", token);
        token = strtok(NULL, ",");             // Get the next token
    }

    return 0;
}

strtok 의 주의점

token: apple
token: banana
token: orange
token: grape

6.2 strtok_r 를 사용한 스레드 안전한 문자열 분할

  1. 원본 문자열을 변경합니다
  • strtok구분자를 '\0'으로 바꾸어,
  1. 스레드 세이프하지 않음
  • strtok전역 정적 변수를 내부에서 사용한다

기본 구문

strtok_r 은, strtok 의 스레드 안전 버전이며, 상태를 saveptr 에 저장하기 때문에 멀티스레드 환경에서도 안전하게 사용할 수 있습니다.입니다。

사용 예: 공백으로 문자열을 분할

char *strtok_r(char *str, const char *delim, char **saveptr);
  • str
  • delim
  • saveptr

strtok_r 의 장점

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

int main() {
    char str[] = "Hello World from C"; // String to be split
    char *token;
    char *saveptr; // Pointer to store internal state

    token = strtok_r(str, " ", &saveptr); // Get the first token
    while (token != NULL) {
        printf("Token: %s\n", token);
        token = strtok_r(NULL, " ", &saveptr); // Get the next token
    }

    return 0;
}

6.3 직접 함수를 사용해 문자열을 분할하기(strtok 를 사용하지 않는 방법)

  • 스레드 세이프
  • 여러 문자열을 동시에 처리할 수 있다

직접 함수의 사양

strtok 은 원본 문자열을 변경하기 때문에, 변경하지 않고 문자열을 분할하는 직접 함수를 만드는 것도 가능합니다。

구현 코드

  • 입력
  • const char *source
  • const char delim
  • char tokens[][50]
  • 처리
  • source
  • delimtokens

실행 결과

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

void split_string(const char *source, char delim, char tokens[][50], int *count) {
    int i = 0, j = 0, token_index = 0;

    while (source[i] != '\0') {
        if (source[i] == delim) {
            tokens[token_index][j] = '\0';
            token_index++;
            j = 0;
        } else {
            tokens[token_index][j] = source[i];
            j++;
        }
        i++;
    }
    tokens[token_index][j] = '\0';
    *count = token_index + 1;
}

int main() {
    char text[] = "dog,cat,bird,fish";
    char tokens[10][50]; // Can store up to 10 words
    int count;

    split_string(text, ',', tokens, &count);

    for (int i = 0; i < count; i++) {
        printf("Token: %s\n", tokens[i]);
    }

    return 0;
}

포인트

Token: dog
Token: cat
Token: bird
Token: fish

6.4 문자열 분할의 응용(CSV 데이터 처리)

  • source
  • tokens

CSV 데이터 분석 예시

CSV(콤마 구분) 데이터를 strtok 를 사용해 분석할 수 있습니다。

실행 결과

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

int main() {
    char csv[] = "Alice,24,Female\nBob,30,Male\nCharlie,28,Male"; // CSV data
    char *line = strtok(csv, "\n"); // Process line by line

    while (line != NULL) {
        char *name = strtok(line, ",");
        char *age = strtok(NULL, ",");
        char *gender = strtok(NULL, ",");

        printf("Name: %s, Age: %s, Gender: %s\n", name, age, gender);

        line = strtok(NULL, "\n");
    }

    return 0;
}

6.5 요약

Name: Alice, Age: 24, Gender: Female
Name: Bob, Age: 30, Gender: Male
Name: Charlie, Age: 28, Gender: Male

결론

방법장점단점
strtok간단히 분할할 수 있다원본 문자열을 변경하다
strtok_rスレッドセーフ사용법이 조금 복잡합니다
자작 함수원본 문자열을 변경하지 마세요코드가 길어집니다
CSV 분석데이터 처리에 편리한strtok 제한에 주의하세요

7. 응용 예: 특정 문자 앞뒤를 추출하는 방법

  • 단순한 분할이라면 strtok
  • 멀티스레딩이라면 strtok_r
  • 원본을 변경하고 싶지 않다면 직접 만든 함수를 사용하세요
  • CSV 데이터 분석에도 적용 가능

다음 섹션에서는, 「응용 예: 특정 문자 앞뒤를 추출하는 방법」에 대해 자세히 설명합니다。

7.1 strchr 를 사용하여 특정 문자 앞의 문자열을 얻는다

문자열 처리에서는、특정 문자와 키워드의 앞뒤를 추출하는작업이 필요해지는 경우가 자주 있습니다。예를 들어、아래와 같은 경우가 생각됩니다。

  • URL에서 도메인 부분만 가져오기
  • 파일 경로에서 파일명을 추출
  • 특정 태그나 기호 앞뒤의 문자열을 가져옵니다

C 언어에서는、strchrstrstr 를 이용함으로써, 이러한 처리를 구현할 수 있습니다。또한、보다 유연한 처리가 필요할 경우, 직접 함수를 만드는 방법도 유효합니다。

기본 구문

strchr 를 사용하면、특정 문자(가장 처음 발견된 것)의 위치를 지정할 수 있습니다。

사용 예: 파일 경로에서 파일 이름을 얻는다

char *strchr(const char *str, int c);
  • str
  • cchar

strchrc 를 찾은 경우, 그 주소를 반환합니다。

실행 결과

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

void get_filename(const char *path, char *filename) {
    char *pos = strrchr(path, '/'); // Search for the last '/'

    if (pos != NULL) {
        strcpy(filename, pos + 1); // Copy from the character after '/'
    } else {
        strcpy(filename, path); // If no '/', copy the whole path
    }
}

int main() {
    char path[] = "/home/user/documents/report.txt";
    char filename[50];

    get_filename(path, filename);
    printf("Filename: %s\n", filename);

    return 0;
}

포인트

Filename: report.txt

7.2 strstr 를 사용하여 특정 키워드 뒤의 문자열을 얻는다

  • strrchr 마지막으로 나타난 특정 문자(/)의 위치를 가져오다
  • pos + 1ファイル名だけを取得可能

기본 구문

strstr 를 사용하면、특정 문자열(키워드)을 검색하고, 그 위치 이후의 문자열을 얻을 수 있습니다。

사용 예: URL에서 도메인을 얻는다

char *strstr(const char *haystack, const char *needle);
  • haystack
  • needle

strstrneedle 를 찾은 경우, 그 위치의 주소를 반환합니다。

실행 결과

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

void get_domain(const char *url, char *domain) {
    char *pos = strstr(url, "://"); // Search for the position of "://"

    if (pos != NULL) {
        strcpy(domain, pos + 3); // Copy from the character after "://"
    } else {
        strcpy(domain, url); // If "://" is not found, copy the entire string
    }
}

int main() {
    char url[] = "https://www.example.com/page.html";
    char domain[50];

    get_domain(url, domain);
    printf("Domain part: %s\n", domain);

    return 0;
}

포인트

Domain part: www.example.com/page.html

7.3 strchr 를 사용하여 특정 문자 앞뒤 부분을 분할

  • strstr"https://""http://""//"
  • pos + 3://

사용 예: 이메일 주소에서 사용자명과 도메인을 분리

strchr 를 활용하면、특정 문자의 앞뒤 문자열을 분할하여 얻을 수 있습니다。

실행 결과

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

void split_email(const char *email, char *username, char *domain) {
    char *pos = strchr(email, '@'); // Search for the position of '@'

    if (pos != NULL) {
        strncpy(username, email, pos - email); // Copy the part before '@'
        username[pos - email] = '\0';          // Add null terminator
        strcpy(domain, pos + 1);               // Copy the part after '@'
    }
}

int main() {
    char email[] = "user@example.com";
    char username[50], domain[50];

    split_email(email, username, domain);
    printf("Username: %s\n", username);
    printf("Domain: %s\n", domain);

    return 0;
}

포인트

Username: user
Domain: example.com

7.4 응용: HTML 태그 내의 특정 속성을 추출

  • strchr'@'
  • strncpy'@' 앞부분을 복사하고, 널 문자를 추가
  • strcpy'@' 뒤에 있는 부분을 복사

사용 예: <a href="URL"> 에서 URL을 얻는다

HTML 태그 중에서 특정 속성을 얻는 경우에도、strstr 를 활용할 수 있습니다。

실행 결과

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

void get_href(const char *html, char *url) {
    char *start = strstr(html, "href=\""); // Search for the position of href="
    if (start != NULL) {
        start += 6; // Move past href="
        char *end = strchr(start, '"'); // Search for the next "
        if (end != NULL) {
            strncpy(url, start, end - start);
            url[end - start] = '\0'; // Add null terminator
        }
    }
}

int main() {
    char html[] = "<a href=\"https://example.com\">Click Here</a>";
    char url[100];

    get_href(html, url);
    printf("Extracted URL: %s\n", url);

    return 0;
}

포인트

Extracted URL: https://example.com

7.5 요약

  • strstr"href=\"
  • strchr"

결론

처리 내용사용 함수장점
특정 문자의 앞부분을 가져오기strchr / strrchr간단하고 빠름
특정 문자의 뒤를 가져오기strstr키워드 검색이 가능합니다
특정 문자를 기준으로 앞뒤를 분리strchr + strncpy사용자 이름·도메인 분리 등에 편리
HTML 태그의 속성 가져오기strstr + strchr웹 스크래핑에 적용 가능

8. 요약

  • strchr 또는 strstr 를 활용하면, 특정 문자·키워드의 앞뒤를 간단히 가져올 수 있다
  • 파일 경로 처리, URL 분석, 이메일 주소 분리 등은 많은 상황에서 유용합니다
  • 웹 스크래핑과 같은 고급 처리에도 적용 가능

8.1 기사 되돌아보기

본 기사에서는, C언어에 대한 문자열 추출 방법에 대해, 기본부터 응용까지 자세히 설명했습니다. 여기서, 각 섹션의 중요한 포인트를 되돌아보고, 용도별로 최적의 방법을 정리합니다.

8.2 용도별 최적의 방법

섹션내용핵심 포인트
C 언어 문자열의 기초C언어에서는 문자열이 배열로 처리되며, 종료 문자 가 중요합니다.문자열을 다룰 때는
표준 라이브러리에서의 추출strncpystrchrstrncpy널 종료를 수동으로 추가
자작 함수에 의한 추출유연한 함수를 만듭니다malloc가변 길이 부분 문자열 추출이 가능합니다
문자 코드별 처리UTF-8, Shift_JIS, EUC-JP에 대한 대응 방법mbstowcswcstombs 와이드 문자로 변환하는 것이 안전
문자열 분할 방법strtokstrtok_rstrtok원본 문자열을 변경
특정 문자의 앞뒤를 추출strchrstrstr파일명 가져오기, URL 파싱, HTML 파싱

1. 부분 문자열 추출

2. 문자열 분할

사용 상황최적의 방법
고정 길이의 문자열을 얻고 싶습니다strncpy or substring()
안전한 절단을 하고 싶다strncpy_s
멀티바이트 문자(UTF-8, Shift_JIS, EUC-JP)를 다루다mbstowcs / wcstombs

3. 특정 문자 전후 가져오기

사용 상황최적의 방법
간단히 문자열을 구분하고 싶다strtok
스레드 세이프한 분할을 하고 싶다strtok_r
원본 문자열을 변경하지 않고 분할하고 싶습니다.자작 함수(split_string()

8.3 C언어 문자열 처리 주의점

사용 상황최적의 방법
파일 경로에서 파일 이름을 가져오기strrchr(path, '/')
URL에서 도메인 부분을 가져오기strstr(url, "://")
이메일 주소에서 사용자 이름과 도메인을 분리strchr(email, '@')
HTML 태그에서 속성 값을 가져오기strstr(tag, "href=\"") + strchr(tag, '"')

1. 널 종료 '
안전한 문자열 복사 예시
'
관리 철저히

2. 버퍼 오버플로우에 주의

C언어의 문자열 처리에서는, 종료 문자 '\0' 를 적절히 관리하는 것이 가장 중요합니다. 특히 strncpystrchr 를 사용할 때는, 널 문자를 수동으로 추가하도록 주의하십시오.

3. 멀티바이트 문자 처리는 mbstowcs 를 사용

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

int main() {
    char src[] = "Hello, World!";
    char dest[6];

    strncpy(dest, src, 5);
    dest[5] = '\0'; // Add null terminator for safety

    printf("Substring: %s\n", dest);

    return 0;
}

4. 버퍼 크기 관리

C언어의 문자열 작업에서는, 배열의 범위를 벗어나 접근하지 않도록 신중히 구현할 필요가 있습니다. 특히, strncpy 를 사용할 때는복사할 바이트 수를 제어하는 것이 중요합니다.

안전한 문자열 복사 예시

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

int main() {
    char src[] = "Hello, World!";
    char dest[6];

    strncpy(dest, src, sizeof(dest) - 1);
    dest[5] = '\0'; // Explicitly add null terminator

    printf("Substring: %s\n", dest);
    return 0;
}

8.4 더 나은 학습을 위해

UTF-8 및 Shift_JIS 등 멀티바이트 문자를 다룰 경우, 단순히 strncpystrlen 가 올바르게 동작하지 않는다.

따라서, 멀티바이트 문자를 다룰 때는, 한 번 mbstowcs 로 와이드 문자열로 변환하고, 적절히 처리하는 것이 권장됩니다.

#include <stdio.h>
#include <wchar.h>
#include <locale.h>

int main() {
    setlocale(LC_ALL, ""); // Set the locale

    char text[] = "こんにちは、世界!"; // UTF-8
    wchar_t wtext[256];

    mbstowcs(wtext, text, 256); // Convert to wide-character string

    printf("Converted wide-character string: %ls\n", wtext);

    return 0;
}

학습을 심화하기 위한 토픽

문자열 처리에서는, 필요한 메모리 크기 를 사전에 계산하고, 버퍼 오버플로우를 방지하는 것이 중요합니다. 특히, malloc 를 사용해 동적 메모리를 확보할 때는, 그 크기를 정확히 파악하도록 합시다.

8.5 요약

C언어의 문자열 처리는, 프로그램의 안전성 및 가독성을 향상시키는 중요한 스킬입니다. 본 기사에서 소개한 내용을 바탕으로, 아래 토픽을 추가로 학습하면 보다 고급 문자열 처리가 가능해집니다.

학습을 심화하기 위한 토픽

  1. 정규 표현식 (regex)
  2. 파일 조작 (fgets, fscanf을 사용한 문자열 처리)
  3. 메모리 관리(malloc, realloc 을 사용한 동적 문자열 처리)
  4. 데이터 분석 (JSON, XML 파싱 방법)

8.5 요약

  1. C 언어의 문자열은 char 배열로 관리되기 때문에, 종료 문자 '\0'의 처리가 중요
  2. 부분 문자열을 추출하려면 strncpy, substring(), malloc 를 사용합니다
  3. 문자열의 분할에는 strtok / strtok_r / 자작 함수를 활용
  4. 특정 문자의 앞뒤를 가져오는 경우는 strchr, strstr 를 활용
  5. 멀티바이트 문자(일본어)를 다룰 때는、mbstowcs 를 이용
  6. 안전한 문자열 처리를 염두에 두고, 버퍼 오버플로우에 주의하세요

본 기사 내용을 활용하면, C언어에서실용적인 문자열 처리가 가능합니다. 기본적인 함수를 이해한 뒤, 자작 함수와 응용 처리에 도전하고, 보다 효율적인 코드를 작성할 수 있게 합시다!