[알고리즘] 백준 10828

은개·2025년 9월 1일

[CS] 알고리즘

목록 보기
17/21

백준 10828 - 스택

에러

#include <string>
#include <iostream>
#include <vector>
#include <algorithm>
#include <stack>
#include <sstream>

using namespace std;

void solution(int n) {
    string _push = "push";
    string _pop = "pop";
    string _empty = "empty";
    string _size = "size";
    string _top = "top";

    stack<int> stk;

    for (int i = 0; i < n; i++) {
        string cmd;

        cin.clear();
        getline(cin, cmd);

        if (cmd == _pop && !stk.empty()) {
            cout << stk.top() << "\n";
            stk.pop();
        }
        else if (cmd == _empty) {
            if (stk.empty()) {
                cout << "1" << "\n";
            } else {
                cout << "0" << "\n";
            }
        }
        else if (cmd == _size) {
            cout << stk.size() << "\n";
        }
        else if (cmd == _top && !stk.empty()) {
            cout << stk.top() << "\n";
        }
        else {
            string s_num;
            stringstream _cmd(cmd);
            _cmd >> cmd >> s_num;

            cout << s_num << "!";

            int num = stoi(s_num);

            stk.push(num);
        }
    }


}

int main() {
    int n;
    cin >> n;

    solution(n);
    
    return 0;
}

⚠️ 에러
libc++abi: terminating due to uncaught exception of type std::invalid_argument: stoi: no conversion ![1] 29681 abort

💥 원인

  • cin은 입력 버퍼에 개행문자(\n)를 남겨둠
  • cin.clear()은 버퍼의 내용을 지우는 게 아니라, 스트림의 에러 플래그만 초기화함
  • 즉, 입력 버퍼에 \n이 남아있어서 getline()이 실행되지 않고 바로 else문으로 넘어감
  • 숫자가 아닌 문자열이 stoi()에 전달되어 에러 발생

오답

#include <string>
#include <iostream>
#include <vector>
#include <algorithm>
#include <stack>
#include <sstream>

using namespace std;

void solution(int n) {
    string _push = "push";
    string _pop = "pop";
    string _empty = "empty";
    string _size = "size";
    string _top = "top";

    stack<int> stk;

    for (int i = 0; i < n; i++) {
        string cmd, s_num;

        cin.ignore();
        getline(cin, cmd);

        cout << cmd << endl;

        if (cmd == _pop && !stk.empty()) {
            cout << stk.top() << "\n";
            stk.pop();
        }
        else if (cmd == _empty) {
            if (stk.empty()) {
                cout << "1" << "\n";
            } else {
                cout << "0" << "\n";
            }
        }
        else if (cmd == _size) {
            cout << stk.size() << "\n";
        }
        else if (cmd == _top && !stk.empty()) {
            cout << stk.top() << "\n";
        }
        else {
            stringstream _cmd(cmd);
            _cmd >> cmd >> s_num;
            
            if (cmd == _push) {
                int num = stoi(s_num);
                
                stk.push(num);
            }
        }
    }
}

int main() {
    int n;
    cin >> n;

    solution(n);
    
    return 0;
}

🤔 시도

else {
	stringstream _cmd(cmd);
    _cmd >> cmd >> s_num;
           
	if (cmd == _push) {
		int num = stoi(s_num);
               
		stk.push(num);
	}
}
  • else문 안에서 다시 cmd == _push 확인
  • cin.clear() 대신 cin.ignore() 사용하여 버퍼 초기화
  • 근데 처음 명령어 받은 이후로 한 글자씩 잘림

💥 원인

  • cin.ignore()은 첫 번째 문자 하나만 버퍼에서 지우고 나머지는 남겨둠
  • 버퍼가 비어있는 경우 사용자의 입력을 기다림 -> 입력 받으면 첫 번째 글자는 지우고 나머지 문자열을 버퍼에 남겨둠
  • cin 입력 → cin.ignore() → '\n' 제거 → getline() → 버퍼 비어있음 → cin.ignore() → getline() 시 입력에서 첫 번째 글자 제거

정답 (8ms)

#include <string>
#include <iostream>
#include <vector>
#include <algorithm>
#include <stack>
#include <sstream>

using namespace std;

void solution() {
    string _push = "push";
    string _pop = "pop";
    string _empty = "empty";
    string _size = "size";
    string _top = "top";

    stack<int> stk;
    vector<string> cmds;

    string n;
    getline(cin, n);
    
    for (int i = 0; i < stoi(n); i++) {
        string cmd;
        getline(cin, cmd);
        cmds.push_back(cmd);
    }

    for (auto cmd : cmds) {
        if (cmd == _pop) {
            if (stk.empty()) {
                cout << "-1" << "\n";
            } else {
                cout << stk.top() << "\n";
                stk.pop();
            }   
        }
        else if (cmd == _empty) {
            if (stk.empty()) {
                cout << "1" << "\n";
            } else {
                cout << "0" << "\n";
            }
        }
        else if (cmd == _size) {
            cout << stk.size() << "\n";
        }
        else if (cmd == _top) {
            if (stk.empty()) {
                cout << "-1" << "\n";
            } else {
                cout << stk.top() << "\n";
            }
        }
        else {
            string s_num;
            stringstream _cmd(cmd);
            _cmd >> cmd >> s_num;
            
            if (cmd == _push) {
                int num = stoi(s_num);
                
                stk.push(num);
            }
        }
    }
}

int main() {
    solution();
    
    return 0;
}

💭 해결

  • cin이랑 getline이랑 같이 쓰면 입력을 정확히 못 받아서 그냥 getline만 씀
    (일단은,,,,,,,,)
  • stack이 empty일 때 예외처리 수정

정답 (208ms)

#include <string>
#include <iostream>
#include <vector>
#include <algorithm>
#include <stack>
#include <sstream>

using namespace std;

void solution(int n) {
    string _push = "push";
    string _pop = "pop";
    string _empty = "empty";
    string _size = "size";
    string _top = "top";

    stack<int> stk;

    for (int i = 0; i < n; i++) {
        string cmd, s_num;

        getline(cin, cmd);

        cout << cmd << endl;

        if (cmd == _pop) {
            if (stk.empty()) {
                cout << "-1\n";
            }
            cout << stk.top() << "\n";
            stk.pop();
        }
        else if (cmd == _empty) {
            if (stk.empty()) {
                cout << "1" << "\n";
            } else {
                cout << "0" << "\n";
            }
        }
        else if (cmd == _size) {
            cout << stk.size() << "\n";
        }
        else if (cmd == _top) {
            if (stk.empty()) {
                cout << "-1\n";
            }

            cout << stk.top() << "\n";
        }
        else {
            stringstream _cmd(cmd);
            _cmd >> cmd >> s_num;
            
            if (cmd == _push) {
                int num = stoi(s_num);
                
                stk.push(num);
            }
        }
    }
}

int main() {
    int n;
    cin >> n;
    cin.ignore();

    solution(n);
    
    return 0;
}

💭 해결

  • cin.ignore()은 cin 이후 한 번만 실행

💡 cin과 getline 차이

cin

  • 공백, 탭, 개행문자를 구분자로 사용
  • "hello world" 입력 시 "hello"만 읽음
  • 개행문자를 버퍼에 남김

getline(cin, str):

  • 개행문자(\n)까지 한 줄 전체를 읽음
  • "hello world" 입력 시 "hello world"
    전체를 읽음
  • 개행문자까지 모두 소비 (버퍼에서 제거)

0개의 댓글