TIL

[C++] 코딩 테스트 오답 노트 & 코드 개선 (가운데 글자 / 수박수박수)

think95592 2026. 5. 19. 20:36

1. 가운데 글자 가져오기

💡 핵심 아이디어 및 접근법

문자열의 길이(s.size())를 이용해 가운데 글자를 뽑아낼 때는 인덱스가 0부터 시작한다는 점을 유의해야 합니다. 홀수와 짝수일 때의 처리가 조금씩 달라집니다.

  • 홀수 (예: "abcde", 길이 5): 5 / 2 = 2가 됩니다. 인덱스 2는 세 번째 글자인 'c'를 정확히 가리키므로 그대로 사용하면 됩니다.
  • 짝수 (예: "qwer", 길이 4): 4 / 2 = 2가 되어 인덱스 2인 'e'를 가리키게 됩니다. 하지만 짝수일 때는 가운데 두 글자('w', 'e')를 가져와야 하므로, 시작점을 (길이 / 2) - 1로 잡아 앞 글자부터 챙겨야 합니다.

❌ 기존 코드

C++
 
#include <string>
#include <vector>

using namespace std;

string solution(string s) {
    string answer = "";
    if(s.size() % 2 == 0)
    {
        answer.push_back(s[s.size()/2-1]);
        answer.push_back(s[s.size()/2]);
    }
    else
    {
        answer.push_back(s[s.size()/2]);
    }
    return answer;
}

생각해 볼 점:

s.size() / 2 연산이 여러 번 중복되어 사용되고 있습니다. 또한, 문자열을 하나씩 push_back으로 조립하는 것보다 C++ 표준 라이브러리의 문자열 자르기 기능을 활용하면 코드가 훨씬 간결해집니다.


개선 코드 (std::substr 활용)

반복되는 연산을 mid 변수에 저장하고, 원하는 길이만큼 문자열을 잘라내는 substr() 함수를 사용해 가독성을 높였습니다.

C++
 
#include <string>

using namespace std;

string solution(string s) {
    int mid = s.size() / 2;
    
    // 짝수면 mid-1부터 2글자, 홀수면 mid부터 1글자 자르기
    if (s.size() % 2 == 0) {
        return s.substr(mid - 1, 2);
    } else {
        return s.substr(mid, 1);
    }
}

2. 수박수박수박수박수박수?

❌ 기존 코드와 문제점 분석

C++
 
#include <string>
#include <vector>

using namespace std;

string solution(int n) {
    string answer = "";
    while(int i = 0 <= n) // 1번 문제 발생
    {
        if(i%2 == 0)
        {
            answer.insert(i,"수"); // 3번 문제 발생
        }
        else
        {
            answer.insert(i,"박"); // 3번 문제 발생
        }
        ++i;
    }
    return answer;
}

① while(int i = 0 <= n)의 조건문 오류

  • 원인: while문 조건식 안에서 변수를 선언하면서 비교 연산자(<=)를 섞어 쓰면, 연산자 우선순위와 선언 규칙 때문에 의도치 않은 방식으로 동작합니다. 매번 i가 초기화되거나 엉뚱한 값과 비교되어 무한 루프에 빠지게 됩니다.
  • 해결: 반복문에서 쓸 루프 변수 int i = 0;은 while문 바깥에 깔끔하게 선언해야 합니다.

② i <= n 조건식으로 인한 반복 횟수 초과

  • 원인: 인덱스를 0부터 시작하면서 조건식을 <= n으로 잡으면, 실제로는 n + 1번 실행됩니다. (예: n=3일 때 0, 1, 2, 3 총 4번 반복)
  • 해결: 정확히 n번만 채우려면 미만(<) 조건인 i < n을 사용해야 합니다.

③ insert() 사용 시 한글 깨짐 현상

  • 원인: C++의 std::string::insert()는 글자 수가 아니라 '바이트(Byte)' 단위로 데이터를 끼워 넣습니다. UTF-8 환경에서 한글은 한 글자당 3바이트를 차지하는데, 인덱스 i를 기준으로 중간에 강제로 밀어 넣으려고 하면 멀쩡한 한글 바이트 조합이 깨져서 기괴한 글자가 출력됩니다.
  • 해결: 문자열의 맨 뒤에 안전하게 한글을 이어 붙이는 += 연산자를 사용하는 것이 가장 안전하고 빠릅니다.

개선 코드

오류 원인들을 모두 수정하고, 가독성을 높인 완성형 코드입니다.

C++
 
#include <string>

using namespace std;

string solution(int n) {
    string answer = "";
    int i = 0; // 1. 변수 선언은 while문 바깥에서 안전하게!
    
    while(i < n) // 2. 정확히 n번만 반복하도록 '<' 사용
    {
        if(i % 2 == 0)
        {
            answer += "수"; // 3. insert 대신 += 사용으로 한글 깨짐 방지
        }
        else
        {
            answer += "박";
        }
        ++i;
    }
    return answer;
}

📝 오늘의 요약 (Takeaway)

  1. 문자열의 인덱스를 계산할 때는 홀수/짝수 케이스를 나누어 시뮬레이션해 보면 실수를 줄일 수 있다.
  2. C++ standard library에서 문자열의 일부분만 추출할 때는 substr(시작인덱스, 자를길이)가 아주 유용하다.
  3. 멀티바이트 문자열(한글 등)을 다룰 때 insert나 인덱스 기반 수정은 바이트가 찢어져 글자가 깨질 위험이 크므로, 맨 뒤에 붙이는 += 연산자를 적극 활용하자!