C++ 문자열
문자열(string)이란 메모리에 저장된 일련의 연속된 문자(character)들의 집합을 의미합니다.
C++에서는 이러한 문자열을 다음과 같은 두 가지 방법으로 생성할 수 있습니다.
1. C언어 스타일의 문자열
2. string 클래스를 이용한 문자열
C언어 스타일의 문자열
C++에서는 큰따옴표("")를 사용해 표현되는 문자열을 문자열 상수(string constant)라고 합니다.
상수라고 표현하는 이유는 해당 문자열이 이름을 가지고 있지 않으며, 문자열의 내용 또한 변경할 수 없기 때문입니다.
C++에서 문자형 배열을 선언하면 이 배열이 곧 문자열 변수가 됩니다.
C++에서는 문자열의 길이에 제한을 두지 않습니다.
널(NULL) 문자
C++에서 문자형 배열로 선언된 문자열 변수는 문자열의 끝을 프로그램에 따로 알려주어야 합니다.
그래야만 프로그램이 실제 문자열에 속한 값과 그 외의 쓰레깃값을 구분할 수 있습니다.
따라서 문자열에 속한 데이터가 끝나면, 문자열의 끝을 의미하는 문자를 하나 더 삽입해 줍니다.
이러한 문자를 널(NULL) 문자라고 하며, '\0'으로 표시하고 아스키코드값은 0입니다.
널 문자의 유무로 문자형 데이터 배열과 실제 문자열을 서로 구분할 수 있습니다.
문자열을 저장하기 위한 문자형 배열을 선언할 때에는 반드시 널 문자까지 포함해서 생각해야 합니다.
문자열 입력
C++에서 문자열을 입력받기 위해서는 문자열이 저장될 문자형 배열을 미리 생성해야 놔야 합니다.
예제
const int SIZE = 20;
char address[SIZE];
char name[SIZE];
cout << "자신의 이름을 적어주세요 : ";
cin >> name;
cout << "자신이 살고 있는 도시를 적어주세요 : ";
cin >> address;
cout << address << "에 살고 있는 " << name << "님~ 감사합니다!";
위의 예제는 사용자의 이름과 살고 있는 도시명을 입력받는 예제입니다.
하지만 이 예제는 다음과 같은 두 가지 문제점을 안고 있습니다.
1. 이름에 띄어쓰기가 들어가면 도시명을 입력할 수 없습니다.
2. 20바이트 이상의 이름이나 도시명을 입력하면 프로그램이 강제 종료됩니다.
C++에서 cin 객체는 띄어쓰기를 포함한 탭 문자, 캐리지 리턴 문자 등을 모두 문자열의 끝으로 인식합니다.
따라서 띄어쓰기를 포함한 문자열을 전부 입력받으려면 cin 객체의 get() 메소드를 사용하여 다음처럼 수정해야 합니다.
예제
const int SIZE = 20;
char address[SIZE];
char name[SIZE];
cout << "자신의 이름을 적어주세요 : ";
cin.get(name, SIZE).get();
cout << "자신이 살고 있는 도시를 적어주세요 : ";
cin.get(address, SIZE).get();
cout << address << "에 살고 있는 " << name << "님~ 감사합니다!";
위의 예제는 띄어쓰기를 포함한 이름이나 도시명을 정확히 입력할 수 있게 되었습니다.
하지만 아직도 20바이트 이상의 이름을 입력할 경우, 도시명을 입력받지 못하는 문제점을 안고 있습니다.
이 문제는 cin 객체의 ignore() 메소드를 사용하여 다음처럼 수정할 수 있습니다.
예제
const int SIZE = 20;
char address[SIZE];
char name[SIZE];
cout << "자신의 이름을 적어주세요 : ";
cin.get(name, SIZE).ignore(SIZE, '\n');
cout << "자신이 살고 있는 도시를 적어주세요 : ";
cin.get(address, SIZE).ignore(SIZE, '\n');
cout << address << "에 살고 있는 " << name << "님~ 감사합니다!";
위의 예제의 실행결과를 살펴보면, 20바이트 이상의 이름이나 도시명을 입력해도 정확히 20바이트까지만 입력받고 있는 것을 확인할 수 있습니다.
C언어 스타일의 문자열 입력에서는 입력할 문자열의 길이를 미리 알고 있어야만 합니다.
하지만 C++에서 제공하는 string 클래스를 이용하면 다음처럼 아주 간단하게 그 문제를 해결할 수 있습니다.
예제
#include <iostream>
#include <string>
using namespace std;
int main(void)
{
string address, name;
cout << "자신의 이름을 적어주세요 : ";
getline(cin, name);
cout << "자신이 살고 있는 도시를 적어주세요 : ";
getline(cin, address);
cout << address << "에 살고 있는 " << name << "님~ 감사합니다!";
return 0;
}
위의 예제는 앞서 살펴본 문자열의 띄어쓰기 문제나 문자열의 길이와 상관없이 모든 문자열을 정확히 입력받을 수 있습니다.
C언어 문자열 처리 함수
C++에서는 C언어 스타일의 문자열을 처리하기 위해 C 라이브러리의 문자열 처리 함수를 사용할 수 있습니다.
이러한 C언어의 문자열 라이브러리를 사용하기 위해서는 우선 cstring 헤더 파일을 포함해야 합니다.
string 클래스
C++은 문자열을 예전의 C언어 스타일뿐만 아니라, 새롭게 추가된 string 클래스를 이용하여 처리할 수 있도록 해줍니다.
string 클래스는 문자형 배열보다 사용하기 편리하며, 문자열을 하나의 타입처럼 표현할 수 있게 해줍니다.
C++에서 string 클래스를 사용하기 위해서는 우선 string 헤더 파일을 포함해야 합니다.
또한, string 클래스는 std 네임스페이스에 속해 있으므로, using 지시자를 사용하거나 해당 네임스페이스를 참조해야 합니다.
문자열 선언 및 초기화
C++에서 string 객체를 사용한 문자열 선언 방식은 다음과 같습니다.
예제
string str1; // 문자열의 선언
str1 = "C++ Programming"; // 문자열의 초기화
string str2 = "C++"; // 문자열의 선언과 동시에 초기화
string 객체는 위와 같이 문자열을 배열 형태가 아닌 단순한 변수로 선언합니다.
따라서 사용자가 길이를 명시하지 않아도 되며, 문자열의 길이에 대한 문제는 C++ 프로그램이 자동으로 처리해 줍니다.
위의 예제에서 문자열 str1은 선언 시 길이가 0인 string 객체를 생성합니다.
그 후 문자열을 초기화하면 C++ 프로그램이 문자열 str1의 길이를 자동으로 조절해 줍니다.
따라서 string 객체를 사용하면 문자형 배열을 사용하는 것보다 훨씬 더 편리하고 안전하게 문자열을 처리할 수 있습니다.
예제
string dog;
cout << "현재 dog 변수의 길이는 " << dog.length() << "입니다." << endl;
dog = "Navi";
cout << dog << "! 정말 이쁜 이름이네요!" << endl;
cout << "현재 dog 변수의 길이는 " << dog.length() << "입니다." << endl;
cout << "강아지 이름의 첫 글자는 바로 " << dog[0] << "입니다.";
위의 예제에서 보면 string 객체로 만든 문자열도 배열처럼 인덱스를 통해 다룰 수 있다는 것을 알 수 있습니다.
또한, 길이가 0인 string 객체가 입력된 문자열에 따라 자동으로 길이가 조절됨을 알 수 있습니다.
컴퓨터에서 한글은 2바이트로 취급됩니다.
따라서 위의 예제에서 한글을 입력하면 이름의 첫 글자로 이상한 문자가 출력될 것입니다.
string 클래스의 length() 메소드나 size() 메소드를 사용하면 string 객체의 현재 길이를 알 수 있습니다.
문자열 처리
C++에서 string 객체를 이용한 문자열의 처리는 문자형 배열을 이용하는 방식보다 훨씬 더 간단합니다.
C언어에서 문자형 배열 사이의 대입 작업은 strcpy() 함수나 strncpy() 함수를 사용했습니다.
하지만 string 객체를 이용한 문자열에서는 대입 연산자(=)만을 사용하여 간단히 대입 작업을 할 수 있습니다.
예제
string str1 = "C++ is Cool!";
string str2;
str2 = str1; // 문자열 대입 연산
cout << str2;
또한, 문자형 배열 사이의 추가나 결합 작업은 strcat()이나 strncat() 함수를 사용했습니다.
하지만 string 객체를 이용하면 복합 대입 연산자(+=)나 append() 메소드를 이용하여 손쉽게 추가나 결합을 할 수 있습니다.
예제
string str1 = "C++ is ";
string str2 = "Cool! and funny!";
string str3;
str3 = str1 + str2; // 문자열 결합 연산
cout << str3 << endl;
str1 += str2; // 문자열 추가 연산
cout << str1;
문자열 입출력
string 객체를 이용한 문자열의 입력에는 cin 객체를, 출력에는 cout 객체를 사용할 수 있습니다.
하지만 cin 객체를 이용한 문자열의 입력은 한 단어 단위로 수행됩니다.
따라서 문자열을 한 행(line)씩 읽고 싶을 때는 getline() 함수를 사용해야 합니다.
예제
string name, subject;
cout << "자신의 이름을 적어주세요 : ";
getline(cin, name);
cout << "가장 자신있는 과목을 적어주세요 : ";
getline(cin, subject);
cout << name << "님이 가장 자신있어 하는 과목은 바로 " << subject << "입니다!";
getline() 함수는 첫 번째 매개변수로 cin 객체를, 두 번째 매개변수로 문자열을 저장할 string 객체 변수를 전달받습니다.
string 메소드
string 메소드는 string 클래스에 정의된 문자열과 관련된 작업을 할 때 사용하는 메소드입니다.
string 클래스에서 제공하는 대표적인 문자열 처리 함수는 다음과 같습니다.
1. length() 메소드와 size() 메소드
2. append() 메소드
3. find() 메소드
4. compare() 메소드
5. replace() 메소드
6. capacity() 메소드와 max_size() 메소드
length() 메소드와 size() 메소드
length() 메소드는 문자열의 길이를 반환하는 메소드입니다.
size() 메소드도 length() 메소드와 언제나 같은 값을 반환하지만, 그 의미는 약간 다릅니다.
length() 메소드는 문자열의 길이를 나타내지만, size() 메소드는 해당 string 객체가 메모리에서 실제 사용하고 있는 크기를 나타냅니다.
예제
string str1;
string str2 = "C++ Programming";
cout << "문자열 str1의 길이는 " << str1.length() << "입니다." << endl;
cout << "문자열 str2의 길이는 " << str2.size() << "입니다.";
append() 메소드
append() 메소드는 하나의 문자열의 끝에 다른 문자열을 추가하는 메소드입니다.
appned() 메소드를 위한 원형은 다음과 같습니다.
문법
1. 문자열.append(추가할문자열); // 추가할 문자열을 맨 끝에 추가함.
2. 문자열.append(추가할문자열, 시작위치, 개수); // 추가할 문자열의 시작 위치부터 개수만큼만 맨 끝에 추가함.
3. 문자열.append(개수, 추가할문자); // 추가할 문자를 개수만큼 맨 끝에 추가함
예제
string str1, str2, str3;
str1.append("C++ Programming");
str2.append("C++ Programming", 4, 7);
str3.append(4, 'X');
cout << str1 << endl;
cout << str2 << endl;
cout << str3;
find() 메소드
find() 메소드는 특정 문자열을 찾아, 그 시작 위치를 반환하는 메소드입니다.
find() 메소드를 위한 원형은 다음과 같습니다.
문법
1. 문자열.find(찾을문자열); // 인덱스 0부터 찾을 문자열을 찾아, 그 시작 위치를 반환함.
2. 문자열.find(찾을문자); // 인덱스 0부터 찾을 문자를 찾아, 그 시작 위치를 반환함.
3. 문자열.find(찾을문자열, 시작위치); // 시작 위치부터 찾을 문자열을 찾아, 그 시작 위치를 반환함.
find() 메소드는 해당 문자열에서 찾을 문자열을 찾지 못하면, string::size_type의 string::npos라는 상수를 반환합니다.
예제
string str = "C++ Programming";
cout << str.find("Pro") << endl;
cout << str.find('r') << endl;
if (str.find("Pro", 5) != string::npos)
{
cout << "해당 문자열을 찾았습니다.";
}
else
{
cout << "해당 문자열을 찾지 못했습니다.";
}
정적 상수인 string::npos는 string 클래스에 static const size_type= -1 로 명시되어 있습니다.
compare() 메소드
compare() 메소드는 두 문자열 간의 내용을 비교하는 메소드입니다.
compart() 메소드의 반환값이 참(true)이 되는 경우는 다음과 같습니다.
예제
1. str1.compare(str_02) == 0 // str1과 str2이 같을 경우
2. str1.compare(str_02) < 0 // str1이 str2보다 사전 편찬순으로 앞에 있을 경우
3. str1.compare(str_02) > 0 // str1이 str2보다 사전 편찬순으로 뒤에 있을 경우
예제
string str1 = "ABC";
string str2 = "ABD";
if (str1.compare(str2) == 0)
{
cout << str1 << "이 " << str2 << "와 같습니다.";
}
else if (str1.compare(str2) < 0)
{
cout << str1 << "이 " << str2 << "보다 사전 편찬 순으로 앞에 있습니다.";
}
else
{
cout << str1 << "이 " << str2 << "보다 사전 편찬 순으로 뒤에 있습니다.";
}
replace() 메소드
replace() 메소드는 특정 문자열을 찾아, 그 문자열을 다른 문자열로 대체하는 메소드입니다.
replace() 메소드를 위한 원형은 다음과 같습니다.
문법
문자열.replace(대체할문자열의시작위치, 대체할문자열의길이, 새로운문자열);
// 전달된 시작 위치부터 문자열의 길이만큼을 제거한 후에, 새로운 문자열을 삽입함.
다음 예제는 문자열에서 "nice"라는 문자열을 찾아, "awesome"으로 바꾸는 예제입니다.
예제
string str1 = "C++ is very nice!";
string str2 = "nice";
string str3 = "awesome";
string::size_type index = str1.find(str2);
if (index != string::npos)
{
str1.replace(index, str2.length(), str3);
}
cout << str1;
capacity() 메소드와 max_size() 메소드
capacity() 메소드는 해당 문자열이 재대입(reallocation)받지 않고 저장할 수 있는 최대 문자열의 길이를 반환합니다.
max_size() 메소드는 해당 문자열이 최대한 대입받으면 가질 수 있는 최대 문자열의 길이를 반환합니다.
예제
string str = "C++ Programming";
cout << "문자열 str의 length는 " << str.length() << "입니다." << endl;
cout << "문자열 str의 capacity는 " << str.capacity() << "입니다." << endl;
cout << "문자열 str의 max_size는 " << str.max_size() << "입니다.";
댓글