본문 바로가기

프로그래밍 강좌/C++

[C++] std::string 클래스 ( 문자열 ) 사용법 완벽 총정리 - string 확장 함수 erase find append stoi to_string

이번엔 문자열(string)을 다루는 클래스인 string 클래스를 파헤쳐 보겠습니다.

이번에는 std::string 의 모든 것을 정리해봤으니 끝까지 읽어 주세요.

 

string 입/출력 방법

이전에 C에서는 char* 나 char[]의 형태로 문자열을 다뤘다면, c++에서는 문자열을 하나의 변수 type으로 간주하여

다룰 수 있게 합니다.

char*나 char[]와 다르게 문자열 끝에 '\0'이 포함되지 않아 문자열의 길이 동적으로 변경이 가능합니다.

지난번에 말씀드린 것과 같이 cin을 통해 string을 입력받을 수 있었습니다.

#include <iostream>
#include <string>

int main()
{
    std::string str;   

    std::cout << "cin 입력:" << std::endl;
    std::cin >> str;
    std::cout << "cin 결과:" << str << std::endl;

    return 0;
}
 

cin>>str : 공백(space)가 입력될 때까지 값을 받습니다.

그래서 cin에 Console Input 을 입력하면 str 에는 Console 밖에 저장되지 않습니다.

cin 의 공백이 들어오면 더이상 받을 수 없는 단점을 보완하려면 getline()을 사용하면 됩니다.

#include <iostream>
#include <string>

int main()
{
    std::string str;   

    std::cout << "getline 입력:";
    std::getline(std::cin, str);
    std::cout << "getline() 결과:"<<str << '\n';

    std::cout << "getline 입력:";
    std::getline(std::cin, str, 'i');
    std::cout << "getline() 결과:" << str << std::endl;

    return 0;
}
 

getline()은 두개가 있는데, #include <fstream>을 추가하고

std::cin.getline()으로 얻어오는 방법도 있지만 #include <string>을 추가하면 std::getline()을 사용할 수 있습니다.

getline은 아래와 같이 구성되어 있습니다.

위 소스 코드의 결과는 아래와 같습니다.

getline() 에서 구분 문자에 'i'를 넣으니까 i 전까지인 getl 만 읽어 옵니다.

구분 문자는 ',' 등 다른 기호를 사용하실 수도 있습니다.

 

string 객체 생성 방법

string 객체를 생성하는 방법은 여러가지가 있지만 대표적으로 아래와 같습니다.

// 빈 문자열 생성	
std::string str;

// "abcdefg"로 선언된 string 생성
std::string str1 = "abcdefg";

std::string str2;
str2 = "abcdefg";

std::string str3("abcdefg");

// str3 문자열을 복사한 str4 생성
std::string str4(str3);

// C에서의 문자열과 호환 가능
char s[] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g' };
std::string str5(s);

// new를 이용한 동적 할당
std::string *str6 = new std::string("abcdefg");
 
string 클래스 멤버 함수

 

std::string은 STL 중 하나입니다.

그럼 vector와 같이 유사한 멤버 함수들을 가지고 있겠죠? 그걸 알아보겠습니다.

 
str.at(idx)
idx 위치 문자 반환, 범위 유효성 체크 O
str[idx]
idx 위치 문자 반환, 범위 유효성 체크 X
str.front()
문자열의 가장 앞의 문자 반환
str.back()
문자열의 가장 뒤의 문자 반환

 

#include <iostream>
#include <string>

int main()
{
	std::string str = "abcdefg";

	std::cout << "4번째 원소(d):" << str.at(3) << std::endl;
	std::cout << "6번째 원소(f):" << str[5] << std::endl;
	std::cout << "제일 앞 원소(a):" << str.front() << std::endl;
	std::cout << "제일 뒤 원소(g):" << str.back() << std::endl;

	return 0;
}
 

index는 항상 '0'부터 시작한다는 사실!!

그래서 idx 자리에 3이 있지만 4번째 원소를 반환하죠.

 

2. 문자열의 크기

 
str.length()
문자열 길이 반환
str.size()
문자열 길이 반환(length()와 동일)
str.max_size()
최대한 메모리 할당할 경우 저장할 수 있는 문자열 길이 반환
str.capacity()
문자열의 메모리 크기 반환
str.resize(n)
str을 n의 크기로 만듦. 삭제 또는 빈 공간으로 채움
str.resize(n, 'a')
n이 str 길이보다 크면 빈 공간을 'a'로 채움
str.shrink_to_fit()
capacity가 실제 사용하는 메모리보다 큰 경우 메모리 줄여 줌(메모리 낭비 제거)
str.reserve(n)
사이즈 n 만큼의 메모리 미리 할당
str.empty()
str이 빈 문자열인지 확인

 

#include <iostream>
#include <string>

