^(코딩캣)^ = @"코딩"하는 고양이;
썸네일 이미지
libc 문자열 조작 함수 정리 (part 11 - strerror) [完]
libc 문자열 조작 함수 정리 C 언어에서 문자열 처리는 복잡하다. 언어 수준에서 문자열이라는 데이터 형 자체를 지원하지도 않으니, 덧셈 기호(+)나 비교연산자(==)와 같은 기호를 사용하는 직관적인 문자열 연산을 사용할 수 없기 때문이다. C 언어가 문자열 데이터 형을 지원하지 않고, 문자열을 다루는 연산자도 없으니 모든 문자열 연산은 문자열 함수를 통해 이루어진다. C 표준 라이브러리(일명 'libc')에서 str...로 시작하는 함수들이 그것이며, 모두 string.h 헤더(C++은 cstring 헤더)에 정의되어 있으며 본 시리즈를 통해 이들 함수의 사용법을 정리해보고자 한다. 본 시리즈는 cplusplus(http://www.cplusplus.com) 및 MSDN에 나와있는 레퍼런스를 기준으로..
Language/C & C++
2018. 8. 23. 09:08

libc 문자열 조작 함수 정리 (part 11 - strerror) [完]

Language/C & C++
2018. 8. 23. 09:08

libc 문자열 조작 함수 정리


C 언어에서 문자열 처리는 복잡하다. 언어 수준에서 문자열이라는 데이터 형 자체를 지원하지도 않으니, 덧셈 기호(+)나 비교연산자(==)와 같은 기호를 사용하는 직관적인 문자열 연산을 사용할 수 없기 때문이다. C 언어가 문자열 데이터 형을 지원하지 않고, 문자열을 다루는 연산자도 없으니 모든 문자열 연산은 문자열 함수를 통해 이루어진다. C 표준 라이브러리(일명 'libc')에서 str...로 시작하는 함수들이 그것이며, 모두 string.h 헤더(C++은 cstring 헤더)에 정의되어 있으며 본 시리즈를 통해 이들 함수의 사용법을 정리해보고자 한다. 본 시리즈는 cplusplus(http://www.cplusplus.com) 및 MSDN에 나와있는 레퍼런스를 기준으로 하여 작성되었다.

  1. libc 문자열 조작 함수 정리 (part 01 - strcpy, strncpy)
  2. libc 문자열 조작 함수 정리 (part 02 - strcat, strncat)
  3. libc 문자열 조작 함수 정리 (part 03 - strcmp, strncmp)
  4. libc 문자열 조작 함수 정리 (part 04 - strchr, strrchr)
  5. libc 문자열 조작 함수 정리 (part 05 - strstr)
  6. libc 문자열 조작 함수 정리 (part 06 - strtok)
  7. libc 문자열 조작 함수 정리 (part 07 - strspn, strcspn)
  8. libc 문자열 조작 함수 정리 (part 08 - strlen)
  9. libc 문자열 조작 함수 정리 (part 09 - strpbrk)
  10. libc 문자열 조작 함수 정리 (part 10 - strxfrm, strcoll)
  11. libc 문자열 조작 함수 정리 (part 11 - strerror)

Part XI. strerror


이번 포스팅에서는 가장 최근에 발생한 오류 내용을 확인할 때 사용하는 함수인 strerror 함수에 대해 정리한다.

1. strerror


strerror 함수의 원형은 다음과 같이 정의되어 있다.

char * strerror(int errnum);
errnum
오류 번호이다. 이 값에 따라 각기 다른 오류 내용을 볼 수 있다. 가장 최근에 발생한 오류의 고유번호를 알고자 한다면 errno.h 헤더에 정의되어 있는 errno 전역 식별자를 여기에 전달하면 된다.

다음은 strerror 함수의 사용 예이다.

/* strerror.c */
#include <stdio.h>
#include <string.h>
#include <errno.h>                                         // identifier 'errno'

int main(int argc, char * argv[])
{
	FILE * fp = NULL;
	
	if ((fp = fopen("NotExists", "r")) != NULL)
	{
		printf("File Exists.\n");                         // File Exists
		fclose(fp); 
	}
	else
	{
		printf("File NOT Exists.\n");                      // File Error
		printf("\"%s\"\n", strerror(errno));
	}

	return 0;
}
[그림 1] strerror.c 예제 소스 코드
[그림 2] strerror.c 예제 소스 코드의 실행 결과

존재 하지 않는 이름("NotExists")의 파일을 fopen 함수를 통해 열려고 하였다. 당연히 fopen 함수는 NULL을 반환하지만 한편으로는 전역변수 errno에 오류 코드를 설정한다. 이 오류 코드는 정수(int)형인데 구체적으로 사용자가 읽을 수 있는 텍스트로써 어떤 내용인지를 보고자 할 때 strerror 함수를 사용하여 문자열 형태로 출력하고 있음을 확인할 수 있다.

1-1. Wide Character 확장 함수 - _wcserror


현재 버전의 표준 C 라이브러리에는 wchar 버전의 strerror 함수가 정의되어 있지 않다. Visual Studio 사용자는 UTF-16/UTF-32와 같은 Wide Character 문자열 형식에 대해 위하여 다음의 함수를 사용 가능하다.

wchar_t * _wcserror(int errnum);

<Epilogue>


본 포스팅을 통해 문자열 비교 함수에 대해 정리해 보았다. 이것으로 C 표준 라이브러리(libc)에서 제공하는 문자열 조작 함수(strXXX)에 대한 정리를 모두 마친다.

- 끝 -

카테고리 “Language/C & C++”
more...
썸네일 이미지
libc 문자열 조작 함수 정리 (part 10 - strxfrm, strcoll)
libc 문자열 조작 함수 정리 C 언어에서 문자열 처리는 복잡하다. 언어 수준에서 문자열이라는 데이터 형 자체를 지원하지도 않으니, 덧셈 기호(+)나 비교연산자(==)와 같은 기호를 사용하는 직관적인 문자열 연산을 사용할 수 없기 때문이다. C 언어가 문자열 데이터 형을 지원하지 않고, 문자열을 다루는 연산자도 없으니 모든 문자열 연산은 문자열 함수를 통해 이루어진다. C 표준 라이브러리(일명 'libc')에서 str...로 시작하는 함수들이 그것이며, 모두 string.h 헤더(C++은 cstring 헤더)에 정의되어 있으며 본 시리즈를 통해 이들 함수의 사용법을 정리해보고자 한다. 본 시리즈는 cplusplus(http://www.cplusplus.com) 및 MSDN에 나와있는 레퍼런스를 기준으로..
Language/C & C++
2018. 8. 21. 23:41

libc 문자열 조작 함수 정리 (part 10 - strxfrm, strcoll)

Language/C & C++
2018. 8. 21. 23:41

libc 문자열 조작 함수 정리


C 언어에서 문자열 처리는 복잡하다. 언어 수준에서 문자열이라는 데이터 형 자체를 지원하지도 않으니, 덧셈 기호(+)나 비교연산자(==)와 같은 기호를 사용하는 직관적인 문자열 연산을 사용할 수 없기 때문이다. C 언어가 문자열 데이터 형을 지원하지 않고, 문자열을 다루는 연산자도 없으니 모든 문자열 연산은 문자열 함수를 통해 이루어진다. C 표준 라이브러리(일명 'libc')에서 str...로 시작하는 함수들이 그것이며, 모두 string.h 헤더(C++은 cstring 헤더)에 정의되어 있으며 본 시리즈를 통해 이들 함수의 사용법을 정리해보고자 한다. 본 시리즈는 cplusplus(http://www.cplusplus.com) 및 MSDN에 나와있는 레퍼런스를 기준으로 하여 작성되었다.

  1. libc 문자열 조작 함수 정리 (part 01 - strcpy, strncpy)
  2. libc 문자열 조작 함수 정리 (part 02 - strcat, strncat)
  3. libc 문자열 조작 함수 정리 (part 03 - strcmp, strncmp)
  4. libc 문자열 조작 함수 정리 (part 04 - strchr, strrchr)
  5. libc 문자열 조작 함수 정리 (part 05 - strstr)
  6. libc 문자열 조작 함수 정리 (part 06 - strtok)
  7. libc 문자열 조작 함수 정리 (part 07 - strspn, strcspn)
  8. libc 문자열 조작 함수 정리 (part 08 - strlen)
  9. libc 문자열 조작 함수 정리 (part 09 - strpbrk)
  10. libc 문자열 조작 함수 정리 (part 10 - strxfrm, strcoll)
  11. libc 문자열 조작 함수 정리 (part 11 - strerror)

Part X. strxfrm, strcoll


이번 포스팅에서는 시스템 로케일 설정에 따라 문자열을 변환하고 비교할 목적으로 사용되는 함수인 strxfrmstrcoll 함수에 대해 정리한다.

1. strxfrm


strxfrm 함수는 시스템 로케일 설정에 따라 문자열을 변환transform하여 버퍼에 복사하고 변환된 문자열의 길이를 반환하는 함수이다. 여기서 변환이란 시스템 로케일에서 정의한 문자열 변환작업을 의미하는데 구체적으로 무엇을 어떻게 변환하는지에 대해서는 명확하게 정의된 것이 없다. 다만, 변환된 문자열은 일종의 해시hash로서 취급되며 strcmp 함수에 의한 일치 또는 순서가 본래의 문자열과 일치함은 보장한다.

strxfrm 함수의 원형은 다음과 같다.

size_t strxfrm(char * destination, const char * source, size_t num);
destination
변환된 문자열이 복사될 문자열 버퍼이다.
source
변환할 문자열이 보관된 상수 또는 문자열 버퍼이다.
num
destination 버퍼가 보관 가능한 최대 문자 수이다.

함수의 수행 결과 현재 시스템 로케일 조건에서 원본 문자열로부터 변환된 문자열이 destination으로 지정한 문자열 버퍼에 복사되고 이 버퍼에 복사된 문자 수가 반환된다.

다음은 strxfrm 함수의 사용 예이다. macOS(10.13.6 High Sierra 기준) 및 FreeBSD에서는 로케일 기능을 구현하는 부분에서 버그가 존재하기 때문에 아래 소스 코드에 의한 결과가 다를 수 있다. 그 결과는 신뢰할 수 없으므로 가급적 macOSFreeBSD를 제외한 운영체제에서 실행해보기를 권장한다.

/* strxfrm.c */
#include <stdio.h>
#include <string.h>
#include <locale.h>

int main(int argc, char * argv[])
{
    char str1[512] = "hlava";
    char str2[512] = "číšník";
    char xfm1[512] = { '\0', };
    char xfm2[512] = { '\0', };
    char * result = NULL;
    size_t lxfm1 = 0;
    size_t lxfm2 = 0;

    lxfm1 = strxfrm(xfm1, str1, sizeof xfm1);
    lxfm2 = strxfrm(xfm2, str2, sizeof xfm2);
    if ((lxfm1 > 0) && (lxfm2 > 0))
    {
        printf("<Locale Unset>\n");
        printf("setlocale = \"%s\"\n", (result == NULL) ? "NULL" : result);
        printf("str1: \"%s\" --> \"%s\"\n", str1, xfm1);
        printf("str2: \"%s\" --> \"%s\"\n", str2, xfm2);
        printf("strcmp(str1, str2) = %d\n", strcmp(str1, str2));
        printf("strcmp(xfm1, xfm2) = %d\n", strcmp(xfm1, xfm2));
        printf("returns of strxfrm: %zu / %zu\n", lxfm1, lxfm2);
    }

    result = setlocale(LC_ALL, "cs_CZ.UTF-8");
    lxfm1 = strxfrm(xfm1, str1, sizeof xfm1);
    lxfm2 = strxfrm(xfm2, str2, sizeof xfm2);
    if ((lxfm1 > 0) && (lxfm2 > 0))
    {
        printf("<cs-CZ.UTF-8>\n");
        printf("setlocale = \"%s\"\n", result);
        printf("str1: \"%s\" --> \"%s\"\n", str1, xfm1);
        printf("str2: \"%s\" --> \"%s\"\n", str2, xfm2);
        printf("strcmp(str1, str2) = %d\n", strcmp(str1, str2));
        printf("strcmp(xfm1, xfm2) = %d\n", strcmp(xfm1, xfm2));
        printf("returns of strxfrm: %zu / %zu\n", lxfm1, lxfm2);
    }

    return 0;
}
[그림 1] strxfrm.c 예제 소스 코드
[그림 2] strxfrm.c 예제 소스 코드의 실행 결과

위 코드는 체코어 단어인 "hlava""číšník"의 순서를 비교하는 예이다. 두 단어는 각각 str1str2에 UTF-8 인코딩으로 보관되어 있다. (단, unix 일때에 한함.) Microsoft Windows 등의 운영체제를 고려하여 확실하게 UTF-8 인코딩으로 문자열 상수를 보관하기 위해 str1str2의 상수 할당을 다음과 같이 지정해도 좋다.

/* strxfrm.c: alternate */
char str1[] = { 0x68, 0x6C, 0x61, 0x76, 0x61, 0x00 }; // hlava
char str2[] = { 0xC4, 0x8D, 0xC3, 0xAD, 0xC5, 0xA1, 0x6E, 0xC3, 0xAD, x6B, 0x00 }; // číšník

보통의 소문자 'c'의 유니코드는 U+0063이고, 카론caron이 붙은 소문자 'č'의 유니코드는 U+010D이다. 또한 보통의 소문자 'h'의 유니코드는 U+0068이다. 유니코드에 의한 단순 정렬 시,

'c' (U+0063) - 'h' (U+0068) - 'č' (U+010D)

가 되겠지만 체코어 알파벳의 순서대로 문자를 정렬할 경우,

'c' (U+0063) - 'č' (U+010D) - 'h' (U+0068)

의 순서로 정렬된다. strxfrm은 특정 언어로 적힌 문자열을 strcmp로 순서 비교할 때 이러한 문화권(로케일) 차이를 반영하여 해당 언어의 사전 순서대로 정렬할 수 있도록 특별한 패턴의 문자열을 생성하는 역할을 한다. 다시 말하면, strcmp로 순서 비교하고자 할 때 여기에 들어갈 문자열은 "hlava""číšník" 등의 원본 문자열이 아니고, strxfrm을 통해 변환된 문자열(일종의 해시hash)이어야 한다는 것이다.

첫 번째 실험인 <Locale Unset>항목을 본다.

아직 로케일을 명시하지 않은 상태이기 때문에 모든 문자열은 단순히 유니코드에 등재된 순서대로 비교 연산을 수행한다. 그렇기 때문에 strxfrm 함수는 문자열 버퍼에 원본 문자열 그대로를 복사하고 strcmp 함수는 원본 문자열 그대로 비교 연산을 수행한다. 앞서 설명한 대로 유니코드에 의한 단순 정렬 시 보통의 라틴문자인 'h'가 확장 라틴문자인 'č'에 선행하기 때문에(우선하기 때문에) strcmp("hlava", "číšník");의 결과 음수가 반환된다. strcmp의 반환값에 대한 설명은 [libc 문자열 조작 함수 정리 (part 03 - strcmp, strncmp)]를 참고한다.

두 번째 실험인 <cs_CZ.UTF-8>항목을 본다.

setlocale 함수를 사용하여 로케일이 설정된 상태이므로 체코어 알파벳 순서에 따라 문자열의 비교가 가능하다. 로케일이 설정된 상태에서 strxfrm 함수는 문자열 버퍼에 변환된 문자열을 만든다. 각 문자열은 "hlava""číšník"로부터 얻어진 일종의 해시이기 때문에 읽을 수 있는 문자열은 아니지만 해당 문자열을 대신하여 strcmp 함수에 의한 우선순위 또는 일치 여부를 확인하는데 사용될 수 있다.

위와 같이 얻어진 문자열을 strcmp 함수에 적용해 보자. 로케일을 설정하기 전에는 'h''č'에 선행한다고 보아 음수를 반환하였는데, 로케일을 설정한 후에는 'č''h'에 선행한다고 보아서 양수를 반환하는 것을 볼 수 있다.

좀 더 확인하기 위하여 여러 종류의 로케일에 대해 문자열을 비교해보도록 한다. 위의 코드 중 setlocale에 전달되는 "cz_CS.UTF-8" 부분을 "문자열이 UTF-8로 인코드된 미국 영어 로케일"(en_US.UTF-8)과 "문자열이 UTF-8로 인코드된 한국어 로케일"(ko_KR.UTF-8)로 설정하였을 때 결과는 각각 다음과 같이 나올 것이다. (Ubuntu 기준)

########## terminal ##########
<ko_KR.UTF-8>
setlocale = "ko_KR.UTF-8"
str1: "hlava" --> "hlava"
str2: "číšník" --> "číšník"
strcmp(str1, str2) = -92
strcmp(xfm1, xfm2) = -92
returns of strxfrm: 5 / 10

<en_US.UTF-8>
setlocale = "en_US.UTF-8"
str1: "hlava" --> (garbage)
str2: "číšník" --> (garbage)
strcmp(str1, str2) = -92
strcmp(xfm1, xfm2) = 5
returns of strxfrm: 17 / 20

미국 영어 로케일(en_US)도 체코어와 같은 로마자를 사용하므로 문자 'č''c' 계열의 문자로 간주하여 'h'보다는 앞 순서로 판별하도록 strxfrm에서 문자열 변환이 이루어진다. 그러므로 strcmp(strxfrm("hlava"), strxfrm("číšník"));의 결과 양수가 반환된다.

한국어 로케일(ko_KR) 조건에서는 로마자 문화권이 아닌 상태가 되므로 'č' 문자를 인식하지 않아 단순 유니코드 값대로 순서가 판단되도록 strxfrm에서 문자열 변환이 일어나지 않는다. 그러므로 strcmp(strxfrm("hlava"), strxfrm("číšník"));의 결과 음수가 반환됨을 확인할 수 있다.

참고로 유닉스(리눅스)에서 현재 시스템이 지원 가능한 로케일의 목록을 확인하는 방법은 다음과 같다.

$ locale -a

로케일 관련된 파일들은 대체로 /usr/share/locale 디렉터리에 정의되어 있다. Debian(Ubuntu) 계열의 운영체제에서 특정 로케일을 설치하고자 할 경우 다음과 같이 실행한다.

예를 들어 한국어 로케일(ko-KR)을 생성하고자 할 경우,

$ sudo locale-gen ko_KR

그리고 EUC-KR 인코딩을 지원하는 한국어 로케일을 추가하고자 할 경우,

$ sudo locale-gen ko_KR.EUC-KR

1-1. Wide Character 확장 함수 - wcsxfrm


상기 strxfrm는 ASCII 문자열 또는 UTF-8 인코딩의 Unicode 문자열에 대해 사용 가능하다. UTF-16/UTF-32와 같은 Wide Character 문자열의 복사는 아래의 함수를 사용 가능하며, wchar.h, C++에서는 cwchar 헤더를 include한다.

size_t wcsxfrm(wchar_t * destination, const wchar_t * source, size_t num);

2. strcoll


함수의 원형은 다음과 같이 정의되어 있다.

int strcoll(const char * str1, const char * str2);
str1
현지 언어로 적힌 첫번째 문자열이다.
str2
현지 언어로 적힌 두번째 문자열이다.

strcoll 함수는 strxfrm 함수와 strcmp 함수를 합친 함수로서, 현재 설정된 로케일에 의한 문자열 비교 연산을 수행한다. 즉 변환 문자열을 담기 위한 버퍼의 선언과 변환 문자열의 복사는 함수 내부적으로 알아서 수행되므로 strcmp 함수를 사용할 때와 같은 방식으로 원본 문자열만 직접 전달해주면 비교 연산 결과를 반환한다. 문자열 비교 연산의 결과에 대한 정리는 [libc 문자열 조작 함수 정리 (part 03 - strcmp, strncmp)]를 참고한다.

앞서 예시로 적은 소스 코드를 strcoll 함수를 사용할 경우 다음과 같이 코드 분량을 줄이면서 현지 언어 문자열 비교를 할 수 있다.

/* strcoll.c */
#include <stdio.h>
#include <string.h>
#include <locale.h>

int main(int argc, char * argv[])
{
    char str1[512] = "hlava";
    char str2[512] = "číšník";
    char * result = NULL;

    printf("<Locale Unset>\n");
    printf("setlocale = \"%s\"\n", (result == NULL) ? "NULL" : result);
    printf("strcoll(\"%s\", \"%s\") = %d\n", str1, str2, strcoll(str1, str2));

    printf("\n");

    result = setlocale(LC_ALL, "cs_CZ.UTF-8");
    printf("<cs-CZ.UTF-8>\n");
    printf("setlocale = \"%s\"\n", (result == NULL) ? "NULL" : result);
    printf("strcoll(\"%s\", \"%s\") = %d\n", str1, str2, strcoll(str1, str2));

    return 0;
}
[그림 3] strcoll.c 예제 소스 코드
[그림 4] strcoll.c 예제 소스 코드의 실행 결과

마찬가지로 두 문자열에 대해 로케일을 적용하기 전의 문자열 비교 결과와 로케일 적용 후의 문자열 비교 결과가 서로 다름을 알 수 있다. 로케일을 적용하기 전에는 문자열을 단순 유니코드 순으로 정렬하므로 "hlava""číšník"에 선행한다고 보아 음수를 반환하지만, 로케일을 적용한 후에는 확장 라틴 문자 또한 해당 언어의 알파벳 순서대로 비교하므로 "číšník""hlava"에 선행한다고 보아 strcoll("hlava", "číšník");는 양수를 반환한다.

2-1. Wide Character 확장 함수 - wcscoll


상기 strcoll은 ASCII 문자열 또는 UTF-8 인코딩의 Unicode 문자열에 대해 사용 가능하다. UTF-16/UTF-32와 같은 Wide Character 문자열의 복사는 아래의 함수를 사용 가능하며, wchar.h, C++에서는 cwchar 헤더를 include한다.

int wcscoll(const wchar_t * wcs1, const wchar_t * wcs2);

<Epilogue>


본 포스팅을 통해 문자열 비교 함수에 대해 정리해 보았다. 다음 포스팅[libc 문자열 조작 함수 정리 (part 11 - strerror)]에서는 가장 마지막에 발생한 오류의 내용을 구할 수 있는 strerror 함수에 대해 정리한다.

카테고리 “Language/C & C++”
more...
썸네일 이미지
libc 문자열 조작 함수 정리 (part 09 - strpbrk)
libc 문자열 조작 함수 정리 C 언어에서 문자열 처리는 복잡하다. 언어 수준에서 문자열이라는 데이터 형 자체를 지원하지도 않으니, 덧셈 기호(+)나 비교연산자(==)와 같은 기호를 사용하는 직관적인 문자열 연산을 사용할 수 없기 때문이다. C 언어가 문자열 데이터 형을 지원하지 않고, 문자열을 다루는 연산자도 없으니 모든 문자열 연산은 문자열 함수를 통해 이루어진다. C 표준 라이브러리(일명 'libc')에서 str...로 시작하는 함수들이 그것이며, 모두 string.h 헤더(C++은 cstring 헤더)에 정의되어 있으며 본 시리즈를 통해 이들 함수의 사용법을 정리해보고자 한다. 본 시리즈는 cplusplus(http://www.cplusplus.com) 및 MSDN에 나와있는 레퍼런스를 기준으로..
Language/C & C++
2018. 8. 21. 15:57

libc 문자열 조작 함수 정리 (part 09 - strpbrk)

Language/C & C++
2018. 8. 21. 15:57

libc 문자열 조작 함수 정리


C 언어에서 문자열 처리는 복잡하다. 언어 수준에서 문자열이라는 데이터 형 자체를 지원하지도 않으니, 덧셈 기호(+)나 비교연산자(==)와 같은 기호를 사용하는 직관적인 문자열 연산을 사용할 수 없기 때문이다. C 언어가 문자열 데이터 형을 지원하지 않고, 문자열을 다루는 연산자도 없으니 모든 문자열 연산은 문자열 함수를 통해 이루어진다. C 표준 라이브러리(일명 'libc')에서 str...로 시작하는 함수들이 그것이며, 모두 string.h 헤더(C++은 cstring 헤더)에 정의되어 있으며 본 시리즈를 통해 이들 함수의 사용법을 정리해보고자 한다. 본 시리즈는 cplusplus(http://www.cplusplus.com) 및 MSDN에 나와있는 레퍼런스를 기준으로 하여 작성되었다.

  1. libc 문자열 조작 함수 정리 (part 01 - strcpy, strncpy)
  2. libc 문자열 조작 함수 정리 (part 02 - strcat, strncat)
  3. libc 문자열 조작 함수 정리 (part 03 - strcmp, strncmp)
  4. libc 문자열 조작 함수 정리 (part 04 - strchr, strrchr)
  5. libc 문자열 조작 함수 정리 (part 05 - strstr)
  6. libc 문자열 조작 함수 정리 (part 06 - strtok)
  7. libc 문자열 조작 함수 정리 (part 07 - strspn, strcspn)
  8. libc 문자열 조작 함수 정리 (part 08 - strlen)
  9. libc 문자열 조작 함수 정리 (part 09 - strpbrk)
  10. libc 문자열 조작 함수 정리 (part 10 - strxfrm, strcoll)
  11. libc 문자열 조작 함수 정리 (part 11 - strerror)

Part IX. strpbrk


본 포스팅에서는 문자열에서 미리 열거된 문자들 중 하나를 검색pointer break하는 함수인 strpbrk 함수에 대해 정리한다.

1. strpbrk


C++ 라이브러리에서 제공하는 헤더 파일인 cstring에서는 검색 대상 문자열의 상수성 여부에 따라 2개의 함수가 오버로드overload되어 있다.

const char * strpbrk(const char * str1, const char * str2);
char * strpbrk(char * str1, const char * str2);

C 라이브러리에서 제공하는 헤더 파일인 string.h에서는 하나의 함수만이 정의되어 있다.

char * strpbrk(const char * str1, const char * str2);
str1
검색 대상 본문이 보관된 문자열 버퍼이다.
str2
검색할 문자들을 열거하는 문자열 상수이다.

다음은 문자열로부터 숫자의 개수를 세는 예이다.

/* strpbrk.c */
#include <stdio.h>
#include <string.h>

int main(int argc, char * argv[])
{
	char str1[512] =
		"L is for the way you look at me. "
		"O is for the only one I see. "
		"V is very, very extraordinary. "
		"E is even more than anyone that you adore.";
	char str2[] = "ELOV";
	char * result = NULL;

	printf("Original String: \n\"%s\"\n", str1);
	printf("****************************************\n");
	
	result = strpbrk(str1, str2);
	while (result != NULL)
	{
		printf("\"%s\"\n", result);
		result = strpbrk(result + 1, str2);
	}

	return 0;
}
[그림 1] strpbrk.c 예제 소스 코드
[그림 2] strpbrk.c 예제 소스 코드의 실행 결과

위 코드를 참조하면, 원본 문자열로부터 'E', 'L', 'O', 'V'로 시작하는 부분 문자열을 구하게 된다. 원본 문자열은 대문자로 시작하는 5개의 문장으로 구성되어 있고 이 문자열에 strpbrk를 적용하여 [그림 2]의 결과를 볼 수 있다. strpbrk의 두 번째 매개변수(str2)에는 'E', 'L', 'O', 'V'의 4개 문자만이 지정되어 있어 각 문자로 시작되는 부분 문자열을 얻을 수 있었지만, 'A'는 지정되지 않았으므로 마지막 문장은 출력되지 않음을 알 수 있다.

1-1. Wide Character 확장 함수 - wcspbrk


상기 strpbrk는 ASCII 문자열 또는 UTF-8 인코딩의 Unicode 문자열에 대해 사용 가능하다. UTF-16/UTF-32와 같은 Wide Character 문자열의 복사는 아래의 함수를 사용 가능하며, wchar.h, C++에서는 cwchar 헤더를 include한다.

C++ 헤더인 cwchar에는 상수성 여부에 따라 다음의 두 함수가 오버로드되어 있다.

const wchar_t * wcspbrk(const wchar_t * wcs1, const wchar_t * wcs2);
wchar_t * wcspbrk(wchar_t * wcs1, const wchar_t * wcs2);

C 헤더인 wchar.h에는 하나의 함수만이 정의되어 있다.

wchar_t * wcspbrk(const wchar_t * str2, const wchar_t * str2);
카테고리 “Language/C & C++”
more...
썸네일 이미지
libc 문자열 조작 함수 정리 (part 08 - strlen)
libc 문자열 조작 함수 정리 C 언어에서 문자열 처리는 복잡하다. 언어 수준에서 문자열이라는 데이터 형 자체를 지원하지도 않으니, 덧셈 기호(+)나 비교연산자(==)와 같은 기호를 사용하는 직관적인 문자열 연산을 사용할 수 없기 때문이다. C 언어가 문자열 데이터 형을 지원하지 않고, 문자열을 다루는 연산자도 없으니 모든 문자열 연산은 문자열 함수를 통해 이루어진다. C 표준 라이브러리(일명 'libc')에서 str...로 시작하는 함수들이 그것이며, 모두 string.h 헤더(C++은 cstring 헤더)에 정의되어 있으며 본 시리즈를 통해 이들 함수의 사용법을 정리해보고자 한다. 본 시리즈는 cplusplus(http://www.cplusplus.com) 및 MSDN에 나와있는 레퍼런스를 기준으로..
Language/C & C++
2018. 8. 21. 13:39

libc 문자열 조작 함수 정리 (part 08 - strlen)

Language/C & C++
2018. 8. 21. 13:39

libc 문자열 조작 함수 정리


C 언어에서 문자열 처리는 복잡하다. 언어 수준에서 문자열이라는 데이터 형 자체를 지원하지도 않으니, 덧셈 기호(+)나 비교연산자(==)와 같은 기호를 사용하는 직관적인 문자열 연산을 사용할 수 없기 때문이다. C 언어가 문자열 데이터 형을 지원하지 않고, 문자열을 다루는 연산자도 없으니 모든 문자열 연산은 문자열 함수를 통해 이루어진다. C 표준 라이브러리(일명 'libc')에서 str...로 시작하는 함수들이 그것이며, 모두 string.h 헤더(C++은 cstring 헤더)에 정의되어 있으며 본 시리즈를 통해 이들 함수의 사용법을 정리해보고자 한다. 본 시리즈는 cplusplus(http://www.cplusplus.com) 및 MSDN에 나와있는 레퍼런스를 기준으로 하여 작성되었다.

  1. libc 문자열 조작 함수 정리 (part 01 - strcpy, strncpy)
  2. libc 문자열 조작 함수 정리 (part 02 - strcat, strncat)
  3. libc 문자열 조작 함수 정리 (part 03 - strcmp, strncmp)
  4. libc 문자열 조작 함수 정리 (part 04 - strchr, strrchr)
  5. libc 문자열 조작 함수 정리 (part 05 - strstr)
  6. libc 문자열 조작 함수 정리 (part 06 - strtok)
  7. libc 문자열 조작 함수 정리 (part 07 - strspn, strcspn)
  8. libc 문자열 조작 함수 정리 (part 08 - strlen)
  9. libc 문자열 조작 함수 정리 (part 09 - strpbrk)
  10. libc 문자열 조작 함수 정리 (part 10 - strxfrm, strcoll)
  11. libc 문자열 조작 함수 정리 (part 11 - strerror)

Part IIX. strlen


본 포스팅에서는 문자열의 길이length을 구하는 함수인 strlen 함수에 대해 정리한다.

<Prologue>


strlen은 C 스타일 문자열(맨 끝에 NULL ('\0')이 붙는 문자열)의 길이를 구하는 함수이다. 즉 NULL ('\0') 문자 직전의 문자까지만 센다. 예를 들어, 문자열 "Hello" = {'H', 'e', 'l', 'l', 'o', '\0'}의 경우 NULL ('\0') 문자를 제외한 5글자('H', 'e', 'l', 'l', 'o')만을 센다.

1. strlen


strlen의 원형은 다음과 같다.

size_t strlen(const char * str);

NULL문자를 만날때까지 문자를 하나씩 센다. 함수가 종료될 때 이 문자 수를 반환한다. 이 때 문자열 버퍼를 구성하는 NULL 문자는 개수에 포함되지 않는다. 메모리를 할당할 때 이를 고려하여 버퍼의 크기를 1개 문자 더 많게 설정해야 할 것이다.

다음은 strlen으로 문자열 버퍼에서 문자의 수를 세는 예시이다.

/* strlen.c */
#include <stdio.h>
#include <string.h>

int main(int argc, char * argv[])
{
	char str[64] = "Hello, World!";
	size_t length = 0;

	length = strlen(str);

	printf("original text: \"%s\" (%zu characters).\n", str, length);

	return 0;
}
[그림 1] strlen.c 예제 소스 코드
[그림 2] strlen.c 예제 소스 코드의 실행 결과

2-1. Wide Character 확장 함수 - wcslen


상기 strlen는 ASCII 문자열 또는 UTF-8 인코딩의 Unicode 문자열에 대해 사용 가능하다. UTF-16/UTF-32와 같은 Wide Character 문자열의 경우 아래의 함수를 사용 가능하며, wchar.h, C++에서는 cwchar 헤더를 include한다.

size_t wcslen(const wchar_t * wcs);

<Epilogue>


본 포스팅을 통해 문자열 복사 함수에 대해 정리해 보았다. 다음 포스팅[libc 문자열 조작 함수 정리 (part 09 - strpbrk)]에서는 특정 문자의 위치를 반환하는 함수인 strpbrk에 대해 정리한다.

카테고리 “Language/C & C++”
more...
썸네일 이미지
libc 문자열 조작 함수 정리 (part 07 - strspn, strcspn)
libc 문자열 조작 함수 정리 C 언어에서 문자열 처리는 복잡하다. 언어 수준에서 문자열이라는 데이터 형 자체를 지원하지도 않으니, 덧셈 기호(+)나 비교연산자(==)와 같은 기호를 사용하는 직관적인 문자열 연산을 사용할 수 없기 때문이다. C 언어가 문자열 데이터 형을 지원하지 않고, 문자열을 다루는 연산자도 없으니 모든 문자열 연산은 문자열 함수를 통해 이루어진다. C 표준 라이브러리(일명 'libc')에서 str...로 시작하는 함수들이 그것이며, 모두 string.h 헤더(C++은 cstring 헤더)에 정의되어 있으며 본 시리즈를 통해 이들 함수의 사용법을 정리해보고자 한다. 본 시리즈는 cplusplus(http://www.cplusplus.com) 및 MSDN에 나와있는 레퍼런스를 기준으로..
Language/C & C++
2018. 8. 20. 20:53

libc 문자열 조작 함수 정리 (part 07 - strspn, strcspn)

Language/C & C++
2018. 8. 20. 20:53

libc 문자열 조작 함수 정리


C 언어에서 문자열 처리는 복잡하다. 언어 수준에서 문자열이라는 데이터 형 자체를 지원하지도 않으니, 덧셈 기호(+)나 비교연산자(==)와 같은 기호를 사용하는 직관적인 문자열 연산을 사용할 수 없기 때문이다. C 언어가 문자열 데이터 형을 지원하지 않고, 문자열을 다루는 연산자도 없으니 모든 문자열 연산은 문자열 함수를 통해 이루어진다. C 표준 라이브러리(일명 'libc')에서 str...로 시작하는 함수들이 그것이며, 모두 string.h 헤더(C++은 cstring 헤더)에 정의되어 있으며 본 시리즈를 통해 이들 함수의 사용법을 정리해보고자 한다. 본 시리즈는 cplusplus(http://www.cplusplus.com) 및 MSDN에 나와있는 레퍼런스를 기준으로 하여 작성되었다.

  1. libc 문자열 조작 함수 정리 (part 01 - strcpy, strncpy)
  2. libc 문자열 조작 함수 정리 (part 02 - strcat, strncat)
  3. libc 문자열 조작 함수 정리 (part 03 - strcmp, strncmp)
  4. libc 문자열 조작 함수 정리 (part 04 - strchr, strrchr)
  5. libc 문자열 조작 함수 정리 (part 05 - strstr)
  6. libc 문자열 조작 함수 정리 (part 06 - strtok)
  7. libc 문자열 조작 함수 정리 (part 07 - strspn, strcspn)
  8. libc 문자열 조작 함수 정리 (part 08 - strlen)
  9. libc 문자열 조작 함수 정리 (part 09 - strpbrk)
  10. libc 문자열 조작 함수 정리 (part 10 - strxfrm, strcoll)
  11. libc 문자열 조작 함수 정리 (part 11 - strerror)

Part VII. strspn, strcspn


본 포스팅에서는 전체 문자열 중에서 특정 범위의 문자로만 구성된 부분 문자열span을 구하는 함수인 strspnstrcspn 함수에 대해 정리한다.

<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;
}
[그림 1] strspn.c 예제 소스 코드
[그림 2] strspn.c 예제 소스 코드의 실행 결과

위 코드를 참조하면, 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;
}
[그림 1] strcspn.c 예제 소스 코드
[그림 2] strcspn.c 예제 소스 코드의 실행 결과

위 소스 코드를 참조하면, 찾고자 하는 패턴("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 함수에 대해 정리한다.

카테고리 “Language/C & C++”
more...
썸네일 이미지
libc 문자열 조작 함수 정리 (part 06 - strtok)
libc 문자열 조작 함수 정리 C 언어에서 문자열 처리는 복잡하다. 언어 수준에서 문자열이라는 데이터 형 자체를 지원하지도 않으니, 덧셈 기호(+)나 비교연산자(==)와 같은 기호를 사용하는 직관적인 문자열 연산을 사용할 수 없기 때문이다. C 언어가 문자열 데이터 형을 지원하지 않고, 문자열을 다루는 연산자도 없으니 모든 문자열 연산은 문자열 함수를 통해 이루어진다. C 표준 라이브러리(일명 'libc')에서 str...로 시작하는 함수들이 그것이며, 모두 string.h 헤더(C++은 cstring 헤더)에 정의되어 있으며 본 시리즈를 통해 이들 함수의 사용법을 정리해보고자 한다. 본 시리즈는 cplusplus(http://www.cplusplus.com) 및 MSDN에 나와있는 레퍼런스를 기준으로..
Language/C & C++
2018. 8. 20. 19:14

libc 문자열 조작 함수 정리 (part 06 - strtok)

Language/C & C++
2018. 8. 20. 19:14

libc 문자열 조작 함수 정리


C 언어에서 문자열 처리는 복잡하다. 언어 수준에서 문자열이라는 데이터 형 자체를 지원하지도 않으니, 덧셈 기호(+)나 비교연산자(==)와 같은 기호를 사용하는 직관적인 문자열 연산을 사용할 수 없기 때문이다. C 언어가 문자열 데이터 형을 지원하지 않고, 문자열을 다루는 연산자도 없으니 모든 문자열 연산은 문자열 함수를 통해 이루어진다. C 표준 라이브러리(일명 'libc')에서 str...로 시작하는 함수들이 그것이며, 모두 string.h 헤더(C++은 cstring 헤더)에 정의되어 있으며 본 시리즈를 통해 이들 함수의 사용법을 정리해보고자 한다. 본 시리즈는 cplusplus(http://www.cplusplus.com) 및 MSDN에 나와있는 레퍼런스를 기준으로 하여 작성되었다.

  1. libc 문자열 조작 함수 정리 (part 01 - strcpy, strncpy)
  2. libc 문자열 조작 함수 정리 (part 02 - strcat, strncat)
  3. libc 문자열 조작 함수 정리 (part 03 - strcmp, strncmp)
  4. libc 문자열 조작 함수 정리 (part 04 - strchr, strrchr)
  5. libc 문자열 조작 함수 정리 (part 05 - strstr)
  6. libc 문자열 조작 함수 정리 (part 06 - strtok)
  7. libc 문자열 조작 함수 정리 (part 07 - strspn, strcspn)
  8. libc 문자열 조작 함수 정리 (part 08 - strlen)
  9. libc 문자열 조작 함수 정리 (part 09 - strpbrk)
  10. libc 문자열 조작 함수 정리 (part 10 - strxfrm, strcoll)
  11. libc 문자열 조작 함수 정리 (part 11 - strerror)

Part VI. strtok


본 포스팅에서는 특정 기호를 기준으로 문자열 분할tokenization을 지원하는 함수인 strtok 계열의 함수에 대해 사용 예를 정리한다.

<Prologue>


strtok은 지정된 문자를 기준으로 문자열을 자르는 역할을 한다. 예를 들어 문자열 중에 ';' 문자가 있다면 그 문자 직전까지를 하나의 문자열로 보고, 그 문자 직후부터를 또 하나의 문자열로 취급한다는 뜻이다. 이 때 strtok 함수는 해당 문자열에서 ';' 문자가 있던 자리를 NULL 문자로 치환해버린다. 즉 원본 문자열의 내용이 변한다는 것이다.

구체적으로 "Rachel;Tom;John;Michael;Jude"라는 문자열에 대해 strtok 함수를 사용하여 ';' 문자를 기준으로 분할을 수행할 때 "Rachel", "Tom", "John", "Michael", "Jude"라는 5개의 부분 문자열을 얻는데, 이 과정에서 원본 문자열은 "Rachel\0Tom\0John\0Michael\0Jude"와 같이 원래 있던 ';' 문자가 NULL 문자로 변경된다.

1. strtok


strtok 함수의 원형은 다음과 같다.

char * strtok(char * str, const char * delimiters);
str
분할할 문자열이다. 내용이 변할 것이므로 const가 붙지 않는다. 즉 문자열 상수는 받을 수 없고 버퍼만 받을 수 있다.
deliminiters
분할의 기준이 되는 문자이다. 문자열로 입력받기 때문에 기준 문자를 여러개 지정할 수 있다. 그 중 하나라도 분할할 문자열에 있다면 그 문자를 NULL 문자로 고치면서 부분 문자열을 반환한다.

str의 문자열에서 deliminiters에 해당하는 문자가 발견되면 그 자리를 NULL 문자로 치환하고 부분 문자열을 반환한다. 문자열의 끝에 도달하였거나 분할할 것이 없다면 NULL을 반환한다.

/* strtok.c */
#include <stdio.h>
#include <string.h>

int main(int argc, char * argv[])
{
	char str1[64] = "name=Tom;social=facebook,twitter,instagram";
	char str2[64] = "=;,";
	char * result = NULL;
	char * temporary = NULL;

	printf("<BEFORE>\n");
	printf("str1 = \"%s\";\n", str1);

	printf("<STRTOK>\n");
	result = strtok(str1, str2);
	printf("strtok(str1, \"%s\") = \"%s\";\n", str2, result);
	while (result != NULL)
	{
		result = strtok(NULL, str2);

		if (result == NULL)
			printf("strtok(NULL, \"%s\") = NULL;\n", str2);
		else
			printf("strtok(NULL, \"%s\") = \"%s\";\n", str2, result);
	}

	printf("<AFTER>\n");
	printf("str1 = \"%s\";\n", str1);

	return 0;
}
[그림 1] strtok.c 예제 소스 코드
[그림 2] strstr.c 예제 소스 코드의 실행 결과

위 코드는 "name=Tom;social=facebook,twitter,instagram"의 문자열을 strtok 함수로 분할하는 예이다. 해당 문자열은 세미콜론(';')과 등호('=') 및 컴마(',')로 단어들을 분리해낼 수 있음을 직관적으로 알 수 있다. C 언어로 이를 분리하기 위하여 deliminiters 매개변수에 세 기호들이 열거된 문자열을 전달한다.

분리 대상이 되는 문자열은 result = strtok(str1, str2);로서 최초 1회만 매개변수로 전달되고 그 이후 호출에서는 result = strtok(NULL, str2);와 같이 전달하지 않는다. 이미 대산 문자열을 한 번 분할했기 때문에 strtok 함수는 내부적으로 가장 마지막으로 분할한 위치를 기억하고 있기 때문이다. 만일 함수 호출 실행시마다 첫 번째 매개변수에 대상 문자열을 전달하면 분할 작업을 가장 첫 문자부터 시작하므로 최초로 분할되어 나온 부분 문자열만 반복하여 얻어질 것이다.

검색할 문자열의 끝에 도달하였거나 문자열에 분할 기준의 문자가 없어서 더 이상 분할될 수 없을 경우에는 NULL을 반환한다. 루프를 수행중이었다면 이 시점에 루프를 종료하면 된다.

1-1. Wide Character 확장 함수 - wcstok


상기 strtok는 ASCII 문자열 또는 UTF-8 인코딩의 Unicode 문자열에 대해 사용 가능하다. UTF-16/UTF-32와 같은 Wide Character 문자열의 'tokenization'은 아래의 함수를 사용 가능하며, wchar.h, C++에서는 cwchar 헤더를 include한다.

wchar_t * wcstok(wchar_t * wcs, const wchar_t * delimiters);

<Epilogue>


본 포스팅을 통해 문자열 복사 함수에 대해 정리해 보았다. 다음 포스팅[libc 문자열 조작 함수 정리 (part 07 - strspn, strcspn)]에서는 패턴에 맞는 부분 문자열을 검색하는 함수인 strspn, strcspn 함수에 대해 정리한다.

카테고리 “Language/C & C++”
more...
썸네일 이미지
libc 문자열 조작 함수 정리 (part 05 - strstr)
libc 문자열 조작 함수 정리 C 언어에서 문자열 처리는 복잡하다. 언어 수준에서 문자열이라는 데이터 형 자체를 지원하지도 않으니, 덧셈 기호(+)나 비교연산자(==)와 같은 기호를 사용하는 직관적인 문자열 연산을 사용할 수 없기 때문이다. C 언어가 문자열 데이터 형을 지원하지 않고, 문자열을 다루는 연산자도 없으니 모든 문자열 연산은 문자열 함수를 통해 이루어진다. C 표준 라이브러리(일명 'libc')에서 str...로 시작하는 함수들이 그것이며, 모두 string.h 헤더(C++은 cstring 헤더)에 정의되어 있으며 본 시리즈를 통해 이들 함수의 사용법을 정리해보고자 한다. 본 시리즈는 cplusplus(http://www.cplusplus.com) 및 MSDN에 나와있는 레퍼런스를 기준으로..
Language/C & C++
2018. 8. 20. 18:06

libc 문자열 조작 함수 정리 (part 05 - strstr)

Language/C & C++
2018. 8. 20. 18:06

libc 문자열 조작 함수 정리


C 언어에서 문자열 처리는 복잡하다. 언어 수준에서 문자열이라는 데이터 형 자체를 지원하지도 않으니, 덧셈 기호(+)나 비교연산자(==)와 같은 기호를 사용하는 직관적인 문자열 연산을 사용할 수 없기 때문이다. C 언어가 문자열 데이터 형을 지원하지 않고, 문자열을 다루는 연산자도 없으니 모든 문자열 연산은 문자열 함수를 통해 이루어진다. C 표준 라이브러리(일명 'libc')에서 str...로 시작하는 함수들이 그것이며, 모두 string.h 헤더(C++은 cstring 헤더)에 정의되어 있으며 본 시리즈를 통해 이들 함수의 사용법을 정리해보고자 한다. 본 시리즈는 cplusplus(http://www.cplusplus.com) 및 MSDN에 나와있는 레퍼런스를 기준으로 하여 작성되었다.

  1. libc 문자열 조작 함수 정리 (part 01 - strcpy, strncpy)
  2. libc 문자열 조작 함수 정리 (part 02 - strcat, strncat)
  3. libc 문자열 조작 함수 정리 (part 03 - strcmp, strncmp)
  4. libc 문자열 조작 함수 정리 (part 04 - strchr, strrchr)
  5. libc 문자열 조작 함수 정리 (part 05 - strstr)
  6. libc 문자열 조작 함수 정리 (part 06 - strtok)
  7. libc 문자열 조작 함수 정리 (part 07 - strspn, strcspn)
  8. libc 문자열 조작 함수 정리 (part 08 - strlen)
  9. libc 문자열 조작 함수 정리 (part 09 - strpbrk)
  10. libc 문자열 조작 함수 정리 (part 10 - strxfrm, strcoll)
  11. libc 문자열 조작 함수 정리 (part 11 - strerror)

Part V. strstr


본 포스팅에서는 부분 문자열substring 포함 여부 확인을 지원하는 함수인 strstr 계열의 함수에 대해 사용 예를 정리한다.

<Prologue>


strstr은 문자열에 대하여 지정한 부분 문자열을 포함하는 지 여부를 확인하는 함수이다. 가장 직접적인 예시로는 문장 내 비속어를 찾아 필터링을 하는 경우가 있다.

1. strstr


C++ 라이브러리에서 제공하는 헤더 파일인 cstring에서는 검색 대상 문자열의 상수성 여부에 따라 2개의 함수가 오버로드overload되어 있다.

const char * strstr(const char * str1, const char * str2);
char * strstr(char * str1, const char * str2);

C 라이브러리에서 제공하는 헤더 파일인 string.h에서는 하나의 함수만이 정의되어 있다.

char * strstr(const char * str1, const char * str2);
str1
검색 대상이 될 문자열이다.
str2
찾을 문구이다.

함수의 실행 결과 str2에서 지정한 문자열이 발견된 위치를 포인터로 반환한다. 그런 문구가 없으면 NULL이 반환된다.

다음은 strstr 함수의 실행 예이다.

/* strstr.c */
#include <stdio.h>
#include <string.h>

int main(int argc, char * argv[])
{
	char str1[64] = "What the hell! Why don't you clean this room?";
	char str2[64] = "What the f*ck! Why don't you clean this room?";
	char str3[64] = "f*ck";
	char * result = NULL;

	result = strstr(str1, str3);
	if (result != NULL)
	{
		// contains forbidden word
		printf("strstr(\"%s\", \"%s\")\n = \"%s\";\n", str1, str3, result);
		printf("forbidden word: %s\n", result);
	}
	else
	{
		// not contains forbidden word
		printf("strstr(\"%s\", \"%s\")\n = NULL;\n", str1, str3);
		printf("forbidden word: none\n");
	}

	printf("\n");

	result = strstr(str2, str3);
	if (result != NULL)
	{
		// contains forbidden word
		printf("strstr(\"%s\", \"%s\")\n = \"%s\";\n", str2, str3, result);
		printf("forbidden word: %s\n", result);
	}
	else
	{
		// not contains forbidden word
		printf("strstr(\"%s\", \"%s\")\n = NULL;\n", str2, str3);
		printf("forbidden word: none\n");
	}

	return 0;
}
[그림 1] strstr.c 예제 소스 코드
[그림 2] strstr.c 예제 소스 코드의 실행 결과

위 코드를 참조하면, 검색 대상이 될 두 개의 문자열이 준비되어 있다. 하나는 "What the hell! Why don't you clean this room?"로서 욕설이 없는 문자열을 포함하는 str1이고, 다른 하나는 "What the f*ck! Why don't you clean this room?"로서 욕설이 있는 문자열을 포함하는 str2이다. 그리고 "f*ck"로서 검색할 욕 단어를 포함하는 str3가 준비되어 있다.

result = strstr(str1, str3);로서 str1에 대해 욕 단어가 있는지를 검색한다. 이 문자열에는 욕 단어가 포함되어 있지는 않으므로 NULL가 반환되며 result 포인터 변수에도 NULL이 보관된다.

result = strstr(str2, str3);로서 str2에 대해 욕 단어가 있는지를 검색한다. 이 문자열에는 str3에서 지정한 욕 단어가 포함되어 있으므로 해당 욕 단어가 시작되는 포인터가 반환되고 result 변수에 이 주소가 보관된다. 그러므로 printf로 이 변수를 출력하면 해당 욕으로 시작되는 부분 문자열이 출력되는 것이다.

1-1. Wide Character 확장 함수 - wcsstr


상기 strstr은 ASCII 문자열 또는 UTF-8 인코딩의 Unicode 문자열에 대해 사용 가능하다. UTF-16/UTF-32와 같은 Wide Character 문자열의 복사는 아래의 함수를 사용 가능하며, wchar.h, C++에서는 cwchar 헤더를 include한다.

C++ 헤더인 cwchar에는 상수성 여부에 따라 다음의 두 함수가 오버로드되어 있다.

const wchar_t * wcsstr(const wchar_t * str1, const wchar_t * str2);
wchar_t * wcsstr(wchar_t * str1, const wchar_t * str2);

C 헤더인 wchar.h에는 하나의 함수만이 정의되어 있다.

wchar_t * wcsstr(const wchar_t * str1, const wchar_t * str2);

<Epilogue>


본 포스팅을 통해 문자열의 문자열 검색 함수에 대해 정리해 보았다. 다음 포스팅[libc 문자열 조작 함수 정리 (part 06 - strtok)]에서는 특정 기호로 구분된 문자열을 분할해주는 strtok 함수에 대해 정리한다.

카테고리 “Language/C & C++”
more...
썸네일 이미지
libc 문자열 조작 함수 정리 (part 04 - strchr, strrchr)
libc 문자열 조작 함수 정리 C 언어에서 문자열 처리는 복잡하다. 언어 수준에서 문자열이라는 데이터 형 자체를 지원하지도 않으니, 덧셈 기호(+)나 비교연산자(==)와 같은 기호를 사용하는 직관적인 문자열 연산을 사용할 수 없기 때문이다. C 언어가 문자열 데이터 형을 지원하지 않고, 문자열을 다루는 연산자도 없으니 모든 문자열 연산은 문자열 함수를 통해 이루어진다. C 표준 라이브러리(일명 'libc')에서 str...로 시작하는 함수들이 그것이며, 모두 string.h 헤더(C++은 cstring 헤더)에 정의되어 있으며 본 시리즈를 통해 이들 함수의 사용법을 정리해보고자 한다. 본 시리즈는 cplusplus(http://www.cplusplus.com) 및 MSDN에 나와있는 레퍼런스를 기준으로..
Language/C & C++
2018. 8. 20. 11:38

libc 문자열 조작 함수 정리 (part 04 - strchr, strrchr)

Language/C & C++
2018. 8. 20. 11:38

libc 문자열 조작 함수 정리


C 언어에서 문자열 처리는 복잡하다. 언어 수준에서 문자열이라는 데이터 형 자체를 지원하지도 않으니, 덧셈 기호(+)나 비교연산자(==)와 같은 기호를 사용하는 직관적인 문자열 연산을 사용할 수 없기 때문이다. C 언어가 문자열 데이터 형을 지원하지 않고, 문자열을 다루는 연산자도 없으니 모든 문자열 연산은 문자열 함수를 통해 이루어진다. C 표준 라이브러리(일명 'libc')에서 str...로 시작하는 함수들이 그것이며, 모두 string.h 헤더(C++은 cstring 헤더)에 정의되어 있으며 본 시리즈를 통해 이들 함수의 사용법을 정리해보고자 한다. 본 시리즈는 cplusplus(http://www.cplusplus.com) 및 MSDN에 나와있는 레퍼런스를 기준으로 하여 작성되었다.

  1. libc 문자열 조작 함수 정리 (part 01 - strcpy, strncpy)
  2. libc 문자열 조작 함수 정리 (part 02 - strcat, strncat)
  3. libc 문자열 조작 함수 정리 (part 03 - strcmp, strncmp)
  4. libc 문자열 조작 함수 정리 (part 04 - strchr, strrchr)
  5. libc 문자열 조작 함수 정리 (part 05 - strstr)
  6. libc 문자열 조작 함수 정리 (part 06 - strtok)
  7. libc 문자열 조작 함수 정리 (part 07 - strspn, strcspn)
  8. libc 문자열 조작 함수 정리 (part 08 - strlen)
  9. libc 문자열 조작 함수 정리 (part 09 - strpbrk)
  10. libc 문자열 조작 함수 정리 (part 10 - strxfrm, strcoll)
  11. libc 문자열 조작 함수 정리 (part 11 - strerror)

Part IV. strchr, strrchr


본 포스팅에서는 문자열로부터 특정 문자character의 검색을 지원하는 함수인 strchr 계열의 함수에 대해 사용 예를 정리한다.

<Prologue>


strchrstrrchr는 문자열 중에서 특정 문자를 검색하여 그 위치를 얻는데 사용된다. 좀 더 엄밀히 말하면 그 문자가 시작되는 위치의 포인터를 반환한다. strchr은 문자열을 순방향으로 검색하여 가장 처음으로 발견될 때의 위치를 반환하고, strrchr은 문자열을 역방향으로 검색하여 가장 처음으로 발견될 때의 위치를 반환한다.

예를 들면 "What can I do for that?"라는 문자열에서 소문자 'a'로 시작되는 문자열을 얻고자 할 때,

strchr은 문자열을 첫 글자부터 순서대로 검색하여 ▶"What can I do for that?"와 같이 3번째에 있는 'a'를 검색하여 이 문자로 시작하는 문자열을 반환하고 strrchr은 문자열을 끝 글자부터 거꾸로 검색하여 "What can I do for that?"◀와 같이 맨 나중에 있는 'a'를 검색하여 이 문자로 시작하는 문자열을 반환한다.

1. strchr


C++ 라이브러리에서 제공하는 헤더 파일인 cstring에서는 검색 대상 문자열의 상수성 여부에 따라 2개의 함수가 오버로드overload되어 있다.

const char * strchr(const char * str, int character);
char * strchr(char * str, int character);

C 라이브러리에서 제공하는 헤더 파일인 string.h에서는 하나의 함수만이 정의되어 있다.

char * strchr(const char * str, int character);
str
검색 대상이 되는 문자열이다.
character
검색하고자 하는 특정 문자이다.

함수의 실행 결과 character의 문자로 시작하는 부분 문자열을 반환한다. 찾을 수 없으면 NULL을 반환한다.

원형을 자세히 보면 문자 매개변수 characterchar 형이 아닌 int 형으로 선언되어 있다. 참고로 char 형은 1 바이트, int 형은 CPU가 처리할 수 있는 기본 단위로 정의된다. 예를 들어 16 비트 CPU에서는 int가 2 바이트이고, 32 비트 CPU에서는 int가 4 바이트이며, 64 비트 CPU에서는 int가 8 바이트이다. C 언어에서 int보다 작은 크기의 데이터가 전달된다고 하더라도 CPU는 내부의 전자 회로 설계상 int 형으로 처리한다.

다음은 strchr의 사용 예이다.

/* strchr.c */
#include <stdio.h>
#include <string.h>

int main(int argc, char * argv[])
{
	char str[64] = "What can I do for that?";             // original string
	char * result = NULL;                                // result of strchr

	result = strchr(str, 'a');                     // find the character 'a'
	if (result != NULL)
	{
		printf("strchr(\"%s\", 'a') = \"%s\";\n", str, result);
		printf("strchr(\"%s\", 'a') : %ld(th) character.\n", str, (result - str) + 1);
	}

	return 0;
}
[그림 1] strchr.c 예제 소스 코드
[그림 2] strchr.c 예제 소스 코드의 실행 결과

위 코드와 실행 결과를 참고하면, strchr(str, 'a');을 실행함으로써 대상 문자열의 3번째 위치한 'a'를 검색하였고 이 문자부터 시작하는 부분 문자열 "at can I do for that?"을 반환하였다. 반환된 문자열은 원본 문자열의 일부이므로 포인터간 뺄셈 연산을 사용하여 몇 번째 문자로서 검색되었는지를 확인할 수 있다. ((result - str) + 1)

1-1. Wide Character 확장 함수 - wcschr


상기 wcschr는 ASCII 문자열 또는 UTF-8 인코딩의 Unicode 문자열에 대해 사용 가능하다. UTF-16/UTF-32와 같은 Wide Character 문자열의 검색은 아래의 함수를 사용 가능하며, wchar.h, C++에서는 cwchar 헤더를 include한다.

C++ 헤더인 cwchar에는 상수성 여부에 따라 다음의 두 함수가 오버로드되어 있다.

const wchar_t * wcschr(const wchar_t * str, wchar_t character);
wchar_t * wcschr(wchar_t * str, wchar_t character);

C 헤더인 wchar.h에는 하나의 함수만이 정의되어 있다.

wchar_t * wcschr(const wchar_t * ws, wchar_t wc);

2. strrchr


strrchr 함수도 위의 strchr 함수와 동일하다. 다만, 검색 방향이 문자열의 맨 끝 문자부터 검색한다는 차이만이 있다. 함수의 원형은 다음과 같다.

C++ 헤더인 cwchar에는 상수성 여부에 따라,

const char * strrchr(const char * str, int character);
char * strrchr(char * str, int character);

C 헤더인 wchar.h에는,

char * strrchr(const char * str, int character);
str
검색 대상이 되는 문자열이다.
character
검색하고자 하는 특정 문자이다.

다음은 strrchr의 사용 예이다.

/* strrchr.c */
#include <stdio.h>
#include <string.h>

int main(int argc, char * argv[])
{
	char str[64] = "What can I do for that?";             // original string
	char * result = NULL;

	result = strrchr(str, 'a');                    // find the character 'a'
	if (result != NULL)
	{
		printf("strrchr(\"%s\", 'a') = \"%s\";\n", str, result);
		printf("strrchr(\"%s\", 'a') : %ld(th) character.\n", str, (result - str) + 1);
	}

	return 0;
}
[그림 3] strrchr.c 예제 소스 코드
[그림 4] strrchr.c 예제 소스 코드의 실행 결과

[그림 2]와 [그림 4]의 실행결과를 비교해보면, result = strchr(str, 'a');을 실행 시 순방향으로 검색이 이루어지므로 최초 발견되는 문자는 3번째 문자인 'a'가 되어 "at can I do for that?" 문자열이 반환되지만 result = strrchr(str, 'a');을 실행 시 역방향으로 검색이 이루어지므로 최초 발견되는 문자는 21번째 문자인 'a'가 되어 "at?" 문자열이 반환됨을 알 수 있다.

2-1. Wide Character 확장 함수 - wcsrchr


상기 wcsrchr는 ASCII 문자열 또는 UTF-8 인코딩의 Unicode 문자열에 대해 사용 가능하다. UTF-16/UTF-32와 같은 Wide Character 문자열의 검색은 아래의 함수를 사용 가능하며, wchar.h, C++에서는 cwchar 헤더를 include한다.

C++ 헤더인 cwchar에는 상수성 여부에 따라 다음의 두 함수가 오버로드되어 있다.

const wchar_t * wcsrchr(const wchar_t * str, wchar_t character);
wchar_t * wcsrchr(wchar_t * str, wchar_t character);

C 헤더인 wchar.h에는 하나의 함수만이 정의되어 있다.

wchar_t * wcsrchr(const wchar_t * ws, wchar_t wc);

<Epilogue>


본 포스팅을 통해 문자열의 문자 검색 함수에 대해 정리해 보았다. 다음 포스팅[libc 문자열 조작 함수 정리 (part 05 - strstr)]에서는 문자열 내에 특정 문자열을 찾아주는 strstr 함수에 대해 정리한다.

카테고리 “Language/C & C++”
more...
썸네일 이미지
libc 문자열 조작 함수 정리 (part 03 - strcmp, strncmp)
libc 문자열 조작 함수 정리 C 언어에서 문자열 처리는 복잡하다. 언어 수준에서 문자열이라는 데이터 형 자체를 지원하지도 않으니, 덧셈 기호(+)나 비교연산자(==)와 같은 기호를 사용하는 직관적인 문자열 연산을 사용할 수 없기 때문이다. C 언어가 문자열 데이터 형을 지원하지 않고, 문자열을 다루는 연산자도 없으니 모든 문자열 연산은 문자열 함수를 통해 이루어진다. C 표준 라이브러리(일명 'libc')에서 str...로 시작하는 함수들이 그것이며, 모두 string.h 헤더(C++은 cstring 헤더)에 정의되어 있으며 본 시리즈를 통해 이들 함수의 사용법을 정리해보고자 한다. 본 시리즈는 cplusplus(http://www.cplusplus.com) 및 MSDN에 나와있는 레퍼런스를 기준으로..
Language/C & C++
2018. 8. 19. 20:17

libc 문자열 조작 함수 정리 (part 03 - strcmp, strncmp)

Language/C & C++
2018. 8. 19. 20:17

libc 문자열 조작 함수 정리


C 언어에서 문자열 처리는 복잡하다. 언어 수준에서 문자열이라는 데이터 형 자체를 지원하지도 않으니, 덧셈 기호(+)나 비교연산자(==)와 같은 기호를 사용하는 직관적인 문자열 연산을 사용할 수 없기 때문이다. C 언어가 문자열 데이터 형을 지원하지 않고, 문자열을 다루는 연산자도 없으니 모든 문자열 연산은 문자열 함수를 통해 이루어진다. C 표준 라이브러리(일명 'libc')에서 str...로 시작하는 함수들이 그것이며, 모두 string.h 헤더(C++은 cstring 헤더)에 정의되어 있으며 본 시리즈를 통해 이들 함수의 사용법을 정리해보고자 한다. 본 시리즈는 cplusplus(http://www.cplusplus.com) 및 MSDN에 나와있는 레퍼런스를 기준으로 하여 작성되었다.

  1. libc 문자열 조작 함수 정리 (part 01 - strcpy, strncpy)
  2. libc 문자열 조작 함수 정리 (part 02 - strcat, strncat)
  3. libc 문자열 조작 함수 정리 (part 03 - strcmp, strncmp)
  4. libc 문자열 조작 함수 정리 (part 04 - strchr, strrchr)
  5. libc 문자열 조작 함수 정리 (part 05 - strstr)
  6. libc 문자열 조작 함수 정리 (part 06 - strtok)
  7. libc 문자열 조작 함수 정리 (part 07 - strspn, strcspn)
  8. libc 문자열 조작 함수 정리 (part 08 - strlen)
  9. libc 문자열 조작 함수 정리 (part 09 - strpbrk)
  10. libc 문자열 조작 함수 정리 (part 10 - strxfrm, strcoll)
  11. libc 문자열 조작 함수 정리 (part 11 - strerror)

Part III. strcmp, strncmp


본 포스팅에서는 문자열 비교compare를 지원하는 함수인 strcmp 계열의 함수에 대해 사용 예를 정리한다.

<Prologue>


정수, 실수 등의 원시 자료형primitive data type에서는 두 변수간의 비교 연산자로 ==를 사용한다. 그러나 C 언어에서 문자열은 포인터pointer의 일종이기 때문에 == 연산자를 사용할 경우 두 포인터 간 주소 비교만이 수행되지, 각 주소에 보관된 문자까지는 비교하지 않는다. 포인터가 가리키는 주소를 참조하여 각 문자를 비교함으로써 문자열의 일치 여부를 확인하기 위해서는 strcmp 함수를 사용한다.

1. strcmp


strcmp 함수의 원형은 다음과 같다.

int strncmp(const char * str1, const char * str2);
str1
비교를 수행할 첫 번째 문자열이다.
str2
비교를 수행할 두 번째 문자열이다.

strcmp는 두 문자열을 서로 비교한 결과를 반환한다.

일치는 0, 사전 순서대로 볼 때 str1이 더 앞쪽에 있다면 음수, str2가 더 앞쪽에 있다면 양수를 반환한다.

/* strcmp.c */
#include <stdio.h>
#include <string.h>

int main(int argc, char * argv[])
{
	char str1[64] = "codingCat";                           // the 1st string
	char str2[64] = "codingTiger";                         // the 2nd string
	char str3[64] = "codingCat";                           // the 3rd string
	int result = 0;

	result = strcmp(str1, str3);            //   "codingCat" = "codingCat"
	printf("compare: \"%s\" vs \"%s\" >> %d\n", str1, str3, result);

	result = strcmp(str1, str2);            //   "codingCat" > "codingTiger"
	printf("compare: \"%s\" vs \"%s\" >> %d\n", str1, str2, result);

	result = strcmp(str2, str3);            // "codingTiger" < "codingCat"
	printf("compare: \"%s\" vs \"%s\" >> %d\n", str2, str3, result);

	return 0;
}
[그림 1] strcmp.c 예제 소스 코드
[그림 2] strcmp.c 예제 소스 코드의 실행 결과

주목할 사항은 strcmp의 반환 값이다. 앞서 설명한 바와 같이 두 문자열이 같다면 0을 반환하므로 0인지 아닌지만 확인할 수도 있겠지만, 두 문자열이 서로 다를 경우에 그 우선순위와 두 문자열간 거리 정보를 얻을 수 있다. 예를 들어, 위 코드를 참고하여 strcmp(str1, str2);를 실행할 경우 str1str2"coding"까지만 동일하고 그 다음 문자는 각각 'C''T'로서 일치하지 않는다. 이 때,

'C''T'보다 앞서므로 str1str2보다 앞선다. 즉, strcmp음수를 반환한다.

strcmp가 반환할 음수는 구체적으로 두 문자열 사이의 거리이다. 'C''T'보다 17번째 앞선 문자이므로(C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T) -17을 반환한다.

strcmp의 매개변수를 바꾸었을 경우 또한 원리는 같다. 위 코드를 참고하여 strcmp(str2, str1);를 실행할 경우 str2str1"coding"까지만 동일하고 그 다음 문자는 각각 'T''C'로서 일치하지 않는다. 이 때,

'T''C'보다 앞서므로 str2str1보다 처진다. 즉, strcmp양수를 반환한다.

strcmp가 반환할 양수는 구체적으로 두 문자열 사이의 거리이다. 'T''C'보다 17번째 뒤에 나오는 문자이므로(C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T) +17을 반환한다.

요약하면,

  • strcmp = 0이면 두 문자열은 일치한다.
  • strcmp ≠ 0이면 두 문자열은 다르다.
    • strcmp > 0이면 첫 번째 문자열이 두 번째 문자열보다 늦다. 절댓값을 취함으로써 서로 일치하지 않는 최초의 문자 사이의 거리를 알 수 있다.
    • strcmp < 0이면 첫 번째 문자열이 두 번째 문자열보다 앞선다. 절댓값을 취함으로써 서로 일치하지 않는 최초의 문자 사이의 거리를 알 수 있다.

1-1. Wide Character 확장 함수 - wcscmp


상기 strcmp는 ASCII 문자열 또는 UTF-8 인코딩의 Unicode 문자열에 대해 사용 가능하다. UTF-16/UTF-32와 같은 Wide Character 문자열의 비교는 아래의 함수를 사용 가능하며, wchar.h, C++에서는 cwchar 헤더를 include한다.

int wcscmp (const wchar_t* wcs1, const wchar_t* wcs2);

2. strncmp


strncmp은 문자열의 일부에 대해서만 비교 연산을 수행하고 나머지 원리는 위에서 정리한 바와 같다.

int strncmp(const char * str1, const char * str2, size_t num);
str1
비교를 수행할 첫 번째 문자열이다.
str2
비교를 수행할 두 번째 문자열이다.
num
비교를 수행할 최대 문자수이다.

마찬가지로 비교 결과를 반환한다. 일치는 0, 사전 순서대로 볼 때 str1이 더 앞쪽에 있다면 음수, str2가 더 앞쪽에 있다면 양수를 반환한다.

/* strncmp.c */
#include <stdio.h>
#include <string.h>

int main(int argc, char * argv[])
{
	char str1[] = "codingCat";                             // the 1st string
	char str2[] = "codingTiger";                           // the 2nd string
	int result = 0;

	result = strncmp(str1, str2, 11);       //   "codingCat" ! "codingTiger"
	printf("strncmp(\"%s\", \"%s\", 11) == %d\n", str1, str2, result);

	result = strncmp(str2, str1, 11);       // "codingTiger" ! "codingCat"
	printf("strncmp(\"%s\", \"%s\", 11) == %d\n", str2, str1, result);

	result = strncmp(str1, str2, 6);        //      "coding" = "coding"
	printf("strncmp(\"%s\", \"%s\", 6) == %d\n", str1, str2, result);

	result = strncmp(str2, str1, 6);        //      "coding" = "coding"
	printf("strncmp(\"%s\", \"%s\", 6) == %d\n", str2, str1, result);

	return 0;
}
[그림 3] strncmp.c 예제 소스 코드
[그림 4] strcmp.c 예제 소스 코드의 실행 결과

2-1. Wide Character 확장 함수 - wcsncmp


상기 strncmp는 ASCII 문자열 또는 UTF-8 인코딩의 Unicode 문자열에 대해 사용 가능하다. UTF-16/UTF-32와 같은 Wide Character 문자열의 비교는 아래의 함수를 사용 가능하며, wchar.h, C++에서는 cwchar 헤더를 include한다.

int wcsncmp (const wchar_t * wcs1, const wchar_t * wcs2, size_t num);

<Epilogue>


본 포스팅을 통해 문자열 비교 함수에 대해 정리해 보았다. 다음 포스팅[libc 문자열 조작 함수 정리 (part 04 - strchr, strrchr)]에서는 문자열에서 특정 문자를 검색하는 strchr, strrchr 함수에 대해 정리한다.

카테고리 “Language/C & C++”
more...
썸네일 이미지
libc 문자열 조작 함수 정리 (part 02 - strcat, strncat)
libc 문자열 조작 함수 정리 C 언어에서 문자열 처리는 복잡하다. 언어 수준에서 문자열이라는 데이터 형 자체를 지원하지도 않으니, 덧셈 기호(+)나 비교연산자(==)와 같은 기호를 사용하는 직관적인 문자열 연산을 사용할 수 없기 때문이다. C 언어가 문자열 데이터 형을 지원하지 않고, 문자열을 다루는 연산자도 없으니 모든 문자열 연산은 문자열 함수를 통해 이루어진다. C 표준 라이브러리(일명 'libc')에서 str...로 시작하는 함수들이 그것이며, 모두 string.h 헤더(C++은 cstring 헤더)에 정의되어 있으며 본 시리즈를 통해 이들 함수의 사용법을 정리해보고자 한다. 본 시리즈는 cplusplus(http://www.cplusplus.com) 및 MSDN에 나와있는 레퍼런스를 기준으로..
Language/C & C++
2018. 8. 18. 23:38

libc 문자열 조작 함수 정리 (part 02 - strcat, strncat)

Language/C & C++
2018. 8. 18. 23:38

libc 문자열 조작 함수 정리


C 언어에서 문자열 처리는 복잡하다. 언어 수준에서 문자열이라는 데이터 형 자체를 지원하지도 않으니, 덧셈 기호(+)나 비교연산자(==)와 같은 기호를 사용하는 직관적인 문자열 연산을 사용할 수 없기 때문이다. C 언어가 문자열 데이터 형을 지원하지 않고, 문자열을 다루는 연산자도 없으니 모든 문자열 연산은 문자열 함수를 통해 이루어진다. C 표준 라이브러리(일명 'libc')에서 str...로 시작하는 함수들이 그것이며, 모두 string.h 헤더(C++은 cstring 헤더)에 정의되어 있으며 본 시리즈를 통해 이들 함수의 사용법을 정리해보고자 한다. 본 시리즈는 cplusplus(http://www.cplusplus.com) 및 MSDN에 나와있는 레퍼런스를 기준으로 하여 작성되었다.

  1. libc 문자열 조작 함수 정리 (part 01 - strcpy, strncpy)
  2. libc 문자열 조작 함수 정리 (part 02 - strcat, strncat)
  3. libc 문자열 조작 함수 정리 (part 03 - strcmp, strncmp)
  4. libc 문자열 조작 함수 정리 (part 04 - strchr, strrchr)
  5. libc 문자열 조작 함수 정리 (part 05 - strstr)
  6. libc 문자열 조작 함수 정리 (part 06 - strtok)
  7. libc 문자열 조작 함수 정리 (part 07 - strspn, strcspn)
  8. libc 문자열 조작 함수 정리 (part 08 - strlen)
  9. libc 문자열 조작 함수 정리 (part 09 - strpbrk)
  10. libc 문자열 조작 함수 정리 (part 10 - strxfrm, strcoll)
  11. libc 문자열 조작 함수 정리 (part 11 - strerror)

Part II. strcat, strncat


본 포스팅에서는 문자열 결합concatenate을 지원하는 함수인 strcat 계열의 함수에 대해 사용 예를 정리한다.

<Prologue>


strcatstrncat는 문자열 끝에 다른 문자열을 붙이는 역할을 한다. 즉, 원래의 문자열 끝에 있던 NULL ('\0') 문자를 떼고 다른 문자열을 이어 붙인 다음 그 끝에 NULL을 새로 붙이는 역할을 한다. 이 때 원래의 문자열은 수정 가능하여야 하며(즉, 문자열 상수 안 됨), 새로 붙게 될 문자열을 수용할만큼 빈 공간이 충분해야 한다(충분하지 않은 공간에 긴 문자열을 이어붙이면, 메모리가 원래의 영역을 벗어나 다른 프로그램까지 고장나게 만든다. 이를 버퍼 오버플로우buffer overflow라고 하며, C 언어에는 타 메모리 영역의 침범을 감지하여 프로그램을 중지시키는 기능이 없기 때문에 주의해야 한다.

1. strcat


strcat의 원형은 다음과 같다.

char * strcat(char * destination, const char * source);
destination
기존의 문자열이 보관된 수정 가능한 버퍼 주소이다.
source
이어붙일 문자열을 가리키는 주소이다.

source가 가리키는 주소에서 문자를 하나씩 읽어 destination이 가리키는 주소의 문자열에 하나씩 이어 붙인다. 함수가 종료될 때 destination이 가리키는 주소를 그대로 반환한다.

다음은 strcat의 사용 예제이다.

/* strcat.c */
#include <stdio.h>
#include <string.h>

int main(int argc, char * argv[])
{
	char str1[64] = "Cat";                               // string to append
	char str2[64] = "coding";                               // string buffer

	printf("<BEFORE>\n");
	printf("str1 = \"%s\"\n", str1);
	printf("str2 = \"%s\"\n", str2);

	strcat(str2, str1);                                       // concatenate

	printf("<AFTER>\n");
	printf("str1 = \"%s\"\n", str1);
	printf("str2 = \"%s\"\n", str2);

	return 0;
}
[그림 1] strcat.c 예제 소스 코드
[그림 2] strcat.c 예제 소스 코드의 실행 결과

1-1. Wide Character 확장 함수 - wcscat


상기 wcsncat는 ASCII 문자열 또는 UTF-8 인코딩의 Unicode 문자열에 대해 사용 가능하다. UTF-16/UTF-32와 같은 Wide Character 문자열의 결합은 아래의 함수를 사용 가능하며, wchar.h, C++에서는 cwchar 헤더를 include한다.

wchar_t * wcscat (wchar_t * destination, const wchar_t * source);

2. strncat


strncat도 문자열을 이어붙이는 역할을 하는데 매개변수로 지정한 몇 글자까지만 이어붙인다.

char * strncat(char * destination, const char * source, size_t num);
destination
원래의 문자열을 가리키는 수정 가능한 메모리 주소이다.
source
이어붙일 문자열을 가리키는 주소이다.
num
source로부터 복사할 문자의 개수이다.

source가 가리키는 주소에서 문자를 하나씩 읽어 destination이 가리키는 주소의 문자열에 이어붙이는데 그 개수는 num 개로 제한한다. 함수가 종료될 때 destination이 가리키는 주소를 그대로 반환합니다.

아래 코드는 strncat의 사용 예이다.

/* strncat.c */
#include <stdio.h>
#include <string.h>

int main(int argc, char * argv[])
{
	char str1[64] = "Cat, Tiger and Lion";               // string to append
	char str2[64] = "coding";                               // string buffer

	printf("<BEFORE>\n");
	printf("str1 = \"%s\"\n", str1);
	printf("str2 = \"%s\"\n", str2);

	strncat(str2, str1, 3);                                   // concatenate

	printf("<AFTER>\n");
	printf("str1 = \"%s\"\n", str1);
	printf("str2 = \"%s\"\n", str2);

	return 0;
}
[그림 3] strncat.c 예제 소스 코드
[그림 4] strncat.c 예제 소스 코드의 실행 결과

2-1. Wide Character 확장 함수 - wcsncat


상기 wcsncat는 ASCII 문자열 또는 UTF-8 인코딩의 Unicode 문자열에 대해 사용 가능하다. UTF-16/UTF-32와 같은 Wide Character 문자열의 결합은 아래의 함수를 사용 가능하며, wchar.h, C++에서는 cwchar 헤더를 include한다.

wchar_t * wcsncat (wchar_t * destination, const wchar_t * source, size_t num);

<Epilogue>


본 포스팅을 통해 문자열 복사 함수에 대해 정리해 보았다. 다음 포스팅[libc 문자열 조작 함수 정리 (part 03 - strcmp, strncmp)]에서는 문자열을 비교하는 strcmp, strncmp 함수에 대해 정리한다.

카테고리 “Language/C & C++”
more...
썸네일 이미지
libc 문자열 조작 함수 정리 (part 01 - strcpy, strncpy)
libc 문자열 조작 함수 정리 C 언어에서 문자열 처리는 복잡하다. 언어 수준에서 문자열이라는 데이터 형 자체를 지원하지도 않으니, 덧셈 기호(+)나 비교연산자(==)와 같은 기호를 사용하는 직관적인 문자열 연산을 사용할 수 없기 때문이다. C 언어가 문자열 데이터 형을 지원하지 않고, 문자열을 다루는 연산자도 없으니 모든 문자열 연산은 문자열 함수를 통해 이루어진다. C 표준 라이브러리(일명 'libc')에서 str...로 시작하는 함수들이 그것이며, 모두 string.h 헤더(C++은 cstring 헤더)에 정의되어 있으며 본 시리즈를 통해 이들 함수의 사용법을 정리해보고자 한다. 본 시리즈는 cplusplus(http://www.cplusplus.com) 및 MSDN에 나와있는 레퍼런스를 기준으로..
Language/C & C++
2018. 8. 18. 06:34

libc 문자열 조작 함수 정리 (part 01 - strcpy, strncpy)

Language/C & C++
2018. 8. 18. 06:34

libc 문자열 조작 함수 정리


C 언어에서 문자열 처리는 복잡하다. 언어 수준에서 문자열이라는 데이터 형 자체를 지원하지도 않으니, 덧셈 기호(+)나 비교연산자(==)와 같은 기호를 사용하는 직관적인 문자열 연산을 사용할 수 없기 때문이다. C 언어가 문자열 데이터 형을 지원하지 않고, 문자열을 다루는 연산자도 없으니 모든 문자열 연산은 문자열 함수를 통해 이루어진다. C 표준 라이브러리(일명 'libc')에서 str...로 시작하는 함수들이 그것이며, 모두 string.h 헤더(C++은 cstring 헤더)에 정의되어 있으며 본 시리즈를 통해 이들 함수의 사용법을 정리해보고자 한다. 본 시리즈는 cplusplus(http://www.cplusplus.com) 및 MSDN에 나와있는 레퍼런스를 기준으로 하여 작성되었다.

  1. libc 문자열 조작 함수 정리 (part 01 - strcpy, strncpy)
  2. libc 문자열 조작 함수 정리 (part 02 - strcat, strncat)
  3. libc 문자열 조작 함수 정리 (part 03 - strcmp, strncmp)
  4. libc 문자열 조작 함수 정리 (part 04 - strchr, strrchr)
  5. libc 문자열 조작 함수 정리 (part 05 - strstr)
  6. libc 문자열 조작 함수 정리 (part 06 - strtok)
  7. libc 문자열 조작 함수 정리 (part 07 - strspn, strcspn)
  8. libc 문자열 조작 함수 정리 (part 08 - strlen)
  9. libc 문자열 조작 함수 정리 (part 09 - strpbrk)
  10. libc 문자열 조작 함수 정리 (part 10 - strxfrm, strcoll)
  11. libc 문자열 조작 함수 정리 (part 11 - strerror)

Part I. strcpy, strncpy


본 포스팅에서는 문자열 복사copy를 지원하는 함수인 strcpy 계열의 함수에 대해 사용 예를 정리한다.

<Prologue>


strcpy와 strncpy는 둘 다 문자열을 복사하는 함수이다. 복사의 목적은 여러가지가 있겠으나 대체로 원본은 그대로 두어 보존하고, 사본을 하나 만들어서 변조도 하고 수정도 하고 그러기 위함이 대부분이다. C 언어에서 문자열은 끝에 항상 NULL('\0') 문자가 붙는다. 화면으로 보이지는 않지만 분명 메모리상으로는 존재하는 것이 이 문자이다. 문자열의 복사는 이 NULL 문자를 만나면 중단하게 되어 있다.

악의적인 목적으로 문자열에서 NULL 문자를 제거해버리면 컴퓨터는 NULL 문자를 찾을때까지 컴퓨터에 설치된 메모리 전체를 쑤시고 다니면서 자신과 무관한 프로그램이 점유하는 메모리의 내용까지 침범하는데 프로그램을 잘못 짜서 자신의 컴퓨터에서만 일어나면 버그bug지만, 다른 컴퓨터를 그렇게 만든다면 훌륭한 사이버 공격이다. 2003년 1월 25일에 우리나라에서 발생한 1.25 인터넷 대란에서 SQL 서버를 쓰러뜨린 슬래머 웜도 이와 같은 원리이다.

1. strcpy


어쨌든, strcpy는 다음과 같은 원형을 가지며 문자열을 통째로 복사하는 역할을 한다.

char * strcpy(char * destination, const char * source);
destination
사본이 저장될 문자열 버퍼이다.
source
원본 문자열이 담긴 문자열 버퍼이다.

source가 가리키는 주소에서 문자를 하나씩 읽어 destination이 가리키는 주소에 하나씩 베껴적는데 NULL 문자를 만나면 그것까지 복사한 다음에 함수를 종료한다. 함수가 종료될 때 destination이 가리키는 주소를 그대로 반환한다. 다음은 strcpy 함수를 사용하는 예이다.

/* strcpy.c */
#include <stdio.h>
#include <string.h>

int main(int argc, char * argv[])
{
	char str1[64] = "Hello, World!";                        // source string
	char str2[64] = {'\0', };                               // string buffer

	printf("<BEFORE>\n");
	printf("str1 = \"%s\"\n", str1);
	printf("str2 = \"%s\"\n", str2);

	strcpy(str2, str1);                                     // copy string

	printf("<AFTER>\n");
	printf("str1 = \"%s\"\n", str1);
	printf("str2 = \"%s\"\n", str2);

	return 0;
}
[그림 1] strcpy.c 예제 소스 코드
[그림 2] strcpy.c 예제 소스 코드의 실행 결과

1-1. Wide Character 확장 함수 - wcscpy


상기 strcpy는 ASCII 문자열 또는 UTF-8 인코딩의 Unicode 문자열에 대해 사용 가능하다. UTF-16/UTF-32와 같은 Wide Character 문자열의 복사는 아래의 함수를 사용 가능하며, wchar.h, C++에서는 cwchar 헤더를 include한다.

wchar_t * wcscpy (wchar_t * destination, const wchar_t * source);

2. strncpy


strncpy도 문자열 복사이긴 한데 원본 문자열의 글자부터 지정된 수만큼의 문자만을 복사한다. 복사된 문자열의 끝에는 자동으로 NULL이 붙는다. 원형은 다음과 같다.

char * strncpy(char * destination, const char * source, size_t num);
destination
사본이 저장될 메모리이다.
source
원본 문자열이 담긴 메모리이다.
num
처음부터 몇 글자까지만 복사할 것인지 지정합니다.

source가 가리키는 주소에서 문자를 하나씩 읽어 destination이 가리키는 주소에 복사하는데, NULL 문자를 만나면 그것까지만 복사한 다음에 함수를 종료한다. 또는 현재까지 복사된 문자 수가 num에서 지정한 개수와 같아도 함수를 종료한다. 함수가 종료될 때 destination이 가리키는 문자열 버퍼의 주소를 그대로 반환한다. 다음은 strncpy 함수의 사용법이다.

/* strncpy.c */
#include <stdio.h>
#include <string.h>

int main(int argc, char * argv[])
{
	char str1[64] = "Hello, World!";                        // source string
	char str2[64] = {'\0', };                               // string buffer

	printf("<BEFORE>\n");
	printf("str1 = \"%s\"\n", str1);
	printf("str2 = \"%s\"\n", str2);

	strncpy(str2, str1, 5);                                 // copy string

	printf("<AFTER>\n");
	printf("str1 = \"%s\"\n", str1);
	printf("str2 = \"%s\"\n", str2);

	return 0;
}
[그림 3] strncpy.c 예제 소스 코드
[그림 4] strncpy.c 예제 소스 코드의 실행 결과

2-1. Wide Character 확장 함수 - wcsncpy


상기 wcsncpy는 ASCII 문자열 또는 UTF-8 인코딩의 Unicode 문자열에 대해 사용 가능하다. UTF-16/UTF-32와 같은 Wide Character 문자열의 복사는 아래의 함수를 사용 가능하며, wchar.h, C++에서는 cwchar 헤더를 include한다.

wchar_t * wcsncpy (wchar_t * destination, const wchar_t * source, size_t num);

<Epilogue>


본 포스팅을 통해 문자열 복사 함수에 대해 정리해 보았다. 다음 포스팅[libc 문자열 조작 함수 정리 (part 02 - strcat, strncat)]에서는 문자열 끝에 다른 문자열을 이어 붙이는 strcat, strncat 함수에 대해 정리한다.

카테고리 “Language/C & C++”
more...

“language” (11건)

개발괴발로 작성하는 개발자 블로그.