문자열(string)은 글자를 차례로 늘어놓은 값입니다. C에는 문자열 자료형이 따로 없어, char 배열에 글자를 하나씩 넣고 끝에 널 문자(null character) '\0'을 붙여 문자열로 씁니다. 끝 표시가 있어야 글자가 어디까지인지 알 수 있기 때문입니다. 시험은 글자 수와 칸 수의 차이, 널 문자에서 멈추는 반복과 출력을 묻습니다. 아래 그림은 "OS"가 칸 셋에 들고, 글자를 세는 반복이 널 문자에서 멈추는 모습입니다.
1널 문자로 끝나는 char 배열
char s[] = "OS";는 칸 셋을 만들어 'O' · 'S' · '\0'을 넣습니다. 큰따옴표 문자열 끝에는 널 문자가 저절로 붙어, 칸 수는 글자 수 + 1입니다.
널 문자는 값이 0인 글자로, 문자열이 끝나는 자리를 알립니다.
| 식 | 값 | 까닭 |
|---|---|---|
sizeof s | 3 | 칸 수(char 한 칸은 1바이트) |
strlen(s) | 2 | 널 문자 앞까지의 글자 수 |
s[2] | '\0' | 끝 표시, 값 0 |
strlen은 <string.h>에 있는 함수입니다. 작은따옴표 'O'는 글자 하나이고, 큰따옴표 "O"는 'O'와 '\0' 두 칸입니다.
char s[10] = "OS";처럼 칸이 남으면 남은 칸은 모두 '\0'으로 채워집니다.
2널 문자까지 읽는다 — %s와 반복
printf("%s", s)는 첫 칸부터 널 문자 앞까지 찍고, 글자를 다루는 반복도 while (s[i] != '\0')처럼 널 문자에서 멈춥니다.
그래서 가운데 칸에 '\0'을 넣으면 문자열이 거기서 끝납니다. "OS"에서 s[1] = '\0'; 뒤 %s는 O만 찍습니다.
글자 하나는 s[i]로 짚고 %c로 찍습니다. 글자는 정수이기도 해서, 소문자 'a'(97)에서 32를 빼면 대문자 'A'(65)가 됩니다(자료형과 형 변환).
예제
글자 l을 세고 가운데 칸에 널 문자를 넣는 코드입니다. 찍힐 값을 먼저 정해 보세요.
#include <stdio.h>
int main(void) {
char s[] = "Hello";
int i = 0, n = 0;
while (s[i] != '\0') {
if (s[i] == 'l') {
n++;
}
i++;
}
s[2] = '\0';
printf("%s %d\n", s, n);
return 0;
}
실행 결과 보기
He 2반복은 H · e · l · l · o를 지나 s[5]의 '\0'에서 멈추고, l이 둘이라 n은 2입니다.
s[2]에 '\0'을 넣으면 문자열은 s[0] · s[1]의 He에서 끝나, %s는 He만 찍습니다. 뒤 칸의 l · o는 남아 있지만 찍히지 않습니다.
같은 코드를 Java·Python으로
| C | Java | Python | |
|---|---|---|---|
| 문자열 | char 배열 + '\0' | String | str |
| 길이 | strlen(s) | s.length() | len(s) |
| 한 글자 | s[1] | s.charAt(1) | s[1] |
| 한 글자 바꾸기 | s[1] = 'a'; 됨 | 안 됨 | 안 됨(TypeError) |
| 잇기 | 함수로(32단원) | + | + |
| char 크기 | 1바이트 | 2바이트 | char 없음 — 길이 1인 str |
Java·Python 문자열은 끝에 널 문자를 두지 않고 길이를 따로 압니다. 한 번 만든 문자열은 바꿀 수 없어 새 문자열을 만듭니다.
시험 포인트
- 필기: C 문자열은 끝에 널 문자
'\0'이 붙어, 크기를 비운char s[] = "…";는 칸 수가 글자 수 + 1입니다.sizeof는 바이트 수라 char 배열에서는 칸 수와 같고,strlen은 널 문자 앞까지의 글자 수입니다.%s와 문자열 반복은 널 문자에서 멈춥니다. - 실기: 출력을 그대로 씁니다. 가운데 칸에
'\0'을 넣으면%s가 거기서 멈추는 것과, 32를 빼고 더하는 대소문자 바꾸기를 따라갑니다. 이름은 널 문자(Null Character), 글자 수를 돌려주는 함수는strlen으로 씁니다.
확인 문제
1. char s[] = "DB2026";일 때 sizeof s와 strlen(s)의 값을 차례로 고르세요.
- ① 6, 6
- ② 7, 6
- ③ 6, 7
- ④ 7, 7
정답
②입니다. 글자가 여섯이고 끝에 널 문자가 붙어 칸은 일곱이며, strlen은 널 문자 앞까지 세어 6입니다.
- ① 널 문자 칸을 빼고 칸 수를 셌습니다.
- ③ 둘을 바꿨습니다. 칸 수가 글자 수보다 하나 많습니다.
- ④ strlen은 널 문자를 세지 않습니다.
2. 예제 코드의 12번 줄에서 s[2]를 s[4]로 바꿨습니다. 출력을 그대로 쓰세요. 답을 끝까지 쓴 뒤 정답을 펼치세요.
#include <stdio.h>
int main(void) {
char s[] = "Hello";
int i = 0, n = 0;
while (s[i] != '\0') {
if (s[i] == 'l') {
n++;
}
i++;
}
s[4] = '\0';
printf("%s %d\n", s, n);
return 0;
}
정답
받는 답:
Hell 2s[4]는 다섯째 칸 o입니다. 그 자리에 '\0'이 들어가 %s는 s[0]부터 s[3]까지 Hell을 찍습니다. n은 반복이 먼저 끝나 2 그대로입니다.
- 틀리는 꼴
Hel 2: 인덱스를 1부터 세어 s[4]를 넷째 칸으로 봤습니다. - 틀리는 꼴
Hello 2: s[4]의 o가'\0'으로 바뀌는 것을 놓쳤습니다. 대입은 그 칸의 글자를 바꾸고,%s는'\0'에서 멈춥니다.
3. 다음 코드를 바퀴마다 줄여 적은 표입니다. (가)·(나)를 채운 뒤 출력을 그대로 쓰세요. 답을 끝까지 쓴 뒤 정답을 펼치세요.
| i | s[i] | 조건 s[i] >= 'a' | 바퀴가 끝난 뒤 s |
|---|---|---|---|
| 0 | 'a' | 참 | ABc |
| 1 | 'B' | (가) | ABc |
| 2 | 'c' | 참 | (나) |
| 3 | '\0' | 반복 끝 |
#include <stdio.h>
int main(void) {
char s[] = "aBc";
int i = 0;
while (s[i] != '\0') {
if (s[i] >= 'a') {
s[i] = s[i] - 32;
}
i++;
}
printf("%s\n", s);
return 0;
}
정답
(가) 거짓 · (나) ABC이고, 출력은 다음과 같습니다.
ABC'B'는 66이라 'a'(97)보다 작아 그대로 두고, 소문자 'a' · 'c'만 32를 빼 대문자가 됩니다.
- 틀리는 꼴
ABc: 마지막 칸'c'를 놓쳤거나, 대문자 B에서 반복이 멈춘다고 봤습니다. if가 거짓이어도 반복은 다음 칸으로 가고,'\0'을 만나는 i가 3일 때 끝납니다.
4. 다음 코드의 출력을 그대로 쓰세요. 답을 끝까지 쓴 뒤 정답을 펼치세요.
#include <stdio.h>
int main(void) {
char s[] = "abcde", t;
int i = 0, j = sizeof s - 2;
while (i < j) {
t = s[i];
s[i] = s[j];
s[j] = t;
i++;
j--;
}
printf("%s %d\n", s, i);
return 0;
}
정답
받는 답:
edcba 24번 줄은 char 배열 s와 char 변수 t를 함께 만듭니다. sizeof s는 널 문자까지 6칸이라 j는 4, 마지막 글자 e의 인덱스입니다.
i와 j가 양 끝에서 다가오며 (0, 4) · (1, 3) 칸을 맞바꾸고, i와 j가 둘 다 2가 되면 2 < 2가 거짓이라 멈춥니다. 가운데 c는 그대로입니다.
- 틀리는 꼴
dcbae 2:sizeof s를 글자 수 5로 보아 j를 3에서 시작했습니다. sizeof는 널 문자 칸까지 세어 6입니다. - 틀리는 꼴
edcba 3: i와 j가 2일 때도 한 바퀴 더 돈다고 봤습니다.2 < 2는 거짓이라 i는 2에서 멈춥니다.
5. 다음 (가)·(나)를 쓰세요. (가)는 한글 이름과 영문으로, (나)는 C 함수 이름 그대로 씁니다. 답을 끝까지 쓴 뒤 정답을 펼치세요.
- (가)
"DB"를 char 배열에 넣으면'D'·'B'다음 칸에 저절로 들어가, 글자가 여기서 끝났음을 알리는 값 0의 글자 - (나)
<string.h>에 있으며, 그 값 0의 글자 앞까지 글자가 몇 개인지 돌려주는 함수
정답
받는 답: (가) 널 문자(Null Character) · (나) strlen
(가)는 '끝에 저절로 들어가는 값 0', (나)는 '그 앞까지 센 글자 수'가 실마리입니다.
- 같은 이름의 다른 꼴:
'\0'만 쓴 꼴 — 코드에 쓰는 꼴입니다. 이름을 물었으니 널 문자(Null Character)로 씁니다. - 틀리는 꼴
sizeof— (나)에: 함수가 아니라 연산자이고, 널 문자 칸까지 센 바이트 수(char 배열은 칸 수)를 냅니다.
처음이라면: C 언어 과목(준비 중)의 '문자열은 널 문자로 끝나는 char 배열' · 'strlen · strcpy · strcat · strcmp' 레슨에서 같은 규칙을 처음부터 천천히 봅니다.