C++: 문자열(String)
C++: 문자열(String)
문자열(String) 클래스
- C++에서 char* 대신 사용할 수 있는 문자열 자료형으로, string 라이브러리에 클래스로 구현되어 있다.
- 내부는 벡터와 유사하며, 차이점은 모든 자료형 대신 char만 담을 수 있다는 점이다.
1 2 3 4 5 6 7 8 9 10 11 12 13
#include <iostream> #include <string> using namespace std; int main() { string A; //String 생성 string B = "Hello"; //생성과 함께 초기화 char temp[] = "Hi"; //Char 배열을 이용한 초기화 string C = temp; char* ptr = temp; //Char 포인터를 이용한 초기화 string D = ptr; cout << D << endl; }
지원 함수
- find()
- 문자열 안에 해당 검색어가 포함됬는지 검색해 그 위치에 해당하는 인덱스를 반환한다. 두번째 인자로 검색을 시작할 index를 지정할 수 있다.
- 없을 경우 string::npos를 반환한다.
- string::npos는 찾지 못한 상태를 나타낸다.
- npos가 나올 수 있는 기능을 구현할 경우 예외 처리를 해주지 않으면 런타임 에러가 날 수 있다.
- 해당 범위에 대해 모든 위치에서 검색어가 존재하는 지 확인한다. 즉, 원본의 길이를 n, 검색어의 길이를 m이라 하면 $O(n *m)$의 시간 복잡도를 가진다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
#include <iostream> #include <string> using namespace std; int main() { string A = "On the other hand"; //생성과 함께 초기화 size_t temp = A.find("hello"); //없으니 string::npos 반환 if (temp != string::npos) { cout << temp << endl; } else { cout << "does not exists in the string!" << endl; } temp = A.find("other"); //other이 시작하는 인덱스 반환 if (temp != string::npos) { cout << temp << endl; } else { cout << "does not exists in the string!" << endl; } temp = A.find("n"); //On에 있는 첫번째 n의 인덱스 반환 if (temp != string::npos) { cout << temp << endl; } else { cout << "does not exists in the string!" << endl; } temp = A.find("n", 3); //인덱스 3 이후로 검색, hand에 있는 첫번째 n의 인덱스 반환 if (temp != string::npos) { cout << temp << endl; } else { cout << "does not exists in the string!" << endl; } }
- substr()
- s.substr(시작위치, 길이)
- 일부분을 새 문자열로 반환
- 길이가 없으면 시작위치부터 끝까지
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
#include <iostream> #include <string> using namespace std; int main() { string A = "On the other hand"; string temp = A.substr(7); //인덱스 7이후의 문자열 반환, he other hand cout << temp << endl; temp = A.substr(7, 5); //인덱스 7에서 5개 길이의 문자열 반환, other cout << temp << endl; temp = A.substr(A.find("hand")); //find와 조합하여 사용, hand cout << temp << endl; }
- find와 substr를 사용하여 파일 확장자 분리나에 많이 쓰임
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
#include <iostream> #include <string> using namespace std; int main() { string A = "260326_SamplePost_Subtitle"; size_t index = A.find('_'); string token = A; while (index != string::npos) { cout << token.substr(0, index) << endl; //토큰 출력 token = token.substr(index+1); //남은 문자열로 이동 index = token.find('_'); } cout << token.substr(0, index) << endl; //마지막 토큰 출력 }
- replace()
- s.replace(시작위치, 길이, “새문자열”)
- 원본을 직접 “하나만 수정”
1 2 3 4 5 6 7 8 9
#include <iostream> #include <string> using namespace std; int main() { string A = "On the other hand"; cout << A << endl; //on the other hand A.replace(0,5, "qqqq"); //인덱스 0부터 5문자를 qqqq로 변환 cout << A << endl; //qqqq other hand }
- find와 조합하여 npos반환할때까지 반복하면 전부 대체 가능
1 2 3 4 5 6 7 8 9 10
#include <iostream> #include <string> using namespace std; int main() { string A = "left right left up down left"; while (A.find("left") != string::npos) { A.replace(A.find("left"), 4, "FOUND!"); cout << A << endl; } }
- stringstream
- string을 스트림처럼 다룰 수 있게 해주는 자료형으로, sstream 라이브러리를 포함하여 사용할 수 있다.
- 읽기 전용인 istringstream, 쓰기 전용인 ostringstream도 존재한다.
- 문자열을 cin, cout을 사용할 때 처럼 스트림(Stream)으로 다룰 수 있게 해준다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
#include <iostream> #include <string> #include <sstream> using namespace std; int main() { string str = "100 200 300 400"; stringstream ss(str); //다른 문자열로 스트링스트림 초기화 cout << "ss: " << ss.str() << endl; //스트링 스트림에서의 토큰 출력 int A[4]; ss >> A[0] >> A[1] >> A[2] >> A[3]; cout << "ss: " << ss.str() << endl; cout << "A[0]: " << A[0] << endl; cout << "A[1]: " << A[1] << endl; cout << "A[2]: " << A[2] << endl; cout << "A[3]: " << A[3] << endl; //스트링 스트림으로 토큰 입력 ss.str(""); //버퍼 초기화, 내용물 없음 ss.clear(); //플래그 초기화, 입력 가능 ss << 500 << " " << 600; cout << "ss: " << ss.str() << endl; //반복문으로 끊어서 토큰 읽기 string token; while (getline(ss, token, ' ')) { cout << "token: " << token << endl; } }
- string을 스트림처럼 다룰 수 있게 해주는 자료형으로, sstream 라이브러리를 포함하여 사용할 수 있다.
- 변환
- stoi: string => int
- stof: string => float
- stol: string => long
- stoll: string => long long
- stod: string => double
- to_string: 다른 자료형 => string
- string에 저장되는 문자는 ascii수준의 문자와 한글같이 유니코드를 사용하는 문자의 사이즈가 다르다. (ASCII: 7비트, 유니코드 UTF-8: 최대 4바이트)
- find()
활용
- 온라인 게임이나 채팅 앱에서 흔히 쓰일법한 채팅 필터링에 쓰일 수 있다. 다만 위 find() 함수는 시간복잡도 탓에 적합하지 않고, 트라이(Trie, 이진 트리의 3갈래 버전)을 사용하는 방식인 아호코라식(Aho-Corasick)을 사용하면 더 빠르게 구현할 수 있다.
- 언리얼 엔진에서는 string에 대응되는 자료형인 FString이 존재한다.
- 위에 나왔던 함수들에 대응되는 Find(), Mid(), Replace() 외에도 Left(), Right()등 다른 기능 함수들도 지원한다.
- JSON,XML등으로 저장된 게임 세이브 데이터, 작업용 데이터, 혹은 URL을 통해 전달되는 웹사이트 정보나 쿼리등을 저장하고(직렬화) 불러오는데(파싱) 사용될 수 있다.
- 서버의 로그 분석에서는 find, substr, stringstream을 이용한 로그 탐색과 분석이 기초적인 패턴이다.
- 운영체제와 네트워크, DB등에서도 문자의 인코딩은 기본적인 기능으로서 위치한다. 인코딩이 깨져 상황을 이해할 수 없는 상황은 안좋은 사용자 경험을 초래하고 에러에 취약하게 만든다.
- 해쉬(Hash)와도 문자를 숫자로 일대일 대응하여 사용한다는 점에서 비슷할 수 있으나, 목적이 문자열 저장인지 아니면 빠른 시간복잡도의 보장인지에서 갈린다.
This post is licensed under CC BY 4.0 by the author.