저번에 풀었던 단어 뒤집기와 유사한 문제다. 그러나 괄호에 있는 문자는 tag로 지정해 뒤집기를 하지 않는다는 점에서 복잡해졌다.
처음에는 tag에 있는 단어만을 떼서 출력해주고 그 나머지를 stack에 넣는 방식을 사용했다. 그러나 이 방식은 너무 복잡해서 풀기가 어려웠다. 다른 사람의 풀이를 찾아봤는데, tag일 경우 bool형식을 true로 두는 방식이 굉장히 간편해 보였다. 즉, tag가 시작할 때 stack에 있는 문자를 모두 빼주고(처음 풀이에서는 이 부분에서 어려움을 겪었다) b를 true로 돌려준다. 만일 tag가 끝이 났다면 b를 false로 만든다. b가 true일 때만 s[i]를 그냥 출력해 주는데 이렇게 하면 따로 while을 안 써도 되서 편리하다.
그리고 띄어쓰기와 '\n'(문장이 끝에 '\n'을 붙여줘서 끝을 표시했다)일 때는 stack을 돌리고 단어가 끝나는 경우 띄어쓰기를 출력해준다.
만일 위의 경우에 다 해당하지 않는 단어이면 stack에 push해준다.
주석참고
#include<iostream>
#include<string>
#include<stack>
using namespace std;
int main() {
string s = "";
stack<char> st;
/*b가 true라면 tag라는 뜻이다.*/
bool b = false;
getline(cin, s);
/*문장이 끝났음을 암시. 만일 없을 경우 마지막 단어를 무시할 수 있다.*/
s += '\n';
/*총 세 가지로 생각한다.
1. tag바로 옆에 붙어 있는 단어
2. tag안에 있는 단어
3. 띄어쓰기가 존재하는 단어*/
for (int i = 0; i < s.length(); i++) {
/*1. tag바로 옆에 붙어있는 단어
만일 s[i]가 <이라면 tag가 시작된다는 뜻이니 tag바로 앞에 있는 단어를 출력해야 한다.
그리고 tag가 시작되었음을 알리는 b를 true로 돌려준다.*/
if (s[i] == '<') {
while (!st.empty()) {
cout << st.top();
st.pop();
}
cout << "<";
b = true;
}
/*tag가 끝났으니 b를 false를 돌려준다.*/
else if (s[i] == '>') {
cout << ">";
b = false;
}
/*만일 tag가 진행중이라면(b가 true라면) s[i]를 그냥 출력한다.*/
else if (b) {
cout << s[i];
}
/*만일 tag가 시작되는 문자에 붙어있는 단어가 아니고 띄어쓰기로 이루어진 단어 혹은 단어가 끝이 났다면 stack에 있는 단어들을 출력한다.
그리고 st가 비었다면 이는 단어가 끝이 났다는 의미니까 띄어쓰기를 출력한다.*/
else if (s[i] == ' ' || s[i] == '\n') {
while (!st.empty()) {
cout << st.top();
st.pop();
}
cout << ' ';
}
/*만일 '<'나 ' '에 붙어있지 않다면 그냥 stack에 넣어준다.*/
else {
st.push(s[i]);
}
}
}