int main()
{
	std::string str = "abcdefg";

	std::cout << "문자열 길이:" << str.length() << std::endl;
	std::cout << "문자열 사이즈:" << str.size() << std::endl;
	std::cout << "문자열 메모리 크기:" << str.capacity() << std::endl;

	str.resize(4);
	std::cout << "문자열 길이 줄임:" << str << std::endl;

	str.resize(10, 'a');
	std::cout << "문자열 길이 늘이고 'a'로 채움:" << str << std::endl;

	str.reserve(15);
	std::cout << "문자열 메모리 할당:" << str.capacity() << std::endl;
	std::cout << "문자열 사이즈:" << str.size() << std::endl;

	str.shrink_to_fit();
	std::cout << "문자열 메모리 최적화:" << str.capacity() << std::endl;

	std::cout << "문자열 비었는지 확인:" << str.empty() << std::endl;

	return 0;
}
 

결과는 아래와 같이 나옵니다.

str.reserve(15)를 하면 메모리를 15개를 잡지만, 문자열 사이즈는 여전히 10인것을 볼 수 있습니다.

이것이 capacity length()/size()의 차이입니다.

 

3. 문자열 삽입/추가/삭제

string도 vector 처럼 사용법이 비슷하죠? string 도 STL이기 때문입니다.

 
str.append(str2)
str 뒤에 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()
clear()와 같음
str.erase(n, m)
n번째 index부터 m개의 문자를 지움
str.erase(n, m) ← iterator
n~m index 문자열을 지움(n, m은 iterator임)
str.push_back(c)
str의 맨 뒤에 c를 붙여 줌
str.pop_back()
str의 맨 뒤의 문자를 제거
str.assign(str2)
str 에 str2 문자열을 할당함

 

테스트 코드는 아래와 같아요.

#include <iostream>
#include <string>

int main()
{
	std::string str = "abcdefg";
	std::string str2 = "hijklmn";

	str.append(str2);
	std::cout << "1. "<< str << std::endl;
	str.append(str2, 1, 3);
	std::cout << "2. " << str << std::endl;
	str.append(3, 'z');
	std::cout << "3. " << str << std::endl;
	str.clear();
	std::cout << "4. " << str << std::endl;
	str.assign("abcdefg");
	std::cout << "5. " << str << std::endl;
	str.insert(2, str2);
	std::cout << "6. " << str << std::endl;
	str.replace(3, 3, "vv");
	std::cout << "7. " << str << std::endl;
	str.erase(0, 3);
	std::cout << "8. " << str << std::endl;
	str.erase();
	std::cout << "9. " << str << std::endl;
	str.push_back('abc');
	std::cout << "10. " << str << std::endl;	
	str.push_back('d');
	std::cout << "11. " << str << std::endl;
	str.pop_back();
	std::cout << "12. " << str << std::endl;	
	
	return 0;
}
 

결과는 아래와 같은데, 7.번에서 3번째 index 에서 3글자 "vv"로 바꿔라 라고 하니까 3글자가 지워지고 2글자만 삽입이 되었네요.

또한 10. 번에서 push_back()에 여러글자를 넣으니까 마지막 한글자만 추가가 되네요.

4. 부분 문자/비교/복사/찾기

 
str.substr()
str 전체를 반환
str.substr(n)
str의 n번째 index부터 끝까지 부분 문자열 반환
str.substr(n, k)
str의 n번째 index부터 k개의 부분 문자열 반환
str.compare(str2)
str과 str2가 같은지 비교, str<str2인 경우 음수, str>str2인 경우 양수 반환
str.copy(str2, k, n)
str의 n번째 index부터 k개의 문자열 복사
str.find("abcd")
"abcd"가 str에 포함되어 있는지 확인, 찾으면 해당 부분 첫 index 반환
str.find("abcd", n)
n번째 index부터 "abcd"를 찾음
str.find_first_of("/")
"/"가 처음 나타나는 index
str.find_last_of("/")
"/"가 마지막으로 나타나는 index

 

#include <iostream>
#include <string>

int main()
{
	std::string str = "abcdefg";
	std::string str2 = "hijklmn";	

	std::string str3 = str.substr();
	std::cout << "전체 복사:" << str3 << std::endl;
	std::string str4 = str.substr(3);
	std::cout << "4번째부터:" << str4 << std::endl;
	std::string str5 = str.substr(2, 4);
	std::cout << "3번째부터 4개 문자열:" << str5 << std::endl;
	std::cout << "두 문자열 같은지:" << str.compare(str2) << std::endl;	
	std::cout << "문자열 찾기:" << str.find("bcd") << std::endl;
	if (str.find("bcd", 2) != std::string::npos) {
		std::cout << "3번째부터 문자열 찾기:" << str.find("bcd", 2) << std::endl;
	}
	else
		std::cout << "3번째부터 문자열 찾기:" << "못찾음" << std::endl;
	std::string str6 = "C:/program/temp/test";	
	std::cout << "'/'시작 인덱스:" << str6.find_first_of("/") << std::endl;
	std::cout << "'/'마지막 인덱스:" << str6.find_last_of("/") << std::endl;

	return 0;
}
 

