35. 문자열 복사/결합
1. 키워드
strcpy
(String Copy)strcat
(String Concatenate)
2. 문자열을 복사하고 붙이기
- 이번에는 문자열을 다른 곳으로 복사하는 방법과 두 문자열을 붙이는 방법을 알아보자
3. 문자열 복사하기
- 문자열은 다른 배열이나 포인터(메모리)로 복사할 수 있다.
string.h
헤더 파일에 선언되어 있는strcpy
함수를 사용하면 문자열을 다른 곳으로 복사할 수 있다.
#define _CRT_SECURE_NO_WARNINGS // scanf 보안 경고로 인한 컴파일 에러 방지
#include <stdio.h>
#include <string.h> // strcpy 함수가 선언된 헤더 파일
int main()
{
char s1[10] = "Hello"; // 크기가 10인 char 타입 배열을 선언하고 문자열 할당
char s2[10]; // 크기가 10인 char 타입 배열을 선언
strcpy(s2, s1); // s1의 문자열을 s2로 복사
printf("%s\n", s2);
return 0;
}
// Hello
- 먼저
"Hello"
문자열이 들어있는 배열s1
과 아무것도 들어있지 않은 배열s2
를 선언했다. - 그리고
strcpy(s2, s1)
와 같이strcpy
함수에 복사된 결과가 저장될 문자열과 복사할 문자열을 넣는다. - 이렇게 하면
s2
에s1
의 문자열이 복사된다.
- 복사된 결과가 저장될 배열의 크기는 반드시
NULL
까지 들어갈 수 있어야 한다. - 크기가 더 작다면 복사가 되더라도 문자열이 정상적으로 출력되지 않는다.
- 따라서
"Hello"
문자열이 복사되려면 배열의 크기는 최소한6
이 되어야 한다.
- 지금까지 문자 배열(
char
타입 배열)을 사용하여 문자열을 복사했다. - 그러면 문자열 포인터에 복사하면 어떻게 되는지 확인해 보자.
#define _CRT_SECURE_NO_WARNINGS // strcpy 보안 경고로 인한 컴파일 에러 방지
#include <stdio.h>
#include <string.h> // strcpy 함수가 선언된 헤더 파일
int main()
{
char *s1 = "Hello"; // 문자열 포인터
char *s2 = ""; // 문자열 포인터
strcpy(s2, s1); // 실행 에러
printf("%s\n", s2);
return 0;
}
strcpy
함수로 문자열 포인터s1
을 문자열 포인터s2
로 복사했다.- 복사가 될 것 같지만 실행을 해보면 에러가 발생한다.
- 왜냐하면
s2
에 저장된 메모리 주소는 복사할 공간도 없을 뿐더러 읽기만 할 수 있고, 쓰기가 막혀있기 때문이다.
문자열과 읽기 전용 메모리
char *s1 = "Hello"; char *s2 = "";
와 같이 문자열 포인터에 할당된 문자열은 읽기 전용이다.- 왜냐하면 C 컴파일러는 문자열 포인터에 할당한 문자열 리터럴을 실행 파일의 읽기 전용 데이터 섹션(데이터 세그먼트)에 배치하기 때문이다.
- 따라서 실행 파일이 실행된 뒤에는 읽기 전용 메모리가 되며 쓰기를 할 수 없다.
- 다음은 각 OS별 읽기 전용 데이터 섹션 이름이다.
1] Windows PE
.rdata
2] 리눅스 ELF
.rodata
3] OSX
__TEXT
,__cstring
- 문자열 포인터에 문자열을 복사하려면 문자열이 들어갈 공간을 따로 마련해야 한다.
- 따라서 다음과 같이
malloc
함수로 메모리를 할당한 뒤 문자열을 복사한다.
#define _CRT_SECURE_NO_WARNINGS // strcpy 보안 경고로 인한 컴파일 에러 방지
#include <stdio.h>
#include <string.h> // strcpy 함수가 선언된 헤더 파일
#include <stdlib.h> // malloc, free 함수가 선언된 헤더 파일
int main()
{
char *s1 = "Hello"; // 문자열 포인터
char *s2 = malloc(sizeof(char) * 10); // char 타입 10개 크기만큼 동적 메모리 할당
strcpy(s2, s1); // s1의 문자열을 s2로 복사
printf("%s\n", s2);
free(s2); // 동적 메모리 해제
return 0;
}
// Hello
char *s2 = malloc(sizeof(char) * 10);
처럼char
타입10
개 크기만큼 동적으로 메모리를 할당했다.- 이렇게 하면
strcpy
함수로s1
의 문자열을s2
에 복사해서 넣을 수 있다. - 문자열 사용이 끝났다면 반드시
free
함수로 동적 할당한 메모리를 해제한다.
4. 문자열 붙이기
string.h
헤더 파일에 선언되어 있는strcat
함수를 사용하면 문자열을 서로 붙일 수 있다.
#define _CRT_SECURE_NO_WARNINGS // strcat 보안 경고로 인한 컴파일 에러 방지
#include <stdio.h>
#include <string.h> // strcat 함수가 선언된 헤더 파일
int main()
{
char s1[10] = "world";
char s2[20] = "Hello"; // s2 뒤에 붙일 것이므로 배열 크기를 크게 만듦
strcat(s2, s1); // s2 뒤에 s1을 붙임
printf("%s\n", s2);
return 0;
}
// Helloworld
strcat(s2, s1)
과 같이strcat
함수에 최종 결과가 나올 문자열과 붙일 문자열을 넣는다.- 이렇게 하면
s2
뒤에s1
을 붙여서"Helloworld"
가 나온다. - 여기서 주의할 부분은 최종 결과가 나올 문자열의 배열 크기이다.
- 문자열을 붙이더라도
NULL
까지 들어갈 수 있도록(배열이 모자라지 않도록) 크기를 넉넉하게 만든다.
- 지금까지 배열 형태로 된 문자열을 붙였다.
- 그러면 문자열 포인터는 어떻게 붙이는지 확인해 보자.
#define _CRT_SECURE_NO_WARNINGS // strcat 보안 경고로 인한 컴파일 에러 방지
#include <stdio.h>
#include <string.h> // strcat 함수가 선언된 헤더 파일
int main()
{
char *s1 = "world"; // 문자열 포인터
char *s2 = "Hello"; // 문자열 포인터
strcat(s2, s1); // 실행 에러
printf("%s\n", s2);
return 0;
}
strcat
함수로 문자열 포인터s2
뒤에 문자열 포인터s1
을 붙였다.- 하지만 실행해 보면 에러가 발생한다.
- 문자열 포인터
s2
는 읽기 전용 메모리라서 문자열을 붙일 수 없다.
- 문자열을 붙이려면
s2
에 쓰기가 가능하도록malloc
함수로 동적 메모리를 할당하고, 문자열을 붙일 수 있도록 공간도 넉넉하게20
으로 설정해 준다.
#define _CRT_SECURE_NO_WARNINGS // strcpy 보안 경고로 인한 컴파일 에러 방지
#include <stdio.h>
#include <string.h> // strcat 함수가 선언된 헤더 파일
#include <stdlib.h> // malloc, free 함수가 선언된 헤더 파일
int main()
{
char *s1 = "world"; // 문자열 포인터
char *s2 = malloc(sizeof(char) * 20); // char 타입 20개 크기만큼 동적 메모리 할당
strcpy(s2, "Hello"); // s2에 "Hello" 문자열 복사
strcat(s2, s1); // s2 뒤에 s1을 붙임
printf("%s\n", s2);
free(s2); // 동적 메모리 해제
return 0;
}
// Helloworld
- 먼저
char *s2 = malloc(sizeof(char) * 20);
처럼char
타입20
개 크기만큼 동적으로 메모리를 할당한다. - 그리고 메모리가 할당된 문자열 포인터에는 문자열을
=
로 직접 할당할 수 없으므로strcpy
함수를 사용하여s2
에"Hello"
문자열을 복사한다. s2
가 준비되었으면strcat
함수로 문자열 포인터s2
뒤에 문자열 포인터s1
을 붙이면 된다.- 문자열 사용이 끝났다면 반드시
free
함수로 동적 할당한 메모리를 해제한다.
5. 배열 형태의 문자열을 문자열 포인터에 복사하기
- 이번에는 배열 형태의 문자열을 문자열 포인터에 복사해 보자.
#define _CRT_SECURE_NO_WARNINGS // strcpy 보안 경고로 인한 컴파일 에러 방지
#include <stdio.h>
#include <string.h> // strcpy 함수가 선언된 헤더 파일
#include <stdlib.h> // malloc, free 함수가 선언된 헤더 파일
int main()
{
char s1[10] = "Hello"; // 크기가 10인 char 타입 배열을 선언하고 문자열 할당
char *s2 = malloc(sizeof(char) * 10); // char 타입 10개 크기만큼 동적 메모리 할당
strcpy(s2, s1); // s1의 문자열을 s2로 복사
printf("%s\n", s2);
free(s2); // 동적 메모리 해제
return 0;
}
// Hello
- 먼저
malloc
함수로s2
에 메모리를 할당한다. - 당연히 할당할 메모리 공간은 복사될 문자열보다 커야 한다.
- 여기서는 메모리 공간이
10
바이트이므로"Hello"
(다섯 글자 +NULL
하나)는 충분히 들어갈 수 있다. - 그리고
strcpy
함수로s1
의 문자열을s2
에 복사하면 된다.
6. 배열 형태의 문자열을 문자열 포인터에 붙이기
- 이번에는 배열 형태의 문자열을 문자열 포인터에 붙여보자.
#define _CRT_SECURE_NO_WARNINGS // strcpy, strcat 보안 경고로 인한 컴파일 에러 방지
#include <stdio.h>
#include <string.h> // strcpy, strcat 함수가 선언된 헤더 파일
#include <stdlib.h> // malloc, free 함수가 선언된 헤더 파일
int main()
{
char s1[10] = "world"; // 크기가 10인 char 타입 배열을 선언하고 문자열 할당
char *s2 = malloc(sizeof(char) * 20); // char 타입 20개 크기만큼 동적 메모리 할당
strcpy(s2, "Hello"); // s2에 "Hello" 문자열 복사
strcat(s2, s1); // s2 뒤에 s1을 붙임
printf("%s\n", s2);
free(s2); // 동적 메모리 해제
return 0;
}
// Helloworld
- 문자열 포인터
s2
뒤에 문자열을 붙일 것이므로 먼저malloc
함수로 메모리를 할당한다. - 문자열이 더 붙더라도 메모리가 모자라지 않도록 넉넉하게 할당한다.
- 그리고
strcpy
함수로s2
에"Hello"
문자열을 복사해 준다. s2
가 준비되었으면strcat
함수로 문자열 포인터s2
뒤에 문자열 포인터s1
을 붙이면 된다.- 그리고 문자열 사용이 끝났다면 반드시
free
함수로 동적 할당한 메모리를 해제한다.