안녕하세요! 오늘은 백준의 키로거 문제를 해결하면서 겪은 시행착오와 해결 과정을 공유하려고 합니다. 이 문제는 STL의 list
와 반복자(iterator
)를 활용하여 커서 이동 및 문자열 편집을 구현하는 문제로, 꽤나 흥미롭습니다.
키보드로 입력된 문자열에서 특수 키(<
, >
, -
)를 처리하여 최종 문자열을 출력해야 합니다.
<
: 커서를 왼쪽으로 이동 (커서가 가장 앞에 있으면 무시).>
: 커서를 오른쪽으로 이동 (커서가 가장 뒤에 있으면 무시).-
: 커서 왼쪽에 있는 문자를 삭제 (삭제할 문자가 없으면 무시).처음에는 한 줄씩 입력을 처리하기 위해 cin >> ch
로 문자를 하나씩 읽으며 구현했습니다.
while ((cin >> ch) && (ch != '\n')) {
if (ch == '<') cursor--;
else if (ch == '>') cursor++;
else if (ch == '-') L.erase(--cursor);
else L.insert(cursor, ch);
}
문제점:
1. erase
함수 호출 후 반복자를 재할당하지 않아 SIGSEGV
오류 발생.
2. 테스트 케이스가 분리되지 않고 출력이 한 줄에 이어지는 문제가 발생.
erase
문제 해결erase
호출 후 반환된 반복자를 cursor
에 재할당하여 문제를 해결했습니다.
cursor = L.erase(--cursor);
새로운 문제:
cin
을 사용하면 입력이 끝난 후에도 EOF 대기 문제가 발생.cin.ignore()
를 추가하여 버퍼 문제를 해결하고, cin.get()
로 입력을 받도록 수정했습니다.
cin.ignore(); // 첫 줄바꿈 제거
while (cin.get(ch)) {
if (ch == '<') cursor--;
else if (ch == '>') cursor++;
else if (ch == '-') cursor = L.erase(--cursor);
else L.insert(cursor, ch);
}
문제점:
cin.get(ch)
는 EOF까지 입력을 계속 대기하기 때문에 여러 테스트 케이스에서 문제가 발생했습니다.getline
으로 한 줄 입력 처리결국, 입력을 한 줄 단위로 처리하기 위해 getline
을 사용했습니다. 이를 통해 EOF 문제와 테스트 케이스 구분 문제를 해결할 수 있었습니다.
#include <bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
int tc;
cin >> tc;
cin.ignore(); // 첫 줄바꿈 제거
for (int i = 0; i < tc; i++)
{
string input;
getline(cin, input); // 한 줄 입력 받기
list<char> L;
auto cursor = L.begin();
for (char ch : input)
{
if (ch == '<')
{
if (cursor != L.begin())
{
cursor--;
}
}
else if (ch == '>')
{
if (cursor != L.end())
{
cursor++;
}
}
else if (ch == '-')
{
if (cursor != L.begin())
{
cursor = L.erase(--cursor);
}
}
else
{
L.insert(cursor, ch);
}
}
for (auto s : L)
{
cout << s;
}
cout << '\n'; // 각 테스트 케이스 결과 출력 후 줄바꿈
}
return 0;
}
list
사용: 중간 삽입과 삭제가 빈번하므로 STL의 list
가 적합합니다.getline
으로 한 줄 입력 처리: 테스트 케이스를 줄 단위로 분리하여 입력 처리.erase
호출 후 반복자를 반드시 재할당해야 오류를 방지할 수 있습니다.이 문제를 해결하며 STL의 활용과 입력 처리의 중요성을 다시 한번 느꼈습니다. 특히, EOF 문제나 버퍼 문제처럼 사소해 보이는 부분이 전체 로직에 영향을 준다는 점을 깨달았습니다.
혹시 비슷한 문제를 풀거나 궁금한 점이 있다면 댓글로 남겨주세요! 😊
#백준 #C++ #STL #문제풀이 #알고리즘