나 개발자 진짜 되냐?

바킹독 0x04 문제2 - / 백준 5397번 키로거 본문

C++을 시작해봐요!/알고리즘을 공부해봐요!

바킹독 0x04 문제2 - / 백준 5397번 키로거

Snow Rabbit 2025. 10. 1. 23:56

 

연결리스트는 참 어렵다.

뭔가 쉬운 거 같은데.. 아니 이론적? 으로는 쉬운 느낌인데 어떻게 머릿속에 떠올려야 할지 잘 모르겠다.

키보드 느낌처럼 하면 된다는데..

머리속에 구상이 잘 안 된다.

강의를 한번 더 듣고 키로거를 풀어보기로 했다.

앞에 풀었던..

에디터는 그대로 잊었다

아니 에디터부터 다시 풀어야 하나?!!?!?

ㅋㅋㅋㅋ

정말 쉽지 않다.

 

그래서 강의를 다시 듣기로 했다...ㅎㅋ

문제는 3개여서 그냥 넘길까 했는데 그래도 알아야 할 거 같아서..

그리고 그 앞에 에디터 진짜 하나도 기억 안 난다.....


STL list

list <int> L = { 1, 2 };

list <int>::iterator t = L.begin();

= auto t = L.begin();

>>>>>> t는 1을 가리키고 있움

L.push_front(10);

>>>>> 10, 1, 2

cout << *t

>>>>>> t는 1을 출력, t에 *을 붙여야 안에 값을 줌

L.push_back(5);

>>>>>> 10, 1, 2, 5

L.insert(t, 6);

>>>>>> t가 가리키는 곳 에 6을 넣움

10, 6, 1, 2, 5

t++;

>>>>>> t를 한 칸 앞으로! 2를 가리키고 있움

t = L.erase(t);

>>>>>> t가 가리키는 값을 제거함

그다음 원소인 5를 반환하게 됨,  즉 t는 5가 됨

 erase  제거 한 다음 원소를 반환

 

for(auto i : L) cout << i << ' ' ;

>>>>>> 하나씩 값 출력

 

그럴 일은 없겠지만.. 만약에 auto를 못쓴다면 for(for(

list <int>::iterator it = L.begin(); it!= L.end(); it++)

cout << *it << ' ';

 

출력은 주소값이 아니라 주소 안에 값이기 때문에 * 해줘야 한다.

 

오케이 나 익혔다? 문제 본다?!


 

 

...

한 20분 고민해 봤는데 감이 안 잡혀서

그냥 지피티에게 힌트를 물어봤다.

 

일단 스켈리톤코드를 짜줬는데

while문으로 시작하고,

string으로 입력받아서 

> 왼쪽일 때

< 오른쪽일 때를 구분해 주자는 거 같았다.

 

맞게 구현해 보겠다.

엉망진창 코드..

 

어? 분명 이상한 코드라고 생각했는데..

생각보다 심각한? 정도는 아니었다.

 

앞에는 좀 맞았는데..

여기가 문제였다.

결국 여기도 지울 때 맨 앞이어서 앞조건을 만들어줘야 한다.

그리고 새로 만들어주고는 ++해줄 필요가 없다.

 

erase는 다음 위치를 반환하기 때문에 결과적으로 문제가 없다.

하지만 반대로 insert는 그 위치를 반환하기 때문에 그 다음칸으로 이동시켜줘야 한다.

 

오늘 문제에서 내가 놓친 부분

 

1. string s 선언 위치

for문 안에다가 만들어주는 것이 중요하다.

그래야 한 줄씩 받아서 사용이 가능하다.
그 다음칸 받고 받고 가 가능하게 된다.

while문으로 할 거면

while(n--) 해서 해주면 되고,

 

마찬가지로 string은 while 안에 해줘야 한다.

 

2. 예외 처리

cur의 경우 시작은 begin인데

만약에 시작부터 < 이게 나온다면

위치가 0보다 뒤로 가기 때문에..

조건을 걸어서 맨 앞이 아닐 경우에만 빼기를 해주도록 한다.

 

반대로 > 이건 맨 끝에서 더 가면 이상한 값으로 가기 때문에

조건을 걸어서 맨 뒤가 아닐 경우에만 더해주도록 한다.

 

제일 중요한 빼기인데, 커서의 위치가 중요하다.

커서의 경우

커서 오른쪽에 있는 값을 가리키는 iterator이다.

그래서!

cur = L.end(); 면 오른쪽에 문자가 없다.이고

cur = L.begin(); 면 왼쪽에 문자가 없다는 뜻이다.

 

근데 백스페이스의 경우

키보드를 봐도 커서기준 왼쪽을 지우기 때문에

빼기를 해준 다음에

왼쪽에 있던 게 그럼 커서 오른쪽으로 갔을 거고

erase 해주면 된다.

 

12/34

지금 커서는 3을 가리킨다.

근데 식에서는 2가 지워져야 하는데,

erase는 오른쪽을 지워서.. 그대로 지우면 3을 지우게 된다.

그래서 cur--해서

1/234로 당겨주고

erase(cur) 해주면

커서의 오른쪽인 2가 지워지고 다시 3을 가리키게 된다.

1/34

 

insert의 경우는 cur의 왼쪽에 삽입한다.

커서는 단어 오른쪽을 표시하고 있어서,

우리가 원하는 방향이기 때문에

특별히 따로 빼고 더하지 않고 그냥 쓰게 된다.

 

맨 앞에 갔을 때는 뺄 게 없다.

그래서 맨 앞을 제외해 주는 조건이 필요하다.

if (cur!= L.begin())

 

3. 마지막 값 출력

for문으로 출력하며,

L 전체를 출력하려면 하나씩 돌면서 출력해줘야 한다.

한 문단이 끝날 때 엔터해줘야 해서

맨 마지막에 cout << '\n'을 따로 해줘야 한다.

 

 

진짜 어렵다.

그리고 요즘 집중도 잘 안된다.

..

벌써 시월이다.

시원하다

예쁘고

벌써 25년도도 얼마 안 남았구나... 싶다