[CS50] 메모리: 문자열 복사
❄️ David Malan 교수의 모두를 위한 컴퓨터 과학(CS50 2019)을 바탕으로 정리한 내용입니다.
문자열을 복사하기 위해 아래 코드를 실행하면 어떻게 될까요?
#include <cs50.h>
#include <ctype.h>
#include <stdio.h>
int main(void)
{
string s = get_string("s: "); // emma 입력
string t = s; // 변수 t에 s를 복사 -> ✅ s의 "주소"를 복사
t[0] = toupper(t[0]); // t[0] 값을 대문자로 변경
printf("%s\n", s); // Emma
printf("%s\n", t); // Emma
}
입력값으로 “emma”를 주게 된다면, 단순한 예상과는 다르게 s와 t 모두 “Emma”라고 출력이 됩니다.
분명 t[0]
의 값만 대문자로 변경했는데, 왜 s
를 출력했을 때에도 “Emma”를 얻을까요?
그 이유는 s라는 변수에는 “emma”라는 문자열이 아닌 그 문자열이 있는 메모리의 주소가 저장되기 때문입니다.
즉 변수 t
에 s
의 “값”이 아닌 “주소”를 복사했기 때문에 t[0]
을 대문자로 바꿀 때 s[0]
까지 같이 바뀐 것 입니다.
(string s
는 char *s
와 동일한 의미라는걸 떠올려보면 됩니다.)
그렇다면 두 문자열을 메모리상에서 서로 다른 공간에 복사하려면 어떻게 해야할까요?
아래 코드와 같이 메모리 할당 함수를 사용해 메모리를 추가로 할당해서 “EMMA”와 동일한 크기의 변수를 만들고, s
안에 있는 글자를 하나씩 t
로 복사해야 합니다.
#include <cs50.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
int main(void)
{
char *s = get_string("s: "); // emma 입력
char *t = malloc(strlen(s) + 1); // null 종단 문자까지
// 아래 코드에는 비효율성과 약간의 버그가 있습니다.
// -> 반복해서 strlen(s)를 물어보기 때문에 비효율적이며 null 종단 문자를 복사하지 않습니다.
// for (int i = 0; i < strlen(s); i++)
// {
// t[i] = s[i];
// }
// 더 효율적이며 시간을 덜 낭비합니다.
for (int i = 0, n = strlen(s); i < n + 1; i++) // null 종단 문자까지
{
t[i] = s[i];
}
t[0] = toupper(t[0]);
printf("%s\n", s); // emma
printf("%s\n", t); // Emma
}
이제 t[0]
만 대문자로 변경되었습니다.
한 가지 좋은 소식은,
문자열 복사는 자주 하는 작업이기 때문에 이 루프를 직접 구현할 필요가 없습니다.
다음처럼 코드를 개선하여 조금 간단하게 만들 수 있습니다.
#include <cs50.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
int main(void)
{
char *s = get_string("s: "); // emma 입력
char *t = malloc(strlen(s) + 1); // null 종단 문자까지
strcpy(t, s) // ✅ t에 s 내용 복사
t[0] = toupper(t[0]);
printf("%s\n", s); // emma
printf("%s\n", t); // Emma
}
💛 개인 공부 기록용 블로그입니다. 👻