1 분 소요

❄️ 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”라는 문자열이 아닌 그 문자열이 있는 메모리의 주소가 저장되기 때문입니다.
즉 변수 ts의 “값”이 아닌 “주소”를 복사했기 때문에 t[0]을 대문자로 바꿀 때 s[0]까지 같이 바뀐 것 입니다.
(string schar *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
}


💛 개인 공부 기록용 블로그입니다. 👻

맨 위로 이동하기

태그:

카테고리:

업데이트: