본문 바로가기
Programming/C++

[Modern C++ 공부 - Day8] String Operations

by 롱일스 2023. 7. 5.
반응형

 

Modern C++ 공부 Day 8입니다.

1. string의 기본 operations

1. Assignment
s1 = s2;

2. Appending
s1 += s2;

3. Concatenating
s1 + s2;

4. Comparison
s1  == s2
s1 != s2
s1 >= s2
s1 > s2
s1 <= s2
s1 < s2

2. string의 member functions  - (1) c_str

C-style string으로 copy해서 return하는 멤버 함수다.

 

3. string의 member functions  - (2) substr

string 변수의 substring을 반환하는 멤버함수다. 매개변수를 하나만 주면, substring의 첫번째 index를 주고, 두 개를 주면, 두번째 매개변수로는 substring의 길이를 주면된다.

string test {"hello"};
string test2 = test.substr(2);   // test2 = "llo"
string test3 = test.substr(2, 2);   // test3 = "ll"

 

4. Constructors 생성자

1. Default 생성자
string test1;

2. String literal 생성자
string test2 {"hello"};

3. count와 initial value 생성자
string test3 {3, 'h'};   // test3 = "hhh";

4. initializer list 생성자
string test4 {'h', 'e', 'l'}; // test4 = "hel";

5. 이미 존재하는 string의 substring을 이용한 생성자
string test5(test2, 2};  // test5 = "llo"
string test5(test2, 2, 2};  // test5 = "ll" (string, initial index number, number of char)

 

5. string에서의 탐색 searching

(1) find() 멤버 함수: 처음 매치된 argument의 index를 반환한다.

1. find() 멤버 함수: 처음 매치된 argument의 index를 반환한다.

string test {"hello world"};
test.find('o'); // returns 4
test.find("or"); // returns 7
test.find('O'); // returns string::npos (매치되는 argument를 찾지 못했을 때 반환하는 것)

size_t idx = test.find('o');
if (idx == string::npos) {
	cout << "Could not find 'o' in the string" << endl;
}
else {
	cout << "First match of 'o' is at index " << idx << endl;
}

 

(2) rfind() 멤버 함수: 가장 마지막에 매치된 argument의 index를 반환한다. 기본적으로 탐색이 string의 맨뒤에서부터 시작된다.

2. rfind() 멤버 함수: 가장 마지막에 매치된 argument의 index를 반환한다. 기본적으로 탐색이 string의 맨뒤에서부터 시작된다.

string test {"hello world"};
test.rfind('o');   // returns 7
test.rfind("or");  // returns 7

// index 5부터 왼쪽방향으로 탐색해라.
test.rfind('o', 5); // returns 4

(3) find_first_of() 와 find_last_of() 멤버 함수: 매개변수 string과 처음 (마지막)으로 매치되는 argument를 반환한다.

find_first_not_of() 와 find_last_not_of() 멤버 함수: 매개변수 string과 처음 (마지막)으로 매치되지 않는 argument를 반환한다.

string str {"eioua"};
test.find_first_of(str); // returns 1  (e)
test.find_last_of(str); // returns 7  (o)

test.find_first_not_of(str); // returns 0 (h)
test.find_last_not_of(str); // returns 10  (d)

 

6. string 추가, 변형 - (1) append(), (2) insert(), (3) erase(), (4) replace()

1. append() 멤버 함수: argument를 string 뒤에 이어붙인다.
substring을 바로 이어붙일 수 있다는 장점이 있다. 

string test {"hello"};
test.append(" world"s);  // test = "hello world"

test.append("hey brothers>_<"s, 3, 4); // test = "hello world bro" 


2. insert() 멤버 함수: 특정 index바로 앞에 characters를 추가할 수 있다. string literal 이나 string 변수도 삽입할 수 있는 등 overloads 여러가지 가능하다.

string test1{ "for" };
test1.insert(2, "lde"s); // "lde"를 test1[2] 앞에 삽입 --> test1 = "folder"

string test2{"care"};
string test3{"omp"};
test2.insert(1, test3);  // test3를 test2[1] 앞에 삽입 --> test2 = "compare"


string test3 {"xx"};
string test4 {"asdfbosa"};
test3.insert(1, test4, 4, 2);  // test3 = "xbox"

string test5("cash");
test5.insert(1, 3, 'r'); // 'r'을 test5[1] 앞에 3번 삽입 --> test5 = "crrrash"

auto test6 = yello.find('o');
yello.insert(test6, 2, 'o'); // 'o'를 2번 yello의 4번째 index 뒤에 삽입. --> test6 = "yellooo"

// iterator를 이용해서 insert()활용도 가능합니다.
string test7{"word"};
auto idx = end(test7) - 1;
test7.insert(idx, 'l');     // test7 = "world"

3. erase() 멤버 함수: string에서 characters를 제거한다. 2개의 arguments를 입력해야 한다. 
(1) 삭제하고픈 element의 첫번째 index 와 (2) 몇 개의 character를 삭제할건지 입력한다.

string test8 {"hello"};
test8.erase(3, 1);  // 4번째 character 삭제
auto idx = hello.find('e');
if (idx != string::npos)   // e가 처음 등장할 때의 idx
	test8.erase(idx, 2);     // idx에서 시작해서 2개의 elements 삭제

// iterator를 이용해서 erase() 활용    
auto first = begin(test8);  // "h"
test8.erase(first);   //  test8 = "ello"

