안녕하세요. c언어 기초 블로그를 작성하고 있는 게임플밍마스터 입니다.
지난 시간에는 포인터라는 다소 추상적인 개념을 맛보았으니, 이제 포인터를 활용하여 우리에게 훨씬 더 실용적이고 친숙한 '문자열', 즉 텍스트 데이터를 다루는 방법을 배워보겠습니다. 이번 장을 배우고 나면 사용자로부터 이름, 문장 등을 입력받아 처리하는 진짜 프로그램다운 프로그램을 만들 수 있게 될 것입니다.
우리는 지금까지 숫자(int, double)와 단 한 개의 문자(char)를 다루는 법을 배웠습니다. 하지만 "Hello", "홍길동"과 같이 여러 문자가 모인 문자열(String) 은 어떻게 저장하고 다룰 수 있을까요?
Java나 Python, C++ 같은 다른 언어들은 string이라는 편리한 자료형을 제공하지만, C언어는 조금 다릅니다. C언어에서 문자열은 '문자들의 배열' 이라는 방식으로 다루어집니다. 그리고 한 가지 매우 중요한 약속이 있습니다.
1. C언어의 약속 - 널 문자 \0
C언어에서 문자열은 char형 배열에 문자들이 차례대로 저장되고, 문자열의 끝을 알리기 위해 마지막에 '널 문자(Null Terminator)' 라고 불리는 '\0' 이 들어가는 형태로 정의됩니다.
예를 들어, "cat"이라는 문자열은 메모리에 다음과 같이 저장됩니다.
| 'c' | 'a' | 't' | '\0' |
분명 글자는 3개인데, 실제로는 마지막에 '\0'이 추가되어 총 4개의 공간(4바이트)을 차지합니다. printf나 다른 문자열 처리 함수들은 이 '\0'을 만날 때까지가 하나의 문자열이라고 인식하고 작업을 수행합니다. 이 '\0'이 없다면, C언어는 어디까지가 문자열인지 알 수 없어 메모리의 엉뚱한 부분까지 계속 읽어 들이는 심각한 오류를 발생시킵니다.
여기서 중요한 핵심은 널문자는 문자열의 끝을 나타내는 수단이라는 사실을 이해하면 됩니다.
널문자는 \0 로 표기하며 문자이므로 ' ' 안에 표기하는것이 원칙입니다.
문자열은 " " 안에 표기하는 것이 원칙이구요.
2. 문자열 변수 만들고 초기화하기
문자열을 저장할 char 배열을 선언하고 초기화하는 방법은 두 가지입니다.
방법 1: 배열 초기화 방식 (원리 이해용)
char 배열에 각 문자와 \0을 직접 넣어주는 방식입니다. 매우 번거롭지만 원리를 이해하기에는 좋습니다.
char str[4] = {'c', 'a', 't', '\0'};
방법 2: 큰따옴표를 이용한 초기화 (실제 사용 방식)
큰따옴표(" ")로 문자열을 감싸서 초기화하면, 컴파일러가 알아서 문자들을 배열에 넣고 마지막에 \0을 자동으로 추가해 줍니다. 훨씬 편리하며, 실제로 이 방법을 사용합니다.
char str1[10] = "hello"; // 크기가 10인 배열에 "hello"를 저장. 남는 공간은 비어있음.
char str2[] = "world"; // 초기값의 길이에 맞춰 배열 크기가 자동으로 6으로 결정됨 ('w' 'o' 'r' 'l' 'd' '\\0')
3. 문자열 입출력
출력: printf 와 %s
printf 함수에서 %s 서식 지정자를 사용하면, 해당 char 배열의 시작 주소부터 \0을 만날 때까지 모든 문자를 출력해 줍니다.
printf("인사말: %s\n", str1);
입력 1: scanf 와 %s (주의가 필요!)
scanf로도 문자열을 입력 받을 수 있습니다. 한 가지 중요한 점은, 배열의 이름은 그 자체로 배열의 시작 '주소'를 의미하기 때문에 & 기호를 붙이지 않는다는 것입니다.
scanf("%s", str1); // &str1이 아님!
하지만 scanf는 두 가지 큰 단점이 있습니다:
- 공백 문자(스페이스, 탭, 엔터)를 만나면 입력이 끝난 것으로 간주합니다. "Hong Gildong"을 입력해도 "Hong"만 저장됩니다.
- 배열의 크기를 확인하지 않습니다. char str[5] 배열에 100글자를 입력하면, 배열의 경계를 넘어 다른 메모리 공간을 침범하는 '버퍼 오버플로우' 라는 심각한 보안 문제를 일으킬 수 있습니다.
입력 2: fgets 함수 (안전한 방법)
이런 단점을 보완하기 위해, 문자열을 입력받을 때는 fgets 함수를 사용하는 것이 훨씬 안전하고 좋습니다.
fgets(저장할_배열, 최대_입력_크기, stdin);
- stdin 은 'Standard Input', 즉 표준 입력(키보드)을 의미합니다.
- 최대_입력_크기 를 지정할 수 있어 버퍼 오버플로우를 막아줍니다. 보통 sizeof(배열이름)을 사용합니다.
- fgets는 한 줄 전체를 읽어오며, 사용자가 누른 Enter키(\n)까지 함께 저장합니다.
#include <stdio.h>
int main(void)
{
char greeting[30];
printf("인사말을 입력하세요 (29자 이내): ");
fgets(greeting, sizeof(greeting), stdin);
printf("입력하신 인사말: %s", greeting); // fgets는 \\n까지 저장해서 줄바꿈이 두 번 될 수 있음
return 0;
}
4. 문자열을 다루는 연장통 - <string.h> 라이브러리
C언어는 문자열을 복사하거나, 길이를 재거나, 두 문자열을 비교하는 등의 유용한 함수들을 string.h라는 헤더 파일에 모아두었습니다. 이 함수들을 사용하려면 코드 상단에 #include <string.h>를 추가해야 합니다.
- strlen(문자열) : 문자열 길이 구하기
\0을 제외한 순수한 글자의 개수를 반환합니다.
int len = strlen("hello"); // len에는 5가 저장됨 - strcpy(복사받을_배열, 원본_문자열) : 문자열 복사하기
strcpy는 'string copy'의 약자입니다. char name[10]; name = "홍길동"; 과 같은 대입은 불가능하므로, 복사 시에는 반드시 이 함수를 사용해야 합니다.
char dest[20];
strcpy(dest, "hello world"); - strcmp(문자열1, 문자열2) : 문자열 비교하기
'string compare'의 약자입니다. 두 문자열의 내용이 같은지 비교합니다. ( if (str1 == str2) 와 같은 비교는 불가능!)- 두 문자열이 완전히 같으면 0을 반환합니다.
- 문자열1이 사전 순으로 앞서면 음수를, 뒤에 있으면 양수를 반환합니다. if (strcmp(str1, "admin") == 0) { // 두 문자열이 같다면... }
5. [도전! 프로그래밍] 간단한 로그인 프로그램
문자열 처리 함수를 연습하기에 좋은 로그인 프로그램을 만들어 봅시다.
요구사항:
- 프로그램 코드 안에 올바른 아이디와 비밀번호를 char 배열로 미리 저장해 둡니다. (예: char correct_id[] = "my_id";)
- 사용자에게 아이디와 비밀번호를 입력받습니다.
- strcmp 함수를 사용하여 사용자가 입력한 값과 코드 안에 저장된 값이 모두 일치하는지 확인합니다.
- 결과에 따라 "로그인 성공!" 또는 "아이디 또는 비밀번호가 틀렸습니다." 라는 메시지를 출력합니다.
이번 장 정리
- C언어의 문자열은 char 배열이며, 반드시 끝에 널 문자(\0) 가 있어야 합니다.
- 문자열 초기화는 " " (큰따옴표)를 사용하는 것이 편리하며, 이 경우 \0은 자동으로 추가됩니다.
- 안전한 문자열 입력을 위해서는 scanf보다 fgets 함수를 사용하는 것이 좋습니다.
- 문자열의 길이 계산(strlen), 복사(strcpy), 비교(strcmp) 등은 <string.h> 헤더에 있는 표준 함수를 사용해야 합니다.
- 두 문자열의 내용이 같은지 비교할 때는 ==가 아닌 strcmp(str1, str2) == 0 형태로 확인해야 합니다.
이제 여러분은 숫자뿐만 아니라 텍스트 데이터까지 자유롭게 다룰 수 있게 되었습니다. 다음 장에서는 이름, 학번, 학점처럼 서로 다른 종류의 데이터들을 하나의 의미 있는 단위로 묶어주는 '구조체'에 대해 배우며, 더 복잡한 데이터를 체계적으로 관리하는 법을 익혀보겠습니다.
여기까지 이해가 잘 되는 사람은 능력자입니다. 이해가 잘 되지 않는 부분이 있는 것이 일반적인 사람입니다.
능력자들은 능력을 잘 즐기면 되구요. 일반적인 사람들은 열심히 노력하면 됩니다. 필자도 일반적인 사람 중에 하나였습니다.
모두 화이팅해서 열심히 공부하구요. 궁금한건 언제든 질문해주세요
'C, C++ 언어' 카테고리의 다른 글
| C언어 기초 14. 포인터 기초 (0) | 2025.10.20 |
|---|---|
| C 언어 기초 13. 배열 (0) | 2025.10.19 |
| C언어 기초 12. 함수 (0) | 2025.10.17 |
| C언어 기초 11. break 와 continue (0) | 2025.10.16 |
| C언어 기초 10. 반복문 while 문과 do-while 문 (0) | 2025.10.15 |