HOWTO · C
문자열에 C의 하위 문자열이 포함되어 있는지 확인
이 기사에서는 문자열에 C의 하위 문자열이 포함되어 있는지 확인하는 방법을 보여줍니다.
이 페이지의 내용
널 종료 C 문자열에 대소문자를 구분하는 정확한 하위 문자열이 있는지 확인하려면 <string.h>의 strstr를 호출합니다. 일치하는 첫 위치를 가리키는 포인터를 반환하고, 일치 항목이 없으면 NULL을 반환합니다. 아래 예제는 각각 실행되었으며 영어 문구 Substring found.를 출력했습니다. 이 문구는 변경되지 않은 코드 블록에 영어로 남아 있습니다.
strstr로 하위 문자열 확인하기
전체 문자열을 첫 번째 인수로, 찾을 텍스트를 두 번째 인수로 전달합니다. 반환된 포인터를 직접 검사하세요. 포인터를 주소로 출력하지 마세요. 그 값은 프로세스마다 달라질 수 있습니다. strstr는 표준 C 헤더 <string.h>에 선언되어 있으며 대소문자를 포함해 문자를 정확히 비교합니다.
이 프로그램은 문장에서 welcome을 찾고, 찾았는지 여부를 안정적인 메시지로 출력합니다. 코드 블록은 변경되지 않으므로 메시지는 영어로 표시됩니다.
#include <stdio.h>
#include <string.h>
int main(void) {
const char *text = "Hello, welcome to C.";
const char *needle = "welcome";
if (strstr(text, needle) != NULL) {
puts("Substring found.");
} else {
puts("Substring not found.");
}
return 0;
}
Substring found.
반환된 포인터는 text에서 첫 번째로 일치하는 문자를 가리키므로 해당 위치의 내용을 확인하거나 그 지점부터 처리를 이어 갈 수 있습니다. 포인터가 널이 아니면 일치하는 항목이 있다는 뜻입니다. 검색할 텍스트가 ""이면 strstr는 text의 시작 위치를 반환합니다. 애플리케이션에서 빈 검색어를 일치로 간주하지 않으려면 이 표준 동작을 고려하세요.
반복문으로 하위 문자열 검색하기
직접 검색하면 비교 과정을 명확히 보여 주거나 애플리케이션별 동작을 추가할 수 있습니다. 아래 함수는 널이 아니며 널 종료된 문자열 두 개를 받아 검색 텍스트가 있으면 1, 없으면 0을 반환합니다. 길이를 빼기 전에 먼저 비교하므로 검색 텍스트가 입력보다 길 때 부호 없는 정수 언더플로가 발생하지 않습니다. strstr와 마찬가지로 빈 검색 텍스트도 일치로 처리합니다.
#include <stdio.h>
#include <string.h>
int contains_substring(const char *text, const char *needle) {
size_t text_len = strlen(text);
size_t needle_len = strlen(needle);
if (needle_len == 0) {
return 1;
}
if (needle_len > text_len) {
return 0;
}
for (size_t i = 0; i <= text_len - needle_len; ++i) {
size_t j = 0;
while (j < needle_len && text[i + j] == needle[j]) {
++j;
}
if (j == needle_len) {
return 1;
}
}
return 0;
}
int main(void) {
const char *text = "Hello, welcome to C.";
const char *needle = "welcome";
puts(contains_substring(text, needle)
? "Substring found."
: "Substring not found.");
return 0;
}
Substring found.
바깥쪽 반복문은 검색 텍스트 전체가 들어갈 수 있는 각 시작 위치를 확인합니다. 안쪽 반복문은 서로 대응하는 문자가 일치하는 동안에만 진행합니다. 검색 텍스트의 길이까지 도달하면 완전히 일치하는 항목을 찾은 것입니다. 이 간단한 방식은 학습이나 사용자 지정에 유용합니다. 일반적인 정확한 검색에는 직접 검색 코드를 유지해야 할 이유가 없다면 표준 라이브러리 함수를 사용하세요.
대소문자를 구분하지 않고 하위 문자열 확인하기
C 표준 라이브러리에는 대소문자를 구분하지 않는 하위 문자열 검색 함수가 없습니다. GNU 시스템에서는 strcasestr가 대소문자 구분 없이 검색하며 GNU 확장으로 제공됩니다. 이 기능 테스트 매크로를 사용하는 시스템에서는 헤더를 포함하기 전에 _GNU_SOURCE를 정의해 함수 선언을 요청하세요. 이 함수는 이식 가능한 표준 C 함수가 아니므로 사용하기 전에 대상 플랫폼에서 지원하는지 확인해야 합니다.
이 완전한 예제는 ASCII 텍스트를 사용해 GNU 전용 호출을 보여 줍니다. 영어 문구 Substring found.를 출력하며, 변경되지 않은 코드 블록에 그대로 남아 있습니다.
#define _GNU_SOURCE
#include <stdio.h>
#include <string.h>
int main(void) {
const char *text = "Hello, Welcome to C.";
const char *needle = "welcome";
if (strcasestr(text, needle) != NULL) {
puts("Substring found.");
} else {
puts("Substring not found.");
}
return 0;
}
Substring found.
이식 가능한 코드를 작성하려면 입력 문자열을 무심코 바꾸는 대신, 명시적으로 정한 문자 정책에 따라 대소문자를 구분하지 않고 비교하세요. tolower는 바이트 단위 텍스트 처리에 도움이 될 수 있지만, 인수는 EOF이거나 unsigned char로 표현할 수 있는 값이어야 하며 동작은 현재 C 로케일을 따릅니다. 이 방법만으로는 유니코드 대소문자 접기를 처리할 수 없습니다. 프로그램이 다룰 데이터에 맞는 라이브러리와 텍스트 정책을 선택하세요.
예외 상황을 처리하고 방법 선택하기
strstr와 위 반복문은 모두 널 종료 문자열에서 정확히 일치하는 문자 시퀀스를 찾습니다. 검색어가 텍스트보다 길면 일치할 수 없습니다. 검색어가 비어 있으면 strstr는 시작 위치에서 일치한다고 보고하고, 위 반복문 구현도 같은 규칙을 따릅니다. 애플리케이션에서 다른 규칙이 필요하면 빈 검색어인지 명시적으로 확인하세요. 표준 문자열 함수에 유효한 문자열 인수가 필요한 것처럼 반복문에도 널이 아닌 포인터가 필요합니다.
strstr는 첫 번째 출현 위치를 반환합니다. 이후의 출현을 찾으려면 이전 일치 위치에 검색어 길이를 더한 곳부터 다시 검색하세요. 다음 검색이 앞으로 진행되도록 검색어가 비어 있지 않은지도 확인해야 합니다. 겹치는 일치 항목도 찾아야 한다면 이전 일치 위치에서 문자 하나만 이동해 검색을 이어 가세요. 어느 방법을 쓸지는 출현 위치끼리 문자를 공유할 수 있는지에 따라 달라집니다.
일반적인 대소문자 구분 정확 검색에는 간결하고 표준 C에 포함된 strstr를 사용하세요. 비교 방식을 직접 가르치거나 사용자 지정해야 한다면 입력 조건을 문서화하고 반복문을 사용하세요. GNU 확장을 사용할 수 있고 바이트 및 로케일 동작이 텍스트에 적합한 경우에만 strcasestr를 사용하세요. strpbrk는 정확한 하위 문자열 검색의 대안이 아닙니다. 입력에 문자 집합 중 하나라도 있는지 확인하므로 다른 질문에 답하는 함수입니다.