//범위를 주고 삭제할 수도 있다.
test8.erase(begin(test8) + 1, end(test8) - 1); // 첫번째랑 마지막 character 빼고 다 삭제 --> test8 = "eo";


4. replace() 멤버 함수: string의 characters를 다른 characters로 대체한다.
3개의 arguments를 줄 수 있다. (1) 첫번째로 대체하려는 elements의 첫번째 character index, (2) 두 번째는 대체하려는 element의 characters 개수, (3) 대체하려는 characters.

string test("Say Hello");
auto idx = test.find('H');
test.replace(idx, 5, "Christmas");   // test = "Say Christmas"

// iterator를 이용한 replace()
test.replace(begin(test), begin(test)+3, "Merry");  // "Merry Christmas"

 

7. string 과 int 사이의 변환

string에서 숫자로/ 숫자에서 string으로 전환하는 멤버함수로 stoi(), stod()가 있다.
c++11 에서는 to_string()을 사용해서 int와 float을 std::string 타입으로 바꿨다. 
C에서는  atoi(), atod()를 이용해서 string에서 숫자로 바꿨다.

1. stoi() 멤버함수는 string에서 int로 convert하는 함수다. std::string을 input으로 받고 int를 반환한다.

string test{"10"};
cout << stoi(test) << endl; // 10

// 맨처음에 빈칸으로 시작하는 string의 경우에는 빈칸(whitespace)가 무시된다.
string test2{" 123 456"};
cout << stoi(test2) << endl; // 123 출력된다. 123 다음에 빈칸은 숫자가 아니기 때문에 여기서 stop해서 빈칸 전까지만 int로 전환되고 뒤에는 무시된다.

2. stoi() 함수에서 두번째 argument를 이용해서 몇개의 character가 int로 변환되었는지 알 수 있습니다. 두 번재 argument로는 size_t 변수에 대한 포인터를 사용합니다. 이 size_t 변수는 정수 변환에 사용되지 않는 문자열의 첫 번째 문자의 위치를 채우게 됩니다. stoi() 함수에서 에러가 발생하지 않으면 두번째 argument가 첫번재 argument로 주어진 string의 길이와 동일하다는 의미다. 

만약 일부만 전환된 경우에는, 아래 예시에서 n은 숫자가 아닌 첫번째 character의 index가 된다.

size_t n;
auto x = stoi(test2, &n); // n = 4 가 된다. 4번째 index가 공백이라 여기서부터 변환이 안되기 때문.

if (n < test2.size()) cout << "cannot convert entire string starting from " << n << endl;

만약 전환이 아예 되지 않은 경우에는 exception을 throw한다. 
stoi("qweasd"s);   // 'std::invalid_argument' 반환, 숫자가 아닌 characters는 int로 변환 불가


3. stoi()는 기본적으로 decimal 값으로 이루어진 string을 받지만, 3번재 argument를 이용해서  다른 진법(base)의 숫자 형태로 이루어진 string도 변환할 수 있다.
* 0-36, 0-9, A-Z, a-z로 이루어질 수 있다.

stoi("2a", nullptr, 16);  // 42를 반환한다. 이 때 몇 개의 characters가 변환되는지 궁금하지 않은 경우에는 2번째 argument로 nullptr를 주면된다.

4. stod() 멤버함수는 string을 floating-point로 변환하는 함수로 double 타입을 return한다. stoi()와 달리 다른 base를 사용할 수 없고 10진법만 가능하다. 

string test3{"1.234567"};
cout << stoi(test3) << endl;   // 1 출력
cout << stod(test3) << endl;   // 1.23457 출력

2번째 argument를 이용하는 방법은 stoi()와 같은 방식으로 사용할 수 있다.

 

8. 그 외의 유용한 함수들

1. data() 멤버 함수는 C++20에서 일련의 연속된 요소를 가진 컨테이너 또는 배열에서 포인터를 얻는 데 사용된다. 이 함수는 컨테이너 또는 배열의 첫 번째 요소에 대한 포인터를 반환하며, 이 포인터는 컨테이너의 데이터를 나타내는 데 사용할 수 있다.

이는 다음과 같은 경우에 유용하다:

(1)데이터를 C스타일 배열이나 이전 버전의 C++ 코드로 전달해야 할 때
(2)연속된 메모리에 있는 데이터를 다룰 수 있는 저수준 API로 전달해야 할 때
(3)연속된 메모리 블록을 가리키는 포인터가 필요한 다른 상황

std::string과 std::vector는 data()멤버함수를 가지고 있다. 
data()는 container의 internal memory buffer를 가리키는 포인터를 반환한다.

std::vector<int> vec {1, 2, 3, 4, 5};
int* p = std::data(vec);

// p now points to the first element of vec
// We can dereference p to get the first element
std::cout << *p << std::endl;  // Output: 1


2. swap() 멤버함수는 두 string을 바꾸는 함수다.

string s1{"hello"};
string s2{"bye"};

s1.swap(s2); // s1 = "bye", s2 = "hello"


3. 그 외의 다양한 함수들
isdigit(c);  // c가 digit (0-9)면 true를 반환
islower(c);   // c가 lower case (a-z)면 true를 반환 
isupper(c);   // c가 lower case (A-Z)면 true를 반환 
isspace(c);  // c가 (space, tab,..)면 true를 반환
ispunct(c);    // c가 (?, !, ., etc)면 true를 반환

tolower(c);   // 대문자로 변환 
toupper(c);   // 소문자로 변환
728x90
반응형