문자열과 문자 처리
지난 편에서는 같은 자료형의 데이터를 여러 개 묶어서 관리하는 배열에 대해 배웠습니다. 그런데 C언어에는 “문자열”이라는 자료형이 따로 존재하지 않습니다. 대신 문자(char)를 여러 개 늘어놓은 배열을 문자열처럼 취급합니다. 즉, 지난 시간에 배운 배열 개념을 그대로 활용해서 “안녕하세요” 같은 텍스트를 다루는 것이 바로 오늘의 주제입니다.
문자열이란 무엇인가
C언어에서 문자열은 char 타입 문자들이 연속으로 저장된 배열이며, 문자열의 끝을 표시하기 위해 마지막에 널 문자(\0)가 자동으로 추가됩니다. 예를 들어 "hello"라는 문자열은 실제로는 h, e, l, l, o, \0 이렇게 6개의 문자가 메모리에 저장되는 것입니다. 이 널 문자 덕분에 프로그램은 문자열이 어디서 끝나는지 알 수 있습니다.
char name[6] = "hello";
배열 크기를 6으로 잡은 이유는 눈에 보이는 글자 5개에 널 문자 하나를 더해야 하기 때문입니다. 이 부분을 깜빡하고 크기를 5로만 잡으면 널 문자가 들어갈 자리가 없어서 문제가 생길 수 있으니 항상 여유 공간을 계산해야 합니다.
문자열 선언과 입출력
문자열은 배열 초기화 문법으로 선언할 수도 있고, 크기를 생략해서 컴파일러가 자동으로 계산하게 할 수도 있습니다.
char greeting[] = "안녕하세요";
문자열을 화면에 출력할 때는 printf와 %s 서식 지정자를 사용하고, 키보드로부터 문자열을 입력받을 때는 scanf의 %s나 공백을 포함한 한 줄 전체를 읽는 fgets 함수를 사용합니다. scanf("%s", ...)는 공백을 만나면 입력을 멈추기 때문에 “홍길동”처럼 공백 없는 단어를 입력받을 때 주로 쓰고, 문장 전체를 받고 싶다면 fgets가 더 안전합니다.
char buffer[50];
printf("이름을 입력하세요: ");
scanf("%s", buffer);
여기서 buffer는 배열의 이름 자체가 이미 시작 주소를 의미하기 때문에 scanf에서 &buffer처럼 주소 연산자를 따로 붙이지 않아도 됩니다. 배열과 포인터의 관계는 다음에 더 자세히 다루겠지만, 지금은 “배열 이름은 주소처럼 동작한다”는 정도만 기억해두면 충분합니다.
문자열 처리 함수 살펴보기
C언어는 <string.h> 헤더에 문자열을 다루는 다양한 함수를 제공합니다. 자주 쓰이는 몇 가지만 짚어보겠습니다.
strlen(s): 문자열s의 길이(널 문자 제외)를 반환합니다.strcpy(dest, src):src문자열을dest로 복사합니다.strcat(dest, src):dest문자열 뒤에src를 이어 붙입니다.strcmp(s1, s2): 두 문자열을 비교해서 같으면 0을 반환합니다.
이 함수들을 직접 써보는 것이 이해하는 가장 빠른 방법이니, 아래 예제 코드를 통해 확인해보겠습니다.
예제 코드로 확인해보기
이름과 인사말을 각각 저장한 뒤, 길이를 구하고 두 문자열을 이어 붙이고 비교까지 해보는 프로그램을 작성해보겠습니다.
#include <stdio.h>
#include <string.h>
int main(void) {
char name[20] = "철수";
char greeting[50] = "안녕하세요, ";
char fullMessage[70];
printf("이름: %s\n", name);
printf("이름의 길이(바이트): %lu\n", strlen(name));
strcpy(fullMessage, greeting);
strcat(fullMessage, name);
strcat(fullMessage, "님!");
printf("완성된 문장: %s\n", fullMessage);
if (strcmp(name, "철수") == 0) {
printf("이름이 '철수'와 일치합니다.\n");
} else {
printf("이름이 '철수'와 다릅니다.\n");
}
return 0;
}
코드 동작 설명 및 실행 결과
name배열에는 “철수”라는 문자열이 저장되어 있고,strlen(name)은 널 문자를 제외한 실제 저장된 바이트 수를 반환합니다. 한글은 인코딩에 따라 한 글자가 여러 바이트를 차지하기 때문에 눈에 보이는 글자 수와strlen결과가 다를 수 있다는 점도 함께 알아두면 좋습니다.strcpy(fullMessage, greeting)는greeting의 내용을fullMessage에 그대로 복사하고, 이어지는 두 번의strcat호출은fullMessage뒤에name과 “님!”을 차례로 이어 붙입니다.strcmp(name, "철수")는 두 문자열이 완전히 같으면 0을 반환하므로,if문에서 0과 비교해서 일치 여부를 판단합니다.- 이 코드를
gcc strings.c -o strings로 컴파일하고 실행하면 다음과 같은 결과가 출력됩니다.
이름: 철수
이름의 길이(바이트): 6
완성된 문장: 안녕하세요, 철수님!
이름이 '철수'와 일치합니다.
“철수”는 한글 두 글자이지만, UTF-8로 저장된 소스 파일에서는 한 글자당 3바이트를 차지하기 때문에 strlen의 결과는 눈에 보이는 글자 수(2)가 아니라 6이 나옵니다. 이처럼 한글 문자열을 다룰 때는 “글자 수”와 “바이트 수”가 다를 수 있다는 점을 꼭 기억해두어야 합니다.
핵심 요약
- C언어에는 별도의 문자열 자료형이 없고,
char배열의 끝에 널 문자(\0)를 붙여 문자열을 표현합니다. - 문자열 배열을 선언할 때는 눈에 보이는 글자 수보다 한 칸 더 큰 크기를 확보해서 널 문자가 들어갈 공간을 남겨야 합니다.
%s서식 지정자로 문자열을 입출력할 수 있으며, 배열 이름 자체가 주소 역할을 하므로scanf에서&를 붙이지 않습니다.<string.h>의strlen,strcpy,strcat,strcmp같은 함수를 활용하면 문자열의 길이 계산, 복사, 연결, 비교를 손쉽게 처리할 수 있습니다.
다음 편에서는 지금까지 배운 문법을 코드 단위로 묶어서 재사용하는 방법인 “함수 기초”에 대해 알아보겠습니다. 반복되는 코드를 함수로 만들어두면 문자열을 다루는 코드도 훨씬 깔끔하게 정리할 수 있을 것입니다.