Phase 2 · C언어 핵심 · 활용

문자열 — 문자 데이터 처리

C언어에는 편리한 string 자료형이 없습니다. 대신 문자를 나열한 배열에 널 문자('\0')를 찍어 문자열을 만듭니다. 문자열의 내부 원리를 꿰뚫고 포인터와 함께 자유롭게 요리해 봅니다.

예상 학습 시간 : 150분
난이도 : ★★★★☆ 중·고급
사전 지식 : 배열, 포인터 기초
다음 단계 : 구조체
01

학습 목표

1
작은따옴표(문자 'A')와 큰따옴표(문자열 "ABC")의 차이를 이해한다.
2
문자열의 끝을 알리는 널 문자('\0')의 역할을 이해한다.
3
scanf의 공백 이슈를 피하기 위해 fgets()를 사용해 문자열을 입력받는다.
4
<string.h>strlen, strcpy, strcmp, strcat 함수를 활용한다.
5
포인터가 '\0'을 만날 때까지 문자열을 순회하는 원리를 파악한다.
6
2차원 char 배열을 이용해 여러 명의 이름(문자열 리스트)을 관리한다.
02

문자와 문자열은 완전히 다르다

문자 한 개를 저장할 때는 작은따옴표를 쓰고 char 변수에 담습니다.
하지만 문자가 여러 개 이어진 '문자열'은 큰따옴표를 쓰고 배열에 담아야 합니다.

⚙️ C
// 문자 1개 (작은따옴표, 서식 %c)
char ch = 'A'; 

// 문자열 (큰따옴표, 배열, 서식 %s)
char str[] = "ABC";

참고로 C언어에서 문자는 내부적으로 숫자(ASCII 코드)로 저장됩니다.
예를 들어 'A'는 컴퓨터 내부에 65라는 숫자로 기억됩니다.

03

문자열의 정체와 널 문자('\0')

C언어에서 "HELLO"라고 적으면 컴퓨터는 H, E, L, L, O 다섯 글자 뒤에, 이 문자열이 여기서 끝난다는 표시기인 '\0'(널 문자)를 몰래 끼워 넣습니다.

str[0]
H
str[1]
E
str[2]
L
str[3]
L
str[4]
O
str[5]
\0
배열 크기 지정 시 주의

글자는 5글자지만 배열 공간은 반드시 최소 6칸이 필요합니다.
따라서 char str[5] = "HELLO"; 라고 쓰면 '\0'이 잘려나가 심각한 오류가 발생할 수 있습니다.

04

공백을 포함하는 문자열 입력

우리가 쓰던 scanf("%s")는 치명적인 단점이 있습니다. 띄어쓰기를 만나면 입력을 멈춰버립니다.
"홍길동 선생님"을 치면 "홍길동"만 저장됩니다.
이를 해결하기 위해 안전한 fgets()를 사용합니다.

⚙️ C
#include <stdio.h>
#include <string.h>

int main() {
    char name[100];
    printf("이름을 입력하세요 : ");

    // stdin(키보드)에서 name 크기만큼 공백 포함하여 입력받음
    fgets(name, sizeof(name), stdin);

    // fgets는 엔터(\n)까지 저장하므로, 엔터를 \0으로 덮어씌워 제거하는 고급 스킬
    name[strcspn(name, "\n")] = '\0';

    printf("입력결과 : %s\n", name);
    return 0;
}
05

자주 쓰는 문자열 제어 함수 (<string.h>)

함수 기능 및 예시
strlen(str) 문자열의 실제 길이를 구합니다. (널 문자 제외)
strlen("Hello") → 5 반환
strcpy(dest, src) 문자열을 복사합니다. 배열은 = 기호로 덮어씌울 수 없습니다!
strcpy(name, "홍길동"); (name 배열에 홍길동 덮어쓰기)
strcat(dest, src) 문자열 뒤에 다른 문자열을 이어 붙입니다.
strcat(greet, " World");
06

가장 중요한 문자열 비교: strcmp

문자열은 == 로 비교하면 절대 안 됩니다!

if (password == "1234") 라고 쓰면 글자 내용이 아니라 메모리 주소가 같은지 비교해 버립니다. 내용을 검사하려면 무조건 strcmp()를 써야 합니다.

⚙️ C
char input[] = "1234";

// strcmp는 두 문자열이 완벽히 같으면 0을 반환합니다.
if (strcmp(input, "1234") == 0) {
    printf("비밀번호가 일치합니다!\n");
}
07

문자열과 포인터의 밀월 관계

문자열 배열의 이름도 어차피 배열 시작 주소입니다. 따라서 문자(char)를 가리키는 포인터 변수에 담아서 한 칸씩 전진시킬 수 있습니다.

⚙️ C
char str[] = "Hello";
char *ptr = str; // 포인터가 H를 가리킴

// 포인터가 가리키는 값이 널 문자('\0')가 아닐 때까지 반복
while (*ptr != '\0') {
    printf("%c\n", *ptr);  // 글자 출력
    ptr++;                // 다음 칸으로 이동!
}

이것이 C언어가 내부적으로 문자열 함수들(strlen, strcpy 등)을 구현해 놓은 기본 원리입니다.

08

2차원 배열을 이용한 문자열 리스트

문자 한 줄이 1차원 배열이라면, 여러 명의 이름을 저장하려면 2차원 배열을 써야 합니다.
char names[5][20]; 이라고 쓰면 "최대 19글자(+널문자)를 담을 수 있는 문자열을 총 5개 만든다"는 뜻입니다.

⚙️ C
char names[3][20] = {
    "홍길동", 
    "김철수", 
    "이영희"
};

// names[0] 자체가 하나의 문자열 시작 주소로 동작합니다.
printf("첫 번째 학생 : %s\n", names[0]);
09

STEP 10 최종 프로젝트

🚀 Mission

학생 이름 검색(Search) 시스템

지금까지 배운 2차원 배열(목록 관리), fgets()(입력), strcmp()(비교)를 모두 결합하여 실제 데이터베이스 검색과 유사한 학생 조회 프로그램을 만듭니다.

  • [1] 2차원 배열 names[5][50]을 선언합니다.
  • [2] for문과 fgets()로 5명의 이름을 등록합니다.
  • [3] 찾고 싶은 사람의 이름을 입력받습니다.
  • [4] 반복문을 돌면서 strcmp() == 0 인 데이터가 있는지 스캔하고, 있으면 몇 번 학생인지 출력합니다.
10

STEP 10 완료 체크리스트

문자('A')와 문자열("ABC")의 메모리 구조 차이를 이해한다.
문자열 배열 크기는 무조건 널 문자('\0') 1칸을 추가로 고려해야 함을 인지한다.
scanf 대신 fgets를 사용하여 공백이 포함된 안전한 문자열을 입력받을 수 있다.
strcmp 함수를 이용해 문자열이 같은지 검사하고 0이 나오면 같다는 사실을 이해한다.
포인터를 이용해 문자열의 각 문자에 접근하고 순회할 수 있다.
2차원 문자 배열을 통해 여러 개의 문자열 데이터를 관리할 수 있다.
C언어 핵심 문법(Phase 2) 수료를 축하합니다!

변수에서 시작해 제어문, 함수, 포인터를 거쳐 문자열 처리까지 배웠습니다. 이제 C언어의 원초적인 문법은 모두 갖추어졌습니다. STEP 11부터는 이것들을 하나의 덩어리로 묶어 객체지향의 근간이 되는 '구조체'를 배우며, 본격적인 실무 애플리케이션 개발 단계(Phase 3)로 진입합니다.

이전 : Step 09 Step 11 : 구조체