string 클래스는 C++ STL(표준라이브러리)에서 제공하는 클래스이다.
문자열을 다루는 방법은 2가지가 있다.
1. char array을 이용하는 방법
2. string str 방식
C에서는 1 방식만 이용할 수 있고, C++에서는 2 방식을 주로 이용한다.
C++에 들어가면서 string을 하나의 변수 type으로 사용할 수 있게 된 것이다.
char 방식에서는 개행문자 '\0'을 고려하여 배열의 크기를 1만큼 추가해야 했지만 string에는 개행문자가 들어가지 않는다. 또한 문자열은 동적 할당이 가능하다.
선언 및 생성
- #include <string>; ▶ string 헤더를 불러온다.
- string str; ▶ string type의 str 변수를 생성
- string str = "hello"; ▶ string type의 str 변수를 생성하고, 값을 'hello'로 초기화
- string str("hello"); ▶ 위와 동일
- string str2(str1); ▶ str1의 값을 복사한 string str2를 생성. (깊은 복사)
동적 할당
- string *str = new string(); ▶ new를 이용하여 문자열을 동적 할당할 수 있다. (포인트 변수로 선언)
- str -> append("hello"); ▶ 포인터 변수인 str이 가리키고 있는 객체의 함수인 append를 사용하여 "hello"를 삽입
- string *str = new string("hello"); ▶ 포인터 변수를 선언하면서 미리 값을 삽입할 수 있음.
- cout << *str << endl; ▶ 포인터 변수가 가리키고 있는 객체의 값을 출력
- delete str; ▶ 동적 할당한 객체를 그만 사용한다면 delete를 이용하여 메모리를 반환해야 함.
입/출력
- cin >> str; ▶ str의 값을 입력 받음
- getline(cin, str); ▶ '\0'을 제외한 문자열을 한 번에 입력 받음. (공백 포함) (=getline(cin, str, '\0');)
- getline(cin, str, 'a'); ▶ 'a' 문자 이전까지의 문자열을 입력 받음.
- cout << str; ▶ str을 출력
비교 연산
C에서는 char 배열을 이용하여 문자열을 생성한다. 따라서 문자열의 비교연산을 하면 메모리 주소를 값으로 비교하기 때문에 정확한 결과가 나오지 않는다. 따라서 C에서는 string 클래스의 함수인 strcmp, strncmp를 사용하여 문자열의 비교를 한다.
반면 C++에서는 string 끼리의 == 연산자를 이용하여 비교 연산을 할 수 있다. (연산자 오버로딩)
Compare 함수로도 비교가 가능하지만 비효율적이므로 == 연산자를 이용한다. (str1.compare(str2);)
#include <iostream>
using namespace std;
int main() {
string str1 = "World!";
string str2 = "World!";
string str3 = "Good!";
cout << (str1 == str2) << " " << (str1 == str3) << " " << endl;
return 0;
}
1 0
- <, > 연산자를 이용하면 사전 순서를 비교할 수 있다.
#include <iostream>
using namespace std;
int main() {
string str1 = "BWorld!";
string str2 = "AWorld!";
string str3 = "CGood!";
cout << (str1 > str2) << " " << (str1 > str3) << " " << endl;
return 0;
}
1 0
사전 순서가 늦은 방향으로 입을 벌리면 true(1)가 반환되고, 반대 방향일 경우 false(0)가 반환된다.
접근
- str[i]; ▶ string type의 원소인 str의 i번째 원소를 반환 (범위 체크 X, 빠름)
- str.at(i); ▶ 위와 동일한 기능. (범위 체크, 위보다는 느림)
- str.front(); ▶ 문자열의 가장 앞 문자를 반환
- str.back(); ▶ 문자열의 가장 마지막 문자를 반환
- string str[5]; ▶ string 타입의 배열을 생성할 수 있음. 5 크기의 string type 배열
- str[0] = "abcde";
- str[1] = "fghij";
- cout << str[0] << endl; ▶ 결과: abcde
크기
- str.length(); ▶ 문자열 길이 반환
- str.size(); ▶ 문자열 길이 반환(위와 동일)
- str.capacity(); ▶ string 객체에 할당된 메모리의 크기를 반환(가변)
- str.resize(n); ▶ string의 크기를 n으로 할당. 할당한 사이즈가 이전보다 작다면 남은 string을 삭제. 만약 이전보다 크다면 빈공간으로 채움
- str.resize(n, 'a'); ▶ string 크기를 n으로 할당하고, 이전보다 할당한 사이즈가 크면 추가하는 문자를 'a'로 초기화
- str.shrink_to_fit(); ▶ string의 길이에 비해 메모리가 더 할당되어 있다면 capacity를 줄이는 함수
- str.reverse(n); ▶ 나중에 들어올 문자열을 대비하여 n만큼의 메모리 사이즈를 미리 예약하여 할당
- str.empty(); ▶ str이 빈 문자열인지 확인
삽입/추가/삭제
- str.append(str2); ▶ str의 뒤에 str2를 연결. str + str2
- str.append(str2, i, j); ▶ str 뒤에 str2의 i번째부터 j개의 문자를 연결
- str.append(n, 'a'); ▶ str 뒤에 'a'를 n개만큼 연결
- str.insert(i, str2); ▶ str의 i번째 위치에 str2를 연결
- str.replace(i, k, str2); ▶ str의 i번째 위치에 있는 문자부터 k개의 문자를 str2로 대체
- str.clear(); ▶ str의 문자열을 모두 지우는 함수. size와 length는 0이 되지만, 할당한 메모리 capacity는 유지된다.
- str.erase(); ▶ str의 문자열을 모두 삭제
- str.erase(i, j); ▶ str의 i번째부터 j개의 문자를 삭제
- str.push_back('k'); ▶ str의 맨 뒤에 문자 k를 추가
- str.pop_back(); ▶ str의 마지막 문자를 제거
- str.assign(str2); ▶ str에 str2 문자열을 할당
기타
- str.substr(i); ▶ str의 i번째 위치부터 마지막까지의 문자를 반환
- str.substr(i, j); ▶ str의 i번째 위치부터 j개의 문자를 반환
- str.find("f"); ▶ 문자(열)가 존재하는 경우 해당 인덱스를 반환. 그렇지 않다면 -1 반환
- str.find("f", i); ▶ i번째 인덱스부터 문자(열)을 찾음
- swap(str1, str2); ▶ str1과 str2를 교환. 복사를 하는 것이 아니라 서로의 reference를 교환하여 스왑. 따라서 복사에 의한 성능 저하를 우려하지 않아도 됨
- isdigit(a); ▶ 문자(열) a가 숫자인지 아닌지 판별. ex) a="a145"인 경우 isdigit(a[0])는 False, isdigit(a[1])은 True
- isalpha(a); ▶ 문자(열) a가 문자인지 아닌지 판별
- str[i] = toupper(str[i]); ▶ str[i]의 문자를 대문자로 변환 (한개씩만 변환되므로 반복문 이용)
- str[i] = tolower(str[i]); ▶ str[i]의 문자를 소문자로 변환 (한개씩만 변환되므로 반복문 이용)
- string(i, str); ▶ str을 i번 반복
응용
특정 문자 제거하기
1. erase, remove 이용
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
string my_string = "aaabbbccc";
string letter = "a";
my_string.erase(remove(my_string.begin(),my_string.end(), letter[0]), my_string.end());
cout << my_string;
return 0;
}
bbbccc
remove로 letter 원소를 뒤로 보내고, erase로 제거
2. 비교 연산 이용
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
string answer = "";
string my_string = "aaabbbccc";
string letter = "a";
for(int i=0; i<my_string.size(); i++)
if(my_string[i]!=letter[0]) answer+=my_string[i];
cout << answer;
return 0;
}
bbbccc
변환
- 1) 문자 → 정수
- (문자 - '0')은 정수로 변환된다.
#include <string>
#include <iostream>
using namespace std;
int main() {
int answer = 0;
string n = "123456";
for (char str: n){
answer += (str - '0');
}
cout << answer;
return 0;
}
21
- 2) 정수 → 문자
- (숫자 + '0')은 문자로 치환된다.
#include <string>
#include <iostream>
using namespace std;
int main() {
string answer = "";
int n[5] = {1, 2, 3, 4, 5};
for (int num: n){
answer += (num + '0');
}
cout << answer;
return 0;
}
12345
- 3) 정수 → 문자 → 정수
- string 헤더 내 함수인 to_string은 정수를 문자로 치환해준다.
#include <string>
#include <iostream>
using namespace std;
int main() {
int answer = 0;
int n = 123456;
string str = to_string(n);
for (char s: str){
answer += (s - '0');
}
cout << answer;
return 0;
}
21
split
- sstream 헤더 내 stringstream 클래스를 이용한다.
- 원하는 문자를 기준으로 문자열을 구분하여 저장할 수 있다.
#include <iostream>
#include <vector>
#include <sstream>
using namespace std;
vector<string> split(string input, char delimiter) {
vector<string> answer;
stringstream ss(input);
string temp;
while (getline(ss, temp, delimiter)) {
answer.push_back(temp);
}
return answer;
}
int main() {
string str = "Hello World !!!";
vector<string> answer = split(str, ' ');
for (int i=0; i<answer.size(); i++){
cout << answer[i] << endl;
}
return 0;
}
구분자인 delimeter를 지정하여 문자열을 벡터에 저장한다.