실행 결과는 아래와 같아요.

string의 인자로는 인덱스와 길이를 쌍으로 입력받는 경우가 많습니다.

인덱스와 인덱스를 받는 경우가 없으니 주의하세요!

 

5. 기타 유용한 함수들

str.c_str()
string을 c스타일의 문자열로 변경
str.begin()
string의 시작 iterator 반환
str.end()
string의 끝 iterator 반환
swap(str, str2)
str과 str2를 바꿔줌
str = str2 + str3
str2와 str3를 붙여서 str에 복사함
str += str2
str 뒤에 str2를 붙여줌
str = str2
str에 str2 복사 (Deep Copy)
str == str2
str과 str2가 같은지 확인
str > str2, str < str2
str이 str2보다 사전순으로 앞인지 뒤인지 확인
isdigit(c)
#include <cctype>, c가 숫자인지 확인, 숫자이면 0이 아닌 숫자 반환
isalpha(c)
#include <cctype>, 알파벳 확인, 대문자는 1 반환, 소문자는 2 반환, 알파벳이 아니면 0 반환
toupper(c)
#include <cctype>, c를 대문자로 변환
tolower(c)
#include <cctype>, c를 소문자로 변환
stoi(), stof(), stol(), stod()
문자열을 숫자로 변환(int, float, long, double)
to_string(n)
숫자 n을 문자열로 변환

 

#include <iostream>
#include <string>
#include <cctype>

int main()
{
	std::string str = "abcdefg";
	std::string str2 = "hijklmn";	
	std::string str3 = str;	

	const char* carrName = str.c_str();
	std::cout << "c스타일:" << carrName << std::endl;

	std::string str4 = { str.begin(), str.end() };
	std::cout << "문자열 bein(), end()로 복사:" << str4 << std::endl;
	std::cout << "첫번째 원소값:" << *str.begin() << std::endl;
	std::cout << "iterator로 전체 원소 print하기:";
	for (std::string::iterator iter = str.begin(); iter != str.end(); ++iter) {
		std::cout << *iter;
	}
	std::cout << std::endl;

	std::string str5 = str + str2;
	std::cout << "str + str2:" << str5 << std::endl;
	str += str2;
	std::cout << "str += str2:" << str << std::endl;
	str = str3;
	std::cout << "str = str3:" << str << std::endl;
	std::cout << "str == str2:" << (str == str2) << std::endl;

	std::string str6 = "123a";
	for (const auto& s : str6) {
		std::cout << s << " is digit?:" << std::isdigit(s) << std::endl;
	}	

	std::string str7 = "1Ab3";
	for (int i = 0; i < str7.size(); ++i) {
		std::cout << str7[i] << " is alphabet?:" << std::isalpha(str7[i]) << std::endl;
	}

	std::string str8 = "aBcDeF";
	std::cout << str8 << "를 대문자로:";
	for (int i = 0; i < str8.size(); ++i) {
		str8[i] = std::toupper(str8[i]);		
	}
	std::cout << str8 << std::endl;

	std::cout << str8 << "를 소문자로:";
	for (auto& s : str8) {
		s = std::tolower(s);		
	}
	std::cout << str8 << std::endl;

	std::string str9 = "123";
	std::cout << "숫자로 변환:" << std::stoi(str9) << std::endl;

	float fNum = 10.234;
	std::string str10 = std::to_string(fNum);
	std::cout << "to_string:" << str10 << std::endl;

	return 0;
}
 

실행 결과는 아래와 같습니다.

여기에서 toupper(), tolower()대/소문자의 아스키 코드를 반환합니다.

예를 들어

#include <iostream>
#include <string>
#include <cctype>

int main()
{
	std::string str = "aBcD";
	for (int i = 0; i < str.size(); ++i)
		std::cout << "'"<<str[i]<<"' 의 대문자 Ascii Code:" << std::toupper(str[i]) << std::endl;

	return 0;
}
 

이렇게 해 보면,

아래와 같이 나옵니다.

그걸 std::string으로 받으면 형변환이 되어 string으로 저장되는 것 입니다.

그리고 stoi()종류나 to_string() 많이 사용하니까 꼭 알아두세요.

그리고 string to char*, char* to string 변환에 대해 궁금하시면 아래를 참조하세요

https://m.blog.naver.com/dorergiverny/223088641477

 

[C++] string to char* 와 char* to string 문자열 변환 총정리 const c_str strcpy begin vector

이전에 std::string 클래스에 대해 총정리를 해 보았습니다. https://m.blog.naver.com/dorergiverny/22304...

blog.naver.com