36-2-라.대입 및 연결

string 객체에 다른 문자열이나 문자를 대입할 때는 = 연산자를 사용한다. 값을 변경할 때는 = 연산자를 사용한다는 상식에 부합하기 위해 이 연산자가 정의되어 있다. 세 가지 종류의 문자열을 대입할 수 있도록 오버로딩되어 있다.

 

string& operator=(char ch);

string& operator=(const char* str);

string& operator=(const string& other);

 

단일 문자, 문자열 상수 또는 다른 string 객체를 대입할 수 있는데 상식적으로 문자열에 대입할만한 모든 것들을 다 대입할 수 있다고 보면 된다. 대입 연산자는 우변의 길이만큼 메모리를 확보한 후 메모리 복사를 수행할 것이며 string 객체끼리 대입할 때는 깊은 복사를 할 것이다. 문자열끼리 연결할 때는 += 연산자를 사용하는데 대입 연산자와 마찬가지로 세 가지 버전으로 오버로딩되어 있다.

 

string& operator+=(char ch);

string& operator+=(const char* str);

string& operator+=(const string& other);

 

문자열 상수나 string 객체를 연결할 수 있고 단일 문자도 연결할 수 있는데 단일 문자를 문자열 끝에 추가하는 기능은 C 함수에는 없는 기능이다. 연결할 때도 마찬가지로 두 문자열을 합친 길이만큼 메모리를 재할당할 것이다. 다음 예제는 대입과 연결 동작을 테스트한다.

 

: stringequalplus

#include <Turboc.h>

#include <iostream>

#include <string>

using namespace std;

 

void main()

{

     string s1("야호 신난다.");

     string s2;

 

     s2="임의의 문자열";

     cout << s2 << endl;

     s2=s1;

     cout << s2 << endl;

     s2='A';

     cout << s2 << endl;

 

     s1 += "문자열 연결.";

     cout << s1 << endl;

     s1 += s2;

     cout << s1 << endl;

     s1 += '!';

     cout << s1 << endl;

 

     string s3;

     s3="s1:"+s1+"s2:"+s2+'.';

     cout << s3 << endl;

}

 

문자열끼리, 단일 문자와 대입 및 연결을 해 보았다. 실행 결과는 다음과 같은데 코드와 연산 후의 결과를 비교해 보아라.

 

임의의 문자열

야호 신난다.

A

야호 신난다.문자열 연결.

야호 신난다.문자열 연결.A

야호 신난다.문자열 연결.A!

s1:야호 신난다.문자열 연결.A!s2:A.

 

대입, 연결 연산자는 모두 string형의 레퍼런스를 리턴하므로 연쇄적인 대입이나 연결도 가능하다. + 연산자도 string의 멤버는 아니지만 프렌드로 정의되어 있어 문자열, string 객체, 단일 문자를 연쇄적으로 연결할 수 있다. 그래서 연결하고 싶은 대상을 순서에 상관없이 + 연산자로 죽 나열하기만 하면 원하는 문자열을 쉽게 만들 수 있다. 예제의 s3는 s1과 s2그리고 중간 중간의 문자열 상수들을 연결하여 만들어진 문자열이다.

문자열을 대입하고 연결하는 =, += 연산자는 항상 피연산자 전체를 대상으로 한다. 다른 문자열의 일부만 대입하거나 연결하고 싶을 때는 연산자를 쓸 수 없으며 다음 두 함수를 사용해야 한다. string 객체끼리 대입, 연결하는 대표적인 두 함수의 원형만 보이는데 예상하다시피 이보다 훨씬 더 많은 원형이 오버로딩되어 있다. 나머지는 레퍼런스를 참조하기 바란다.

 

string& assign(const string& _str, size_t off, size_t count);

string& append(const string& _str, size_t off, size_t count);

 

인수의 형식은 직관적인데 str객체의 off 위치에서 count개수만큼만 대입하거나 연결한다. = 연산자가 표준 strcpy 함수라면 assign은 strncpy 함수에 해당한다. 동작이 간단하므로 예제만 한 번 실행해 봐도 이해할 수 있을 것이다.

 

: AssignAppend

#include <Turboc.h>

#include <iostream>

#include <string>

using namespace std;

 

void main()

{

     string s1("1234567890");

     string s2("abcdefghijklmnopqrstuvwxyz");

     string s3;

 

     s3.assign(s1,3,4);

     cout << s3 << endl;

     s3.append(s2,10,7);

     cout << s3 << endl;

}

 

두 개의 문자열 객체를 만들어 놓고 이 중 일부를 대입 및 연결해 보았다.

 

4567

4567klmnopq

 

s3문자열 객체는 디폴트 생성자에 의해 빈 문자열로 생성되었다가 s1의 일부 문자열을 대입받고 다시 s2의 일부 문자열을 연결하여 만들어졌다.

다음 두 함수는 문자 배열에 문자열을 복사하거나 string 객체끼리 교환한다.

 

size_type copy(value_type* _Ptr, size_type _Count, size_type _Off = 0) const;

void swap(basic_string& _Str);

 

copy 함수는 _Ptr 문자 배열에 객체의 _Off 위치에 있는 문자들을 _Count 개수만큼 복사한다. _Off의 디폴트값이 0이므로 이 인수를 생략하면 객체의 처음 문자부터 지정한 개수만큼 복사될 것이다. 지정한 개수만큼만 정확하게 복사하므로 널 종료 문자는 붙이지 않는다. 만약 객체의 문자열 길이가 _Count보다 더 작으면 객체의 길이만큼만 복사된다. _Ptr 배열은 복사받을 문자열의 길이만큼 충분한 길이를 가져야 하는데 만약 이 길이가 부족하면 결과는 예측할 수 없다. 다운될 수도 있다는 얘기인데 시작 번지만 전달되는 문자 배열의 길이는 C++에서도 여전히 알 수 없으므로 어찌할 도리가 없다.

copy 함수를 사용하면 string 객체의 내용을 문자 배열로 변환할 수 있다. swap함수는 이름 그대로 두 문자열의 내용을 교환하는데 이때 두 객체의 메모리는 자동으로 관리된다. 이 두 함수의 동작 확인을 위한 간단한 예제를 만들어 보자.

 

: CopySwap

#include <Turboc.h>

#include <iostream>

#include <string>

using namespace std;

 

void main()

{

     string s("1234567890");

     char str[128]="abcdefghijklmnopqrstuvwxyz";

 

     s.copy(str,5,3);

     cout << str << endl;

 

     string s1("dog");

     string s2("cow");

     cout << "s1:" << s1 << "s2:" << s2 << endl;

     s1.swap(s2);

     cout << "s1:" << s1 << "s2:" << s2 << endl;

}

 

s의 copy 함수로 3번째 문자부터 길이 5만큼을 str 배열로 복사해 보았다. str의 첫 다섯 문자가 s의 부분 문자열로 대체될 것이다. 그리고 s1, s2 두 문자열 객체를 swap 함수로 교환해 보았다.

 

45678fghijklmnopqrstuvwxyz

s1:dogs2:cow

s1:cows2:dog

 

만약 copy 함수로 배열의 중간쯤에 문자열을 복사하고 싶다면 첫 번째 인수인 포인터에 정수를 더하기만 하면 된다. 예를 들어 str의 4번째 위치에 문자열을 복사하고 싶다면 s1.copy(str+4,5,3)을 호출한다. swap 함수는 두 객체의 내용을 교환하므로 호출 객체와 피연산자를 바꿔도 결과는 동일하다. 즉 s2.swap(s1)이라고 해도 똑같다.