세계는 균형이 잘 잡혀있어야 한다. 양과 음, 빛과 어둠 그리고 왼쪽 괄호와 오른쪽 괄호처럼 말이다.
정민이의 임무는 어떤 문자열이 주어졌을 때, 괄호들의 균형이 잘 맞춰져 있는지 판단하는 프로그램을 짜는 것이다.
문자열에 포함되는 괄호는 소괄호("()") 와 대괄호("[]")로 2종류이고, 문자열이 균형을 이루는 조건은 아래와 같다.
모든 왼쪽 소괄호("(")는 오른쪽 소괄호(")")와만 짝을 이뤄야 한다.
모든 왼쪽 대괄호("[")는 오른쪽 대괄호("]")와만 짝을 이뤄야 한다.
모든 오른쪽 괄호들은 자신과 짝을 이룰 수 있는 왼쪽 괄호가 존재한다.
모든 괄호들의 짝은 1:1 매칭만 가능하다. 즉, 괄호 하나가 둘 이상의 괄호와 짝지어지지 않는다.
짝을 이루는 두 괄호가 있을 때, 그 사이에 있는 문자열도 균형이 잡혀야 한다.
정민이를 도와 문자열이 주어졌을 때 균형잡힌 문자열인지 아닌지를 판단해보자.
하나 또는 여러줄에 걸쳐서 문자열이 주어진다. 각 문자열은 영문 알파벳, 공백, 소괄호("( )") 대괄호("[ ]")등으로 이루어져 있으며, 길이는 100글자보다 작거나 같다. 각 줄은 마침표(".")로 끝난다.
입력의 종료조건으로 맨 마지막에 점 하나(".")가 들어온다.
각 줄마다 해당 문자열이 균형을 이루고 있으면 "yes"를, 아니면 "no"를 출력한다.
괄호를 push하고 pop하면서 양쪽의 괄호 개수가 맞는지 알아보는 프로그램이다. 아마 스택을 처음 배울 때, 처음 나오는 여러 예제 중 하나였던 것 같다.
처음 문제를 보고 코드를 짤 때, scanf 함수를 이용하여 문자열을 받고 stack도 2개를 이용했다. 하지만 scanf를 사용하니 무한루프에 빠지는 문제가 생겼고, stack도 2개가 필요할 것 같지는 않았다.
우선, scanf 대신 쓴 fgets에 대한 이해가 있어야 한다.
#include <stdio.h>
char * fgets (char *string, int n, FILE *stream);
fgets 함수의 원형은 이렇게 생겼다. 입력 stream에서 입력받은 정보를 크기 n의 문자열 string에 저장한다는 뜻이다. 이 함수를 쓸 때 주의할 사항이 하나 있다.
만약 입력이 abcdefg라고 해보자. 우리는 저 글자를 몽땅 cmd에 친 후 엔터를 누를 것이다. fgets는 그 엔터까지 문자열에 포함해서 abcdefg + \n + EOF까지를 저장받게 된다. 그러므로, 전체 문자열 크기에 2를 더해주어야 maximum 길이까지 입력받을 수 있을 것이다.
나머지 함수는 다음과 같이 구현했다:
- 전체 문자열을 입력받고, 문자열이 . 하나로 끝난다면 종료
 - 그렇지 않다면, 문자열 전체 길이를 구해 그만큼의 루프문을 돌림
 - 여는 괄호('(', '[')를 받았다면, stack에 push해 준다.
 - 만약 닫는 소괄호(')')를 받았다면, 변수 a에 pop한 문자를 저장한다.
 
4 - 1. 만약 그 문자가 여는 소괄호('(')가 아니면, num을 0으로 바꾼 뒤 반복문을 나간다.- 만약 닫는 대괄호(']')를 받았다면, 위 소괄호와 같이 판별한다.
 - 변수 top이 -1이 아니라면, 전체 stack이 비어있지 않다는 뜻이므로 이때도 num을 0으로 바꾼다.
 - num이 1이면 yes, num이 0이면 no를 출력한다.
 
#include <stdio.h>
#include <string.h>
char stack[102];
int top = -1;
void push(char);
char pop(char);
int main(void) {
	char sentence[102];
	char a; int num = 1;
	for (;;) {
		fgets(sentence, 102, stdin);
		sentence[strlen(sentence) - 1] = '\0';
		if (sentence[0] == '.' && sentence[1] != '.') {
			break;
		}
		int length = strlen(sentence);
		for (int i = 0; i < length; i++) {
			if (sentence[i] == '(' || sentence[i] == '[') {
				push(sentence[i]);
			}
			else if (sentence[i] == ')') {
				a = pop(sentence[i]);
				if (a != '(') {
					num = 0;
					break;
				}
			}
			else if (sentence[i] == ']') {
				a = pop(sentence[i]);
				if (a != '[') {
					num = 0;
					break;
				}
			}
		}
		if (top != -1) {
			num = 0;
		}
		if (num == 0) {
			printf("no\n");
		}
		else if (num == 1) {
			printf("yes\n");
		}
		top = -1; num = 1;
	}
	return 0;
}
void push(char a) {
	stack[++top] = a;
}
char pop(char a) {
	if (top == -1) {
		return '@';
	}
	return stack[top--];
}