앞선 정리 포스팅에서 언급하였듯, C++에서는 문자열을 사용할 수 있는 방법이 2가지가 있다.
cstring은 null 문자(\0)로 끝나는, 전통적인 C언어의 문자열 처리 방식이고, string 클래스는 C++ 표준 라이브러리에서 제공하는 클래스로서 문자열을 객체로 다루게 된다. 이번 포스팅에서는 string에 대해서 알아보자.
string 클래스를 사용하기 위해서는 다음 코드가 필요하다.
#include <string>
using namespace std;
string 클래스는 문자열의 크기에 맞추어 메모리를 동적으로 자동 조정하기 때문에 편리하게 사용할 수 있다. 이제부터 사용법에 대해서 알아보겠다.
string str; // 빈 문자열 객체
string address("..."); // 문자열로 초기화
string copyAddress(address); // 다른 문자열을 복사해서 생성
// 복사를 통한 생성은 cstring도 복사가 가능하다.
생성은 이렇고, 출력은 다음과 같다.
cout<<address<<endl;
또한 객체이고, 메모리를 할당받아 생성하는 자료형이다보니 new와 delete 연산자를 통해서 동적으로 생성하고 반환할 수 있다.
string *p = new string("C++");
cout<<*p;
p->append("Great!!");
cout<<*p;
delete p;
💡 string 클래스의 주요 생성자
1. string() : 빈 문자열 생성
2. string(const string& str) : str을 복사한 새로운 string 객체 생성
3. string(const char s) : cstring을 복사해서 생성
4. string(const char s, int n) : 문자 배열 s에서 n개의 문자를 복사해서 생성
cin 객체와 >> 연산자를 이용해서 키보드로부터 string 객체에 문자열을 입력받을 수 있다.
string name;
cin >> name;
앞서 살펴본 것처럼, >> 연산자는 공백문자를 포함하지 않는다. 따라서 공백문자를 포함해서 문자열을 입력하고 싶으면, getline() 함수를 사용해야 한다. getline() 함수는 string 헤더 파일에 선언되어 있다.
string name;
getline(cin, name, '\n');
예시 코드를 한번 살펴보자.
#include <iostream>
#include <string>
using namespace std;
int main() {
string names[5];
for (int i = 0; i < 5; i++) {
cout << "이름 >> ";
getline(cin, names[i], '\n');
}
string latter = names[0];
for (int i = 0; i < 5; i++) {
if (latter < names[i]) // latter가 names[i]보다 앞에 온다면
latter = names[i];
}
cout << "사전에서 가장 뒤에 나오는 문자열은 " << latter << endl;
}
간단히 = 연산자를 사용한다.
string a = "hello", b="world";
a = b; // a에 b의 문자열을 복사해서 치환
문자열 비교는 compare() 함수를 사용한다. 이 함수는 문자열이 같으면 0을 반환하고, str보다 사전 순으로 앞에 오면 음수, 뒤에 오면 양수를 리턴한다. compare 함수의 원형은 다음과 같다.
int compare(const string& str);
이 함수를 사용하는 예시는 다음과 같다.
string name="hello";
string alias = "kito";
int res = name.compare(alias);
if(res==0) cout << "두 문자열이 같다" << endl;
else if(res<0) cout << name << "<" << alias << endl;
else cout << alias << "<" << name << endl;
혹은 "==" 연산자를 통해서도 비교 연산이 가능하다.
문자열 연결은 연산자와 함수를 이용해서 가능하다.
함수의 경우, append() 함수를 사용한다. 원형은 다음과 같다.
string& append(const string& str); // 문자열 뒤에 str 추가
string& append(const string& str, int pos, int n);
// str에서 pos 위치부터 n개 문자를 복사해서 추가
혹은 +, += 연산자를 통해서도 할 수 있다.
string a("hello world");
string b("!!!");
string c;
c = a+b; // hello world!!! 가 복사
문자열 삽입은 insert() 함수와 replace() 함수를 통해서 진행할 수 있다.
insert() 함수의 원형은 다음과 같다.
string& insert(int pos, const string& str);
// 문자열의 pos 위치에 str 삽입
replace() 함수의 원형은 다음과 같다.
string& replace(int pos, int n, const string& str);
// 문자열의 pos 위치부터 n개 문자를 str 문자열로 대치
예시는 다음과 같다.
string a("I love C++");
a.insert(2, "really "); // I really love C++로 변화
a.replace(2,11,"study"); // I study C++로 변화
문자열 길이는 문자열에 포함된 문자 개수를 말하며, length()와 size() 함수를 통해서 문자열 길이를 리턴받을 수 있다. 길이와 달리, 객체의 내부 메모리 용량을 리턴하는 capacity() 함수도 있다.
각 함수들의 원형은 다음과 같다.
int size();
int lengh();
int capacity();
사용 예시는 다음과 같다.
string a("abcdefghi");
int length = a.length();
int size = a.size();
int capa = a.capacity();
erase()는 문자열의 일부분을 삭제할 수 있고, clear() 함수는 완저히 삭제가 가능하다.
함수의 원형은 다음과 같다.
string& erase(int pos, int n);
// pos부터 n개 문자 삭제
void clear(); // 모두 삭제하고 빈 문자열로 만들기
substr() 함수를 사용하면 문자열에서 일부분만 발췌한 문자열(substring)을 얻을 수 있다. 이때 원 문자열은 변화가 없다.
string substr(int pos, int n);
// pos위치부터 n개 문자를 새로운 substring으로 생성
문자열 내에 특정 문자열이 존재하는지 검색하는 기능은, find() 함수를 통해서 구현된다. find() 함수는 문자열에서 특정 문자나 문자열을 발견하면 첫번째 인덱스를 리턴하며, 발견하지 못하면 -1을 리턴하게 된다.
먼저 원형을 살펴보자.
int find(const string & str);
// 문자열의 처음부터 str을 검색하여 발견한 처음 인덱스를 리턴, 없으면 -1 리턴
int find(const string& str, int pos);
// 문자열의 pos 위치부터 str을 검색하여 발견한 처음 인덱스 리턴. 없으면 -1 리턴
int rfind(const string& str, int pos);
// 문자열의 pos 위치부터 str을 검색하여 마지막에 발견한 인덱스 리턴, 없으면 -1 리턴
예시를 들면 다음과 같다.
string e = "i love love C++";
int index = e.fine("love"); // e에서 love를 검색해 인덱스 2 리턴
index = e.find("love", index+1); // e에서 3부터 love 검색, 7 리턴
index = e.find("C#"); // -1 리턴
index = e.find('v', 7); // e의 인덱스 7부터 v를 검색, 9 리턴
문자열은 인덱스 연산자인 "[ ]" 혹은 at() 함수를 통해서 문자열의 특정 위치에 있는 문자를 리턴할 수 있다. at() 함수의 원형은 다음과 같다.
char & at(int pos); // pos 위치의 문자 리턴
"[ ]" 연산자를 사용하면 단순히 특정 위치의 문자를 리턴할 수 있는 것뿐만 아니라 해당 위치의 문자를 수정할 수 있다.
a="1234";
a[1]="1";
// a는 1134
C++11 표준부터 문자열을 숫자로 변환하는 전역 함수 stoi()를 추가하였다. stoi() 함수는 다음과 같이 사용한다.
string year = "2014";
int n = stoi(year); // n은 정수 2014의 값을 가짐
string 헤더 파일은 문자열을 다루지 개별 문자를 다루는 기능은 없다. 문자를 다루는 함수는 "locale" 헤더 파일에 존재한다. "locale" 헤더 파일은 toupper() 함수, isdigit() 함수, isalpha() 함수 등을 지원한다.
toupper() 함수 : 대문자로 바꿔준다.
isdigit() 함수 : 숫자인지 판정해준다.
isalpha() 함수 : 알파벳인지 판정해준다.
- += : 두 문자열을 연결해준다.
- == : 같은 문자열이면 true 리턴
- != : 다른 문자열이면 true 리턴
- s1 < s2 : s1이 사전순으로 s2보다 앞에 오면 true 리턴
- s1 > s2 : s1이 사전순으로 s2보다 뒤에 오면 true 리턴
- s1 <= s2 : s1이 s2와 같거나 앞에 오면 true 리턴
- s1 >= s2 : s1이 s2와 같거나 뒤에 오면 true 리턴
#include <iostream>
#include <string>
using namespace std;
int main() {
string s;
cout << "아래에 문자열을 입력하세요. 빈 칸이 있어도 됩니다(한글 안됨)." << endl;
getline(cin, s, '\n');
int len = s.length();
for (int i = 0; i < len; i++) {
string first = s.substr(0, 1); // 맨 앞에 문자 1개를 문자열로 분리
string sub = s.substr(1, len - 1); // 나머지 문자열을 분리
s = sub + first; // 두 문자열을 연결하여 새로운 문자열 생성
cout << s << endl;
}
}
#include <iostream>
#include <string>
using namespace std;
int main() {
string s;
cout << "덧셈이 포함된 문자열을 입력하세요" << endl;
getline(cin, s, '\n');
int sum = 0;
int startIndex = 0;
while (true) {
int fIndex = s.find('+', startIndex); // + 문자 검색
if (fIndex == -1) {
// 만약 +가 없다면
string part = s.substr(startIndex);
if (part == "") break; //+로 끝나는 경우 중단
cout << part << endl;
sum += stoi(part); // 문자열을 수로 변환해서 더하기
break;
}
int count = fIndex - startIndex; // 서브스트링으로 자를 문자 개수
string part = s.substr(startIndex, count); //count개의 서브스트링 만들기
cout << part << endl;
sum += stoi(part); // 문자열을 수로 변환하여 더하기
startIndex = fIndex + 1; // 검색을 시작할 인덱스 전진
}
cout << "숫자들의 합은 " << sum << endl;
}
#include <iostream>
#include <string>
using namespace std;
int main() {
string s;
cout << "여러 줄의 문자열을 입력하세요. 입력의 끝은 & 문자입니다." << endl;
getline(cin, s, '&');
cin.ignore(); // & 뒤에 따라오는 엔터 키 제거
string f, r;
cout << endl << "find: ";
getline(cin, f, '\n');
// 검색할 문자열 입력
cout << "replace : ";
getline(cin, r, '\n'); // 대치할 문자열 입력
int startIndex = 0;
while (true) {
int fIndex = s.find(f, startIndex); // startIndex부터 f 검색
if (fIndex == -1)
break;
// 문자열의 끝까지 변경하였다는 뜻
s.replace(fIndex, f.length(), r); // fIndex부터 f의 길이만큼 문자열 r로 변경
startIndex = fIndex + r.length();
}
cout << s << endl;
}