libc 문자열 조작 함수 정리
C 언어에서 문자열 처리는 복잡하다. 언어 수준에서 문자열이라는 데이터 형 자체를 지원하지도 않으니, 덧셈 기호(+)나 비교연산자(==)와 같은 기호를 사용하는 직관적인 문자열 연산을 사용할 수 없기 때문이다. C 언어가 문자열 데이터 형을 지원하지 않고, 문자열을 다루는 연산자도 없으니 모든 문자열 연산은 문자열 함수를 통해 이루어진다. C 표준 라이브러리(일명 'libc')에서 str...
로 시작하는 함수들이 그것이며, 모두 string.h
헤더(C++은 cstring
헤더)에 정의되어 있으며 본 시리즈를 통해 이들 함수의 사용법을 정리해보고자 한다. 본 시리즈는 cplusplus(http://www.cplusplus.com) 및 MSDN에 나와있는 레퍼런스를 기준으로 하여 작성되었다.
- libc 문자열 조작 함수 정리 (part 01 - strcpy, strncpy)
- libc 문자열 조작 함수 정리 (part 02 - strcat, strncat)
- libc 문자열 조작 함수 정리 (part 03 - strcmp, strncmp)
- libc 문자열 조작 함수 정리 (part 04 - strchr, strrchr)
- libc 문자열 조작 함수 정리 (part 05 - strstr)
- libc 문자열 조작 함수 정리 (part 06 - strtok)
- libc 문자열 조작 함수 정리 (part 07 - strspn, strcspn)
- libc 문자열 조작 함수 정리 (part 08 - strlen)
- libc 문자열 조작 함수 정리 (part 09 - strpbrk)
- libc 문자열 조작 함수 정리 (part 10 - strxfrm, strcoll)
- libc 문자열 조작 함수 정리 (part 11 - strerror)
Part VII. strspn, strcspn
본 포스팅에서는 전체 문자열 중에서 특정 범위의 문자로만 구성된 부분 문자열span을 구하는 함수인 strspn
과 strcspn
함수에 대해 정리한다.
<Prologue>
strspn
은 문자열을 첫 글자부터 끝 글자까지 하나씩 탐색해 나가다가 미리 지정한 문자 외의 다른 문자를 만나면 지금까지 센 문자수를 반환하고 종료하는 기능을 한다. 즉 특정 범위의 문자로만 구성된 부분 문자열의 길이를 얻는 기능을 수행한다. 반대로 strcspn
는 문자열을 첫 글자부터 끝 글자까지 하나씩 탐색해 나가다가 특정 범위의 문자로만 구성된 부분 문자열을 만났을 경우 그 위치를 반환한다.
1. strspn
strspn
의 원형은 다음과 같다.
size_t strspn(const char * str1, const char * str2);
str1
- 검색 대상이 되는 문자열이다.
str2
- 문자들을 열거하는 패턴pattern이다.
반환 값은 size_t
형으로서, 맨 처음 문자부터 시작하여 str2
에서 지정한 패턴을 벗어나지 않는 부분 문자열의 길이를 반환한다. 패턴에 맞는 부분 문자열이 처음부터 없다면 0
을 반환한다.
예를 들어, 문장의 첫 부분에 금액이 적혀있는 경우 이를 인식하여 따로 보관하고자 한다. 금액은 '0'
부터 '9'
까지의 숫자 문자와 '.'
, ','
, $
기호로 구성되어 있기 때문에 이 범위를 벗어난 부분 문자열이 나타날때까지 문장의 첫 글자부터 세어 나가게 한다.
/* strspn.c */
#include <stdio.h>
#include <string.h>
int main(int argc, char * argv[])
{
char str1[64] = "$1,823.55 is paid to purchase this product.";
char str2[64] = { '\0', };
char pattern[64] = "1234567890$,.";
size_t result = 0;
printf("original text: %s\n", str1);
result = strspn(str1, pattern);
if (result > 0)
{
strncpy(str2, str1, result);
printf("currency data found: \"%s\"\n", str2);
}
else
{
printf("currency data not found.\n");
}
return 0;
}
위 코드를 참조하면, result = strspn(str1, pattern);
에 의해 문자열의 맨 처음 문자로부터 주어진 패턴("123456789$,."
)을 만족하는 부분 문자열의 길이를 얻는다. 이 값은 result
변수에 보관되며 구체적으로 9
의 값("$1,823.55"
의 총 9 문자)이 보관된다.
이 값은 strncpy
함수에서 사용된다. strncpy(str2, str1, result);
에 의해 str1
의 처음 9 문자가 str2
에 복사된다. 즉, 해당 패턴을 만족하는 부분 문자열이 별도의 버퍼에 복사된 것이다. 이를 그 다음 줄인 printf
함수에서 출력하는 방식으로 본 예제는 작동한다.
1-1. Wide Character 확장 함수 - wcsspn
상기 strspn
는 ASCII 문자열 또는 UTF-8 인코딩의 Unicode 문자열에 대해 사용 가능하다. UTF-16/UTF-32와 같은 Wide Character 문자열의 경우 아래의 함수를 사용 가능하며, wchar.h
, C++에서는 cwchar
헤더를 include
한다.
size_t wcsspn(const wchar_t * str1, const wchar_t * str2);
2. strcspn
strcspn
은 지정된 패턴을 만족하지 않는 부분 문자열의 길이를 구할 때 사용한다. 원형은 다음과 같다.
size_t strcspn(const char * str1, const char * str2);
str1
- 검색 대상이 되는 문자열이다.
str2
- 문자들을 열거하는 패턴pattern이다.
실행 결과 패턴을 만족하지 않는 부분 문자열의 길이, 다시 말하면 패턴을 만족하는 부분 문자열이 시작하는 위치를 반환한다. 만일 str1
에는 str2
에서 지정한 패턴에 맞는 부분 문자열이 없을 경우 str1
의 길이를 반환한다.
상기 예제 코드에서 문자열을 수정하였다. 금액 관련한 표현이 문자열의 처음에 등장하지 않을 경우 해당 위치를 찾을 때 본 함수를 활용 가능하다.
/* strcspn.c */
#include <stdio.h>
#include <string.h>
int main(int argc, char * argv[])
{
char str1[64] = "Totol expense: $1,234.56 will be paid.";
char str2[64] = { '\0', };
char pattern[64] = "1234567890$,.";
size_t result = 0;
size_t count = 0;
printf("original text: \"%s\"\n", str1);
result = strcspn(str1, pattern);
if (result > 0)
{
printf("currency data found at %zu(th) position.\n", result);
count = strspn((str1 + result), pattern);
if (count > 0)
{
strncpy(str2, (str1 + result), count);
printf("currency data found: \"%s\"\n", str2);
}
else
{
printf("unexpected error.\n");
}
}
else
{
printf("currency data not found.\n");
}
return 0;
}
위 소스 코드를 참조하면, 찾고자 하는 패턴("1234567890$,."
)의 숫자 문자열이 문장의 중간에 위치해 있는데 정확히 몇 번째 문자부터 시작하는지를 확인하기 위하여 strcspn
을 사용한다. 이 함수는 해당 패턴이 만족하지 않는 부분 문자열의 길이를 반환하는데 이는 곧 해당 패턴이 만족하는 영역의 시작 위치이므로, result
변수에 보관한다. 구체적으로 이 값은 15
, 즉 15번째 문자부터 해당 패턴을 만족하는 부분 문자열이 존재함을 알린다. (주의: C 언어는 맨 처음 문자를 0 번째로 본다.)
if 문의 조건(result > 0
)을 만족하므로 상기 설명한 strspn
함수를 사용하여 검출하고자 하는 부분 문자열의 길이를 구한다. 이 때 매개변수로 전달되는 문자열 포인터는 str1 = &str[0]
이 아니라 (str1 + result) = &str[15]
임을 확인한다. strspn
은 문자열의 중간에서 부분 문자열을 복사하는 기능이 없으므로 strcspn
에서 구한 위치와 원본 문자열을 포인터 연산하여 해당 부분 문자열이 strspn
의 입장에서 가장 처음에 오도록 전달하는 것이다.
패턴에 맞는 부분 문자열의 시작 위치를 strcspn
을 통해 알고 있고 그 부분 문자열의 길이를 strspn
을 통해 알았다면 복사만 하면 된다. 부분 문자열의 복사는 strncpy
로 수행하는데 역시 복사 대상 문자열은 (str1 + result) = &str[15]
으로 전달되었음을 확인한다.
2-1. Wide Character 확장 함수 - wcscspn
상기 strcspn
는 ASCII 문자열 또는 UTF-8 인코딩의 Unicode 문자열에 대해 사용 가능하다. UTF-16/UTF-32와 같은 Wide Character 문자열의 경우 아래의 함수를 사용 가능하며, wchar.h
, C++에서는 cwchar
헤더를 include
한다.
size_t wcscspn(const wchar_t * str1, const wchar_t * str2);
<Epilogue>
본 포스팅을 통해 문자열 복사 함수에 대해 정리해 보았다. 다음 포스팅[libc 문자열 조작 함수 정리 (part 08 - strlen)]에서는 문자열의 길이를 구하는 함수인 strlen
함수에 대해 정리한다.