^(코딩캣)^ = @"코딩"하는 고양이;

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...