12-1-다.문자열 비교

문자열 비교 함수는 두 문자열이 같은지 다른지, 다르다면 어떤 문자열이 더 큰지를 비교한다.

 

int strcmp(const char *s1, const char *s2);

int strncmp(const char *s1, const char *s2, size_t count);

 

strcmp 함수는 String Compare의 약자이며 가장 기본이 되는 비교 함수이다. strncmp 함수는 지정한 개수까지만 문자열을 비교한다. 이 함수들은 인수로 주어진 두 문자열을 비교한 후 그 결과를 다음과 같이 정수값 하나로 리턴한다.

 

s1과 s2가 같으면 0

s1>s2 이면 양수

s1<s2 이면 음수

 

리턴값이 0, 1, -1 과 같이 상수로 정의되어 있지 않고 부호로 정의되어 있는 이유는 비교 속도를 높이기 위해서이다. strcmp 함수는 두 문자열의 대응되는 문자들을 차례대로 비교해 나가다가 최초로 다른 문자가 발견되면 두 문자의 코드값을 그대로 뺄셈해서 리턴해 버린다. 그래서 비교 결과도 부호로 판별해야 한다.

두 문자열이 같거나 다른 경우는 쉽게 이해가 되겠지만 숫자도 아닌 문자열이 대소관계를 가진다는 것이 선뜻 이해가 안 갈 수도 있다. 그러나 문자열도 메모리상에 기록될 때는 문자 코드로 기록되므로 숫자와 마찬가지로 대소 관계를 가질 수 있다. 예를 들어 A 문자 보다는 B 문자의 코드가 더 크기 때문에 A(65)보다는 B(66)가 더 크다고 할 수 있다. 문자열의 대소 관계는 문자열을 구성하는 각 문자들의 코드값을 수치로 비교하여 판단하는데 사전에서 뒤쪽에 나오는 단어가 더 큰 값을 가지는 것으로 평가된다.

 

"ABC"와 "ABC"는 같다. 비교 결과는 0이다.

"ABC"는 "ABD"보다 작다. 비교 결과는 음수이다.

"ABC"는 "ABB"보다 크다. 비교 결과는 양수이다.

 

문자열끼리 대소 관계를 비교해야 하는 경우는 그리 흔하지 않으며 두 문자열이 같은지 다른지를 검사할 경우가 대부분이다. 이럴 때는 리턴값의 부호 따위는 무시해 버리고 0인지 아닌지만 살펴보면 된다. 다음 예제는 입력한 문자열이 특정 문자열이 맞는지를 strcmp 함수로 비교해 본다.

 

: strcmp

#include <Turboc.h>

#include <string.h>

 

void main(void)

{

     char capital[16];

 

     printf("우리나라의 수도는 어디입니까? ");

     scanf("%s",capital);

 

     if (strcmp(capital,"서울")==0) {

          printf("축하합니다. 정답입니다.\n");

     } else {

          printf("틀렸다. 넌 어떻게 그것도 모르니?\n");

     }

}

 

사용자가 입력한 capital 문자열과 "서울"이라는 문자열 상수를 비교한 결과가 0이면 두 문자열이 같은 것으로, 즉 사용자가 정답을 입력한 것으로 판단하였다. 비교할 두 문자열을 strcmp 함수의 인수로 넘겨 주고 그 리턴값이 0인지 아닌지만 보면 된다.

strncmp 함수는 가운데 n이 끼어 있는데 strncpy, strncat 함수들과 마찬가지로 지정한 개수만큼만 문자열을 비교한다. 전체 문자열이 아닌 문자열의 앞쪽 몇 글자만 비교해 보고 싶을 때 이 함수를 사용하면 된다. 예를 들어 Name 문자열이 사람의 이름을 가질 때 strncmp(Name,"김",2) 함수를 호출하면 이 사람의 성이 김가인지 아닌지를 알 수 있다.

영문에는 대소문자라는 것이 있어서 똑같은 문자열이라도 대소문자 구성에 따라 다른 문자열로 인식될 수도 있다. strcmp 함수는 문자의 코드를 별다른 조작없이 곧바로 비교하므로 대문자보다는 소문자가 더 큰 것으로 인식된다. 예를 들어 "DOG" 보다는 "dog"가 더 큰 값을 가지며 이 두 문자열을 strcmp로 비교하면 서로 다르다는 평가를 할 것이다. 다음 두 함수는 대소문자 구분없이 문자열을 비교한다.

 

int stricmp(const char *string1, const char *string2);

int strnicmp(const char *string1, const char *string2, size_t count);

 

함수명 중간에 i가 삽입되어 있는데 여기서 i는 Ignore, 즉 대소문자 구성을 무시하고 비교한다는 뜻이다. 참고로 비주얼 C++의 도움말인 MSDN에서 이 함수들을 찾아 보면 함수명 앞에 _가 붙어 있는 _stricmp, _strnicmp로도 정의되어 있어 양쪽 모두 사용 가능하다. 볼랜드 계열의 컴파일러에는 이 함수들의 이름이 stricmp, strnicmp로 되어 있고 또 어떤 컴파일러는 strcmpi, strcmpni로 되어 있는 경우도 있다. 컴파일러에 따라 표준 함수의 이름이 조금씩 달라질 수도 있다는 점을 염두에 두도록 하자. 이 책에서는 가급적이면 _가 없는 함수 이름을 쓰기로 한다.

strcmp("DOG", "dog")는 대소문자를 구분하므로 두 문자열을 다르다고 평가하지만 stricmp("DOG", "dog")는 두 문자열이 같다고 평가한다. 그래서 "NoteBook"이나 "NOTEBOOK"이나 "NoTEbOoK"이나 모두 같은 문자열로 평가된다.

한글 문자열을 비교할 때는 strcmp 함수로도 충분하지만 영문을 비교할 때는 대소문자 구분 여부에 따라 정확한 비교 함수를 사용해야 한다. 도스나 윈도우즈의 파일 시스템은 파일명의 대소문자를 구분하지 않으므로 파일명을 비교할 때는 strcmp 함수 대신 반드시 stricmp 함수로 비교해야 한다. 그렇지 않으면 "MEMO.TXT"와 "memo.txt"가 다른 파일이 되어 버릴 것이다. 반면 유닉스나 리눅스의 파일 시스템은 파일명의 대소문자를 구분하므로 strcmp 함수로 비교해야 한다.