C++/C++ 기초

[C++] 문자열 관련 함수 : string 클래스 정리 및 사용법

Song 컴퓨터공학 2023. 7. 5. 16:05

[목차]

1. keyboard 입력

  • <string> : getline(cin, address, '\n'
  • <cstring> : cin.getline(address, 크기, '\n');
  • 1번 키보드 입력 관련 자세한 내용은 ↓ 아래 포스팅에 나와 있습니다.
 

[C++] 기본 입출력 ( 화면 출력 / 키 입력받기 / 문자열 입력받기 )

[목차] 1. 화면 출력 2. 키 입력 받기 (cin) 3. 문자열 입력 받기 cin.getline() 을 이용해 받는 방법 : 배열로 문자열 저장하는 경우 getline() 을 이용해 받는 방법 : string 객체 사용하는 경우 화면 출력 - co

songsite123.tistory.com

2. 문자열 함수


String 클래스란 C++ STL 에서 제공하는 클래스로, 문자열을 다루는 클래스입니다. C에서 char* 이나 배열의 형태로 문자열을 다뤘다면 C++에서는 마치 하나의 변수(객체) 처럼 사용하게 되고, 훨씬 쉽게 다룰 수 있습니다. string 클래스를 사용하기 위해서는 #include <string> 헤더 파일을 사용해야만 합니다.

 

C에서 다루던 방식의 char*, char[] 와는 다르게 문자열의 끝에 '\0' 이 들어가지 않으며, 문자열의 길이를 동적으로 변경할 수 있다는 특징이 있습니다.

 

 

 

 string 클래스 생성 / 입/출력

 

<string>을 include 한 이후 string 을 생성하는 방법은 다음과 같습니다.

string str;  빈 문자열 str 생성
 string str = "abcdef";
-------------------------------
 string str;
 str = "abcdef";
 "abcdef" 로 선언된 str 생성
 string str("abcdef");  "abcdef" 로 선언된 str 생성
 string str2(str1);  str1 문자열을 복사한 str2 생성
 char s[ ] = {'a', 'b', 'c', 'd', 'e', 'f'};
 string str(s);
 C에서의 문자열과 호환 가능
 string *str = new string("abcdef");
 new를 이용한 동적할당

string 을 통해 입출력을 하는 방법은 C++ 입출력 방식인 cin 과 cout 으로 입출력이 가능하고, cin 으로 입력 받는 경우 공백을 인식하지 못하고 공백 앞까지만 읽어들이기 때문에 이런 경우에는 getline 함수를 사용해 입력을 받아줍니다.

string str;         	// 문자열 생성
cin >> str;          	// 공백(space) 이전까지의 문자열을 입력받는다.
getline(cin, str);	// '\n' 이전까지의 문자열, 즉 한 줄을 통째로 입력받는다.  (공백 포함)
getline(cin, str, 'a')	// 'a' 문자 이전까지의 문자열을 입력받는다. getline(cin, str, '\n') == getline(cin, str)  
cout << str;        	// 문자열을 출력한다.

 

#include <iostream>
#include <string>
using namespace std;

int main() {
	string str;
	getline(cin, str);
	cout << "str : " << str << '\n';
	getline(cin, str, 'p');
	cout << "str : " << str << '\n';
	cin >> str;
	cout << "str : " << str << '\n';
}

getline 함수에서 구분자를 'p' 로 지정해주어 Song Co 까지만 입력을 받아 str에 저장하고, 그 다음의 cin >> str 구문은 현재까지 입력받은 위치부터 공백이 나올 때까지를 입력 받으므로 uter만 저장되는 것을 알 수 있습니다.

 

 

 

 문자열의 크기

 

string 클래스의 문자열 크기를 얻는 방법은 크게 size(), length() 가 있습니다. 부가적으로 capacity() 가 무엇인지까지 배워봅시다. 먼저 간단한 예시 코드를 통해 3가지 함수를 확인해봅시다.

#include <iostream>
#include <string>
using namespace std;

int main() {
	string str = "Song Blog";
	cout << "str : " << str << endl;
	cout << "str.size() : " << str.size() << endl;
	cout << "str.length() : " << str.length() << endl;
	cout << "str.capacity() : " << str.capacity() << endl;
}

size 와 length, capacity 는 모두 string 클래스의 멤버함수이기 때문에 .을 붙여서 사용합니다. 그런데 위 문자열은 공백을 포함하여 9자리가 맞는데 이상하게 capacity() 만 15가 나오고 있습니다. capacity 가 의미하는 것은 배열의 전체 용량 입니다. 우리가 9개의 문자열을 저장한 것이 맞으나 std::string이 추후 str에 새로운 문자열이 추가되거나 변경되었을 때 배열의 크기를 다시 할당하지 않도록 일부러 여유 공간을 남겨놨기 때문입니다. 한 번 15를 넘어가는 숫자를 넣어서 다시 확인해보면

18의 길이를 가질 때나 30의 길이를 가질 때나 31의 용량을 가지는 것을 볼 수 있습니다. 이 쯤에서 궁금해지는데요 어떤 기준으로 증가하는 걸까는 상황에 따라 다를 수 있기 때문에 조금만 더 늘려보면

뭔가 4비트 단위로 처리하는 느낌은 납니다. 아무튼 capacity 가 의미하는 것은 동적 할당 받아놓은 배열의 전체 크기라는 것을 알아주시면 되고, 지금까지 계속 봤듯 size() 와 length() 는 제대로 문자열의 길이를 반환하는 멤버 함수 입니다.

 

그런데 .size() 와 .length() 의 기능이 같다면 굳이 2개를 만들어 놓지 않았겠죠? 엄밀하게 따지면 .length() 함수는 주로 string 클래스에서 사용되는 멤버 함수로 string 객체의 문자열의 길이를 반환하는 이름 그대로의 함수입니다.

 

그러나 size() 는 string 클래스에서만 사용되는 함수가 아닙니다. 추후 배울 vector, array 등의 클래스(이를 컨테이너라고 함) 에서도 사용할 수 있는 좀 더 범용적인 멤버함수입니다. size() 함수는 해당 컨테이너의 요소 수를 반환합니다.

 

결론적으로 string 클래스에서 문자열의 길이를 구할 때는 length 나 size 무엇을 써도 무방하지만, size 가 다른 컨테이너에도 적용될 수 있는 더 범용적인 멤버 함수입니다.

 

 

 

 조작함수 (string 클래스의 멤버 함수)

 

▶ string의 특정 원소 접근

 str.at(index) index 위치의 문자 반환. 유효한 범위인지 체크 O
 str[index] index 위치의 문자 반환. 유효한 범위인지 체크 X. 따라서 at 함수보다 접근이 빠름
 str.front() 문자열의 가장 앞 문자 반환
 str.back() 문자열의 가장 뒤 문자 반환

 

▶ string의 크기

 str.length() 문자열 길이 반환
 str.size() 문자열 길이 반환 (length와 동일)
 str.capacity() 문자열이 사용중인 메모리 크기 반환
 str.resize(n) string을 n의 크기로 만듦. 기존의 문자열 길이보다 n이 작다면 남은 부분은 삭제하고, n이 크다면 빈공간으로 채움
 str.resize(n, 'a') n이 string의 길이보다 더 크다면, 빈 공간을 'a'로 채움
 str.shrink_to_fit() string의 capacity가 실제 사용하는 메모리보다 큰 경우 낭비되는 메모리가 없도록 메모리를 줄여줌
 str.reserve(n) size = n만큼의 메모리를 미리 할당해줌
 str.empty() str이 빈 문자열인지 확인

 

▶ string에 삽입, 추가, 삭제

 str.append(str2) str 뒤에 str2 문자열을 이어 붙여줌 ('+' 와 같은 역할)
 str.append(str2, n, m) str 뒤에 'str2의 n index부터 m개의 문자'를 이어 붙여줌
 str.append(n, 'a') str 뒤에 n개의 'a'를 이어 붙여줌
 str.insert(n, str2) n번째 index 앞에 str2 문자열을 삽입함.
 str.replace(n, k, str2) n번째 index부터 k개의 문자를 str2로 대체함
 str.clear() 저장된 문자열을 모두 지움
 str.erase(n, m) n번째 index부터 m개의 문자를 지움
 str.erase(n, m) (iterator) n~m index의 문자열을 지움 (n과 m은 iterator)
 str.erase() clear와 같은 동작
 str.push_back(c) str의 맨 뒤에 c 문자를 붙여줌
 str.pop_back() str의 맨 뒤의 문자를 제거
 str.assign(str2) str에 str2 문자열을 할당. (변수 정의와 동일)

 

▶ 기타 유용한 string 멤버 함수

 str.find("abcd") "abcd"가 str에 포함되어있는지를 확인. 찾으면 해당 부분의 첫번째 index를 반환
 str.find("abcd", n) n번째 index부터 "abcd"를 find
 str.substr() str 전체를 반환
 str.substr(n) str의 n번째 index부터 끝까지의 문자를 부분문자열로 반환
 str.substr(n, k) str의 n번째 index부터 k개의 문자를 부분문자열로 반환
 str.compare(str2) str과 str2가 같은지를 비교. 같다면 0, str<str2 인 경우 음수, str>str2 인 경우 양수를 반환
 swap(str1, str2) str1과 str2를 바꿔줌. reference를 교환하는 방식
 isdigit(c) c 문자가 숫자이면 true, 아니면 false를 반환 
 isalpha(c) c 문자가 영어이면 true, 아니면 false를 반환
 toupper(c) c 문자를 대문자로 변환
 tolower(c) c 문자를 소문자로 변환

 

 

 

 문자열 변경 [ string → int "to_string()", int → string "stoi()" ] 

 

코딩을 하다보면 int 형을 string 문자열로 바꾸거나 문자열로 주어진 숫자를 int 형 정수로 바꾸는 일이 빈번하게 필요합니다. C++ 에서 이 기능은 to_string 함수stoi 함수 를 사용해서 변환합니다. 인자로 주어진 값을 변환시킵니다.

 

#include <iostream>
#include <string>
using namespace std;

int main() {
	string str = "Song";
	string num = "100";
	int n = 30;

	// cout << "stoi(str) : " << stoi(str) << endl; // Debug Error !
	cout << "stoi(num) : " << stoi(num) << endl;
	cout << "to_string(n) : " << to_string(n) << endl;
}

stoi() 함수의 인자에 숫자로 표현되지 않은 Song 이라는 문자열을 int 로 변형시키려고 하니 바로 Debug Error 가 발생하네요. 조금 수정해서 숫자가 포함된 문자열을 테스트해보니

가장 맨 처음에 나오는 문자가 숫자여야하고, 그 뒤에 숫자가 아닌 문자가 온다면 숫자까지만 정수로 변형시켜주는 것을 확인할 수 있었습니다. 또한 to_string() 함수는 애초에 필요한 매개변수가 int 형이기 때문에 다른 것을 넣으면 오류가 발생합니다.

 

 

 

 문자열 연산자 (+, +=, 관계 연산자)

 

string 클래스에 적용할 수 있는 연산자는 크게 2종류 입니다. append 와 동일한 역할을 하는 +, += 연산자. 그리고 ==, >= > , != ... 와 같은 관계 연산자입니다.

#include <iostream>
#include <string>
using namespace std;

int main() {
	string str1 = "Song";
	string str2 = " blog";
	

	cout << "str1 : " << str1 << endl;
	cout << "str2 : " << str2 << endl;
	cout << "str1 + str2 : " << str1 + str2 << endl;
	cout << "str1.append(str2) : " << str1.append(str2) << endl;
	cout << "str1.erase(4) : " << str1.erase(4) << endl;
	str1 += str2;
	cout << "str1 : " << str1 << endl;
	(str1 == str2) ? cout << "True" << endl : cout << "False" << endl;
}

이런 식으로 연산자를 통해서 append 대신 문자열을 덧붙이고, 관계 연산자를 통해 조건문을 실행할 수 있습니다.