[ C언어 ] 14. 문자열
Table of Contents
1. 개요
char 들의 배열로 사용되는 '문자열'은, int 나 float 등의 배열과 조금 다른 특성과 쓰임을 가지고 있습니다. 이에 따라 C언어에서는 문자열에 사용할 수 있는 서식문자나 함수등 여러 가지 요소들을 제공하고 있으며, 이 글에서는 이런 문자열에 대해 소개하고 있습니다. 변수형 char에 대해 기억이 나지 않으신다면 char 설명 을 보고 오시는 걸 추천합니다.
2. 문자열의 입출력
1. 기본 입출력
배열의 원소 하나하나에 입력을 받는 int 배열과 달리 문자열은 한번에 입력, 출력을 할 수 있습니다. 대표적인 형식은 아래와 같습니다.
1
2
3
|
//code by RiKang, weeklyps.com
scanf("%s",문자열의 주소);
printf("%s",문자열의 주소);
|
cs |
문자열의 주소는 어렵게 생각할 것 없는 것이, char 배열을 선언하면 배열의 이름이 곧 문자열의 주소를 의미하게 됩니다.
1
2
3
4
5
6
7
8
9
|
//code by RiKang, weeklyps.com
#include <stdio.h>
int main(void) {
char a[105];
scanf("%s",a);
printf("%s",a);
return 0;
}
|
cs |
입력 : as;sdf\\ad -> 출력 : as;sdf\\ad
변수의 이름과 달리 배열의 이름은 그 자체로 주소를 나타내기 때문에, 변수를 입력 받을 때와 달리 &를 쓰지 않는다는 점을 주의하시길 바랍니다.
2. scanf("%s",문자열의 주소);
scanf 에서 %s를 사용하면, 입력에 띄워 쓰기나 줄 바꿈(엔터)이 들어올 때까지 문자열을 입력 받습니다. 따라서 아래와 같은 프로그램을 코딩하시고 "let me"라는 입력을 넣어 보시면, a 에는 "let", b에는 "me" 가 들어간다는 걸 확인하실 수 있습니다.
1
2
3
4
5
6
7
8
9
10
|
//code by RiKang, weeklyps.com
#include <stdio.h>
int main(void) {
char a[105];
char b[105];
scanf("%s %s",a,b);
printf("a : %s\nb : %s",a,b);
return 0;
}
|
cs |
입력 : let me -> 출력 : a : let\nb : me
1
2
3
4
5
6
7
8
9
10
|
//code by RiKang, weeklyps.com
#include <stdio.h>
int main(void) {
char a[105], b[105], c[105];
scanf("%s%s%s",a,b,c);
printf("%s\n",a);
printf("%s\n",b);
printf("%s\n",c);
return 0;
}
|
cs |
입력 : i am fine -> 출력 : i\nam\nfine
3. 문자열의 주소의 다른 표현
문자열의 주소는 첫 번째 문자의 주소, 즉, a[0] 의 주소와 일치합니다. 따라서 아래와 같이 입력하여도 똑같이 실행 가능합니다.
1
2
3
4
5
6
7
8
|
//code by RiKang, weeklyps.com
#include <stdio.h>
int main(void) {
char a[105];
scanf("%s",&a[0]);
printf("%s\n",&a[0]);
return 0;
}
|
cs |
입력 : ace -> 출력 : ace
또한 아래와 같은 식으로 문자열의 주소를 다른 주소로 잡으면 중간부터 출력 되기도 합니다.
1
2
3
4
5
6
7
8
|
//code by RiKang, weeklyps.com
#include <stdio.h>
int main(void) {
char a[105];
scanf("%s",&a[0]);
printf("%s\n",&a[1]);
return 0;
}
|
cs |
입력 : ace -> 출력 : ce
3. 문자열 초기화
문자열에 원하는 값을 넣어주고 싶다면, 배열에 초기값을 넣는 것처럼 {문자, 문자, ...} 의 형식도 가능하고, "문자열"의 형식도 가능합니다.
1
2
3
4
5
6
7
8
9
10
|
//code by RiKang, weeklyps.com
#include <stdio.h>
int main(void) {
char a[105]={'t','a','d','s',};
char b[105]="tads";
printf("%s\n",a);
printf("%s",b);
return 0;
}
|
cs |
문자 변수 하나를 쓸 때는 작은 따옴표를, 문자열을 쓸 때는 큰 따옴표를 사용합니다.
다음으론 배열의 크기를 지정해주지 않는 경우입니다. 이때는, 입력해준 문자의 개수에 따라 컴파일러가 알아서 크기를 설정하도록 되어있습니다.
1
2
3
4
5
6
7
|
//code by RiKang, weeklyps.com
#include <stdio.h>
int main(void) {
char a[]="ace";
printf("%s\n",a);
return 0;
}
|
cs |
3. NULL 문자
C언어의 문자열에는 마지막 문자 다음에 NULL 문자 (아스키 코드값 0) 가 들어간다는 약속이 있습니다. 이로 인해, 컴파일러 입장에서는 문자열을 앞부터 순서대로 읽다가 중간에 NULL 문자가 나오면, "문자열이 끝났구나!"라는 걸 알 수 있습니다.
한 번 아래와 같은 문자열을 생각해 보겠습니다.
얼핏 보면, 8개의 문자가 들어간 문자열로 처리할 것 같지만, 출력해보면 "ace"가 출력됩니다. 컴파일러가 NULL을 만나자마자 문자열이 끝났다고 판단하고, 결국 첫 번째 NULL 뒤에 있는 변수들은 비어있는 셈 치기 때문이지요.
1
2
3
4
5
6
7
8
|
//code by RiKang, weeklyps.com
#include <stdio.h>
int main(void) {
char a[105]={'a','c','e',NULL,'b', 'd', NULL, 'a', };
printf("%s\n",a);
return 0;
}
|
cs |
-> 출력 : ace
문자열의 끝에는 이 NULL 문자가 반드시 있어야 합니다. 따라서 문자 3개를 저장할 문자열이라고 해도, char a[3]; 이런 식으로 선언하면 에러가 날 수 있습니다. NULL 문자가 들어갈 자리가 없기 때문입니다. 이로 인해 문자열을 선언할 때에는 저장할 문자열의 최대 길이 + 1 정도의 여유를 두는 것이 일반적입니다.
1
2
3
4
5
6
7
8
9
|
//code by RiKang, weeklyps.com
#include <stdio.h>
int main(void) {
char a[3]="ace";
char b[4]="ace";
printf("%s\n",a); // NULL 이 없기 때문에 제대로 처리가 안될 수 있다.
printf("%s\n",b);
return 0;
}
|
cs |
4. gets() 와 puts()
scanf() 와 printf() 이외에도 문자열을 입출력 할 수 있는 함수들이 존재하는데, 이 곳에서는 그 중 gets()와 puts()를 소개합니다.
gets(문자열의 주소);
gets를 위와 같이 사용하면, 줄 바꿈(엔터)가 들어오기 전까지 문자열을 입력 받습니다. 즉, scanf에서 %s로 입력받을 떄와 달리 띄워 쓰기도 문자열에 포함됩니다.
puts(문자열의 주소);
문자열을 출력하고 줄 바꿈을 합니다. printf() 는 \n 을 써주지 않으면 줄 바꿈을 하지 않는다는 점에서 차이점을 보입니다.
1
2
3
4
5
6
7
8
9
|
//code by RiKang, weeklyps.com
#include <stdio.h>
int main(void) {
char a[105];
gets(a);
puts(a);
return 0;
}
|
cs |
입력 : let me introduce my self -> 출력 : let me introduce my self\n
1
2
3
4
5
6
7
8
9
|
//code by RiKang, weeklyps.com
#include <stdio.h>
int main(void) {
char a[105];
scanf("%s",a);
printf("%s",a);
return 0;
}
|
cs |
입력 : let me introduce my self -> 출력 : let
위의 두 프로그램을 만들어 놓고 여러 가지 입력을 넣어보시면 차이점을 보다 명확히 알 수 있습니다.
5. strlen()
strlen() 은 문자열의 길이를 반환해주는 함수입니다.
strlen(문자열의 주소);
이 strlen 함수는 이전에 쓰인 함수들과 달리 stdio.h 가 아니라 string.h 에 저장되어 있기 때문에, strlen 을 쓰기 위해서는 전처리문 #include <string.h> 을 꼭 써주어야 합니다. 일단 아래의 코드를 따라 해보겠습니다.
1
2
3
4
5
6
7
8
9
10
11
12
|
//code by RiKang, weeklyps.com
#include <stdio.h>
#include <string.h>
int main(void) {
char a[105];
scanf("%s",a);
int b;
b=strlen(a);
printf("a의 길이 : %d",b);
return 0;
}
|
cs |
입력 : let -> 출력 : a의 길이 : 3
입력 : introduce -> 출력 : a의 길이 : 9
strlen 은 길이를 반환하기 때문에, 이와 같이 정수형 변수를 통해 그 값을 저장할 수 있습니다. 또한 이를 활용해 문자열을 순회하는 것이 가능합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
//code by RiKang, weeklyps.com
#include <stdio.h>
#include <string.h>
int main(void) {
char a[105];
scanf("%s",a);
int b;
b=strlen(a);
for(int i=0; i<b; i++){
printf("a의 %d 번째 문자 : %c\n", i, a[i]);
}
return 0;
}
|
cs |
아래와 같은 형식도 가능합니다.
1
2
3
4
5
6
7
8
9
10
11
12
|
//code by RiKang, weeklyps.com
#include <stdio.h>
#include <string.h>
int main(void) {
char a[105];
scanf("%s",a);
for(int i=0; i<strlen(a); i++){
printf("a의 %d 번째 문자 : %c\n", i, a[i]);
}
return 0;
}
|
cs |
strlen 함수는 , scanf 나 printf 와 달리 무언가를 반환해주는 함수이며, 따라서, 그 반환값을 받지 않고 그대로 두면 에러가 발생합니다.
1
2
3
4
5
6
7
8
9
10
|
//code by RiKang, weeklyps.com
#include <stdio.h>
#include <string.h>
int main(void) {
char a[105];
scanf("%s",a);
strlen(a);
return 0;
}
|
cs |
strlen(a)는 정수형 변수를 반환하는데, 그걸 어떠한 형태로도 사용하지 않았기 때문에 에러가 발생하는 것이지요. 결국 아래의 코드가 에러가 나는 이유와 비슷한 원리라고 볼 수 있습니다.
1
2
3
4
5
6
7
8
9
|
//code by RiKang, weeklyps.com
#include <stdio.h>
#include <string.h>
int main(void) {
char a[105];
scanf("%s",a);
3;
return 0;
}
|
cs |
6. 문제
(4) [BOJ 1157] 단어 공부
(5) [BOJ 8958] OX퀴즈
(8) [BOJ 10798] 세로읽기