[목차]
1. keyboard 입력
- <string> : getline(cin, address, '\n'
- <cstring> : cin.getline(address, 크기, '\n');
- 1번 키보드 입력 관련 자세한 내용은 ↓ 아래 포스팅에 나와 있습니다.
2. 문자열 함수
- 문자열의 크기 ( .size(), .length(), .capacity() ... )
- 조작함수 ( .append(), substr(), replace(), find(), ... )
- 문자열 변경 ( to_string() , stoi() ... )
- 문자열 연산자 ( +, +=, 관계 연산자 )
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 대신 문자열을 덧붙이고, 관계 연산자를 통해 조건문을 실행할 수 있습니다.
'C++ > C++ 기초' 카테고리의 다른 글
[C++] 참조 매개 변수 / 참조 리턴 (Reference parameter / Reference return) + Call-by-reference (0) | 2023.07.09 |
---|---|
[C++] 동적 메모리 할당 : new / delete 연산자 (0) | 2023.07.06 |
[C++] 기본 입출력 ( 화면 출력 / 키 입력받기 / 문자열 입력받기 ) (0) | 2023.07.02 |
[C++] 템플릿 ( Template ) - 함수 템플릿 / 클래스 템플릿 (0) | 2023.05.05 |
[C++] 생성자와 소멸자 ( Constructor and Destructor ) (0) | 2023.05.05 |