[문제 풀이]
괄호 검사랑 비슷하기 때문에 stack으로 문제를 풀 수 있을 거라 생각했다. 조금 더 쉽게 풀기 위해서 tag에는 들어가는 것이 한정적임으로 struct으로 자료구조를 만들면 될거라고 생각했다. tag에는 문자열, backslash, attribute가 들어가고 back slash가 문자열 뒤에 나오면 close tag가 필요 없게 됨으로 관련해서 4개의 element를 가진 struct을 만들었다.
주어진 문자열 한 character씩 검사해서 <가 나오면 struct을 만들어서 > 가나올 때까지 element를 채웠다. 그 후는 괄호 검사 할 때의 stack처리를 하였다.
[코드]
#include <iostream>
#include <string>
#include <stack>
using namespace std;
struct mark_up {
string tag; //tag 안에 들어가는 문자
bool slash = false; //back slash가 존재하는지
bool attribute = false; //attribute가 존재하는지
bool close_need = true; //close tag가 필요한지
void clear() {
//초기화 해주는 코드
this->tag = "";
this->slash = false;
this->attribute = false;
this->close_need = true;
}
};
bool check_txt(char ch) {
//character인지 확인해주는 함수
if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) return true;
return false;
}
string check_legality(string line) {
stack<mark_up> st;
string answer = "legal";
bool flag_branket = false; //true이면 <>안에 있는 것을 확인하는 중
mark_up mark;
for (int i = 0; i < line.size(); i++) {
if (line[i] == '<') {
mark.clear();
flag_branket = true; // <일 때 true로 바꿔주는 것
}
else if (flag_branket) {
if (check_txt(line[i]) && !mark.attribute) {
//attribute안에 있는 문자가 아닐 때
mark.tag.push_back(line[i]);
}
else if (line[i] == '/' && !mark.attribute) {
// back slash가 나왔고 이것이 attribute에서 나온 것이 아닐 때
if (mark.tag == "") mark.slash = true; //close tag임
else mark.close_need = false; //close tag가 필요 없는 tag임
}
else if (line[i] == ' ') {
//다음 문자가 /가 아님으로 다음 문자부터는 attribute임
if(i+1 <line.size() && line[i+1] != '/') mark.attribute = true;
}
else if (line[i] == '>') {
flag_branket = false; // >일 때 다음 문자 부터는 <>안에 있는 것이 아님으로 false로 바꿔줌
if (mark.close_need && !mark.slash) st.push(mark); //close tag가 필요함으로 stack에 넣음
else if (mark.slash && !st.empty()) {
//close tag임으로 stack top에 있는 것이랑 문자가 일치하지 않으면 illegal
mark_up inspected_st = st.top();
if (inspected_st.tag != mark.tag) return "illegal";
else st.pop();
}
else if (mark.slash && st.empty()) return "illegal"; //close tag이나 상응하는 tag가 없으면 illegal
}
}
}
if (st.empty()) return answer;
else return "illegal";
}
int main() {
string line;
while (getline(cin, line)) {
if (line == "#") break;
string answer = check_legality(line);
cout << answer << "\n";
}
}
[총평]
이렇게 line 하나하나 검사하는 것 말고도 c++ string 라이브러리 함수를 사용해서 하는 것이 있을 것이다. 그것을 잘 사용해 봐야 겠다.
https://sooooooyn.tistory.com/26