C++ 문자열 동적 저장
목차
문자열 동적 저장이란 문자열의 입력을 받을 때 마다 동적으로 char 배열을 생성하는 것입니다.
문자열을 정적으로 사용하려면 저장하려는 문자열이 컴파일 단계에서 결정되어 있어야 합니다. 그런데 사용자와 상호작용해야 하는 소프트웨어가 실행도중에 문자열을 만들 때는 정적인 방식만으로는 한계가 있습니다.
특히 배열은 실시간으로 크기를 늘릴 수 없는데 이럴 때 동적인 할당이 필요합니다. C++에는 string 객체가 있다고 했습니다. 대부분의 프로그래밍 언어에서는 string 객체에 상응하는 문자열 클래스가 있습니다. 또 거듭강조하지만 문자열은 사람이 컴퓨터를 사용하는데 있어서 가장 중요한 부분입니다.
동적 문자열 개념
일반 배열의 문제
동적 문자열이 왜 필요한지를 생각해보겠습니다. C의 기본 문자형은 char 타입입니다. 이 char 타입을 문자열에 사용하려면 배열을 만듭니다.
char 가 1바이트니까 영문 100개를 저장하려면 char myString[100] 이라고 합니다. 그런데 문장에는 긴 문장이 있고 짧은 문장이 있습니다. 문자열 “Hello World!”와 “Hello my name is Bob. nice to meet you!” 라는 문자열 둘다 myString 에 저장할 수 있습니다.하지만 Hello World! 는 100개 공간의 13개 공간만 사용할 뿐입니다. (마지막 +1 은 널문자 ‘\0’) 87개가 낭비됩니다.
두번째 문장은 조금 공간을 더 쓰지만 결국 100개를 다 사용하지 못합니다. 또 다른 문제는 문장이 100을 넘었을 때입니다. C계열은 런타임에서 메모리의 인덱스 범위를 넘어가는 것을 허용합니다. char myString[100] 의 인덱스를 넘어 char myString[101] 이 되는 순간 그 뒤의 메모리는 허가 받지 않은 공간입니다.
프로그래밍에서는 1바이트의 실수도 치명적 오류로 이어집니다. 그러므로 범위를 넘어갈 때 문제는 더 심각해진다 볼 수 있습니다. 대입 방식에 따라 문자열이 짤리거나 인덱스가 넘어가거나 둘 중 하나입니다.
해결책
해결책은 동적 메모리 할당입니다.
문자열 개수만 알면 힙메모리에 할당이 가능합니다. 즉 Hello World!에는 char myString[13] 을 할당하면 87개를 절약합니다. 100을 넘어가도 char myString[130] 과 같이 자동으로 코드가 만들어 집니다. 이것이 바로 우리가 사용하는 string 클래스의 원리입니다. 요새 유행인 동적 언어들(파이썬 등) 대부분 동적 할당 방식으로 문자열을 생성합니다.
이 string 클래스는 한술 더 떠서 자동으로 new 와 delete 를 실행합니다. 프로그래머의 메모리 관리 부분을 대신해줍니다.
평상시에는 string 클래스를 사용하는 것으로 충분하겠지만 원리를 이해하기 위해서 아래 예제를 실습해봅니다.
getMyText() 함수는 cin 으로 입력을 받습니다. 문자열에 따라 크기가 늘어나고 줄어드는 원리에 대하여 제대로 파악할 수 있습니다.
new를 사용했다면 delete 도 잊지 않습니다. 이건 항상 쌍으로 가야합니다. 언제 delete를 하느냐? 메모리를 다 사용한 후 즉시 delete 하는게 제일 좋습니다. 컴퓨터의 자원 사용은 최소한으로 유지하도록 합니다.
#include <iostream> using namespace std; char* getMyText(); int main() { char* myText; myText = getMyText(); cout << "- myText : " << myText << endl; cout << "- myText 주소 : " << (void*) myText << endl; cout << "- 문자열 길이 : " << strlen(myText) << endl; delete[] myText; return 0; } char* getMyText() { cout << "- 문자열을 동적으로 생성합니다" << endl; const int size = 100; char temp[size]; cin.getline(temp, size); char* ps = new char[strlen(temp) + 1]; // 할당된 메모리가 작으면 정해진 범위를 벗어난다 //char* ps = new char[20]; strcpy(ps, temp); return ps; }
- 문자열을 동적으로 생성합니다 This is dynamically allocated char array - myText : This is dynamically allocated char array - myText 주소 : 016264B8 - 문자열 길이 : 40
문자열이 생성된 후 길이를 체크하면 용량이 다르게 나옵니다.
그래서 웬만하면 배열을 사용하지 않고 동적 메모리 할당을 사용합니다.
요약
C++ 문자열을 다루는 방법에서 다른 언어와 다른 부분이 있습니다. 문자 -> 문자열로 변형하는 과정에서 불편한 부분들이 있기 때문에 연산자를 오버라이딩 해서 사용합니다. string 객체에서 char 의 불편한 부분들을 상당히 개선한 부분들을 알 수 있습니다.
그래서 다른 언어가 아니라 C++로 문자열을 다루어 보면 컴퓨터의 문자열 처리의 어려움들을 원초적으로 이해할 수 있습니다. 다른 언어들과 비해서 알고리즘 적으로 많은 공부가 되는 장점이 있습니다.
참고문서
Dynamic character array – C++ Forum (cplusplus.com)
C++ Notes: Dynamic Allocation of C-Strings (puc-rio.br)
C++ dynamic memory : new, delete, allocating memory dynamically