코딩테스트를 위한 C++ 문자열 처리

신현철·2023년 2월 24일
4

TIL

목록 보기
5/5
post-thumbnail

파이썬으로 코테 연습을 하다가 C++로 넘어와서 그런지 항상 문자열 핸들링 하는게 익숙치 않아서 정리해보았다.

📗 입출력 속도 향상

int main() {
	// 0. 입출력 속도 향상
    // stdio의 스트림과 동기화 해제
    ios_base::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);
}

📙 EOF가 포함된 입력을 받을 때

    // 1. EOF 포함한 입력 받기
    // // 1-1. 일반적인 방법
    while(cin >> N){
    	cout << N;
    }

    // 1-2. getline 사용하는 방법
    // getline 사용 시에 개행 문자가 버퍼에 남으므로 cin.ignore()로 지워줘야함
    while(getline(cin, str)){
        cout << str;
    }
    
    // 1-3. cin.eof() 사용하는 방법
    while(!cin.eof()){
        cin >> str;
        cout << str;
    }

📘 소수점 포맷팅

   // 2. 출력시에 소수점 포맷팅

    double n = 12.6374;
    cout<<fixed;
    cout.precision(0); // 일의 자리까지 반올림해서 출력
    cout << n << '\n'; // 13
    cout.precision(1); // 소수점 첫 자리까지 반올림해서 출력
    cout << n << '\n'; // 12.6
    cout.precision(2); // 소수점 둘째 자리까지 반올림해서 출력
    cout << n << '\n'; // 12.64
  • 버림은 cmath 헤더의 floor를 사용하거나 자리수를 곱하고 형변환한 뒤에 나눠주면 된다.

📒 문자열 수정

    // 3. 문자열 수정
    string ex = "abcd123 hello !@#$ abcd 1234";
    // 3-1. 특정 인덱스를 치환
    // str.replace(n, k, str2)
    // 인덱스 n부터 k개를 str2로 치환
    // 리턴 없이 str을 수정함
    cout << ex.replace(14, 4, "cpp") << '\n'; // abcd123 hello cpp abcd 1234
    
    // 3-2. 특정 인덱스 삭제
    cout << ex.replace(8, 6, "") << '\n'; // abcd123 cpp abcd 1234
    cout << ex.erase(7,1) << '\n';        // abcd123cpp abcd 1234
    // 인덱스 대신 iterator 사용해도된다. iterator도 오버로딩되어 있음.
    cout << ex.erase(7) << '\n';          // abcd123 //갯수 안 쓰면 끝까지 삭제

    // 3-3. 문자의 대소문자 변환
    string ex2 = "abAB123!@#$";
    // 아스키 값 리턴
    cout << ex2[0] << " -> " << (char)toupper(ex[0]) << '\n'; // a -> A
    cout << ex2[2] << " -> " << (char)tolower(ex[2]) << '\n'; // A -> c
    cout << ex2[10] << " -> " << (char)toupper(ex[11]) << '\n'; // $ -> A
    // 알파벳 아닌 경우엔 l, L 리턴

    string ex3 = "int";
    // 3-4. 문자열 삽입
    // str.insert(n, str2) n번째 앞에 str2 삽입
    cout << ex3.insert(2, "ser") << '\n'; // insert

📕 문자 판별

int main() {
   // 4. 문자 판별
    // cctype 헤더... 라고는 하는데 사실 선언 안해도 돌아간다..
    string ex4 = "aA12 ";
    cout << ex4[0] << " is a digit : " << isdigit(ex4[0]) << '\n'; // a is a digit : 0
    cout << ex4[0] << " is a alpha : " << isalpha(ex4[0]) << '\n'; // a is a digit : 0

    cout << ex4[2] << " is a digit : " << isdigit(ex4[2]) << '\n'; // a is a digit : 0
    cout << ex4[2] << " is a alpha : " << isalpha(ex4[2]) << '\n'; // 1 is a alpha : 0

    cout << ex4[1] << " is a upper : " << isupper(ex4[1]) << '\n'; // A is a upper : 1
    cout << ex4[1] << " is a lower : " << islower(ex4[1]) << '\n'; // A is a lower : 0
    cout << ex4[4] << " is a space : " << isspace(ex4[4]) << '\n'; //   is a space : 1
}

📓 문자열 탐색, 추출

    // 5. 문자열 탐색, 추출
    string ex5 = "hello string";

    // 5-1. 부분문자열 추출
    // str.substr(pos, count = npos)
    // 참고로 substr은 매우 느리다
    cout << ex5.substr(0, 5) << '\n';
    cout << ex5.substr(0) << '\n';
    cout << ex5.substr(0, string::npos) << '\n';

    // 5-2. 부분문자열 탐색
    string ex5_2 = "hello cpp world cpp";
    // 인덱스 반환, 없으면 string::npos 리턴
    // find(substr, n) n부터 substr의 인덱스
    cout << ex5_2.find("cpp") << '\n';
    cout << ex5_2.find("cpp", 7) << '\n';
    cout << (ex5_2.find("java") == string::npos) << '\n';
    cout << ex5_2.find_first_of("cpp") << '\n'; // 문자들이 처음 등장하는 시작 인덱스
    cout << ex5_2.find_first_not_of("cpp") << '\n'; // 문자들이 아닌 첫 인덱스
    cout << ex5_2.find_last_of("cpp") << '\n'; // 문자들 중 마지막 등장하는 마지막 인덱스
    cout << ex5_2.find_last_not_of("cpp") << '\n'; // 문자들 아닌 마지막 인덱스

    // 5-3. 특정문자열 갯수 카운트
    string ex5_3 = "hello java and spring boot";

    regex re("a"); // 타겟 문자열
    auto end = sregex_iterator();
    auto iter = sregex_iterator(ex5_3.begin(), ex5_3.end(), re);

    cout << "\'a\' count : " << distance(iter, end) << '\n';

🪚 split 함수 구현

// 6. split 함수 구현
// str : 타겟문자열, char : 구분자
vector<string> split(string str, char delimiter){
    istringstream iss(str); // 문자열 스트림
    string buffer; // 문자열 버퍼

    vector<string> result; // 결과 문자열들을 담을 벡터

    while(getline(iss, buffer, delimiter)){
        result.push_back(buffer);
    }

    return result;
}

🛁 trim 함수 구현

// 7. trim 함수 구현
// 7-1. string 함수로 구현
// 전부 제거
string trim(string str){
    while (str.find(' ') != string::npos) str.erase(str.find(' '),1);

    return str;
}

// 7-2. 앞 뒤 제거
// 공백 말고도 가능
string trim2(string str){
    str.erase(0, str.find_first_not_of(' '));
    str.erase(str.find_last_not_of(' ') + 1);

    return str;
}

// 7-3. regex로 구현
string ltrim(string str){
    return regex_replace(str, regex("^\\s+"), "");
}

string rtrim(string &str){
    return regex_replace(str, regex("\\s+$"), "");
}

string trim_regex(string &str){
    return ltrim(rtrim(str));
}

📚 마치며

정규식을 습관화하자.

profile
DB는 두부

0개의 댓글