티스토리 뷰
>문제
> 핵심
문자열 입력
스택
>풀이과정
괄호 비교!
자료구조 수업에서 스택을 배워본 사람이라면 한번쯤 만들어본 코드일 것이다.
나도 그럴 줄 알고 쉽게 만들 수 있을 줄 알았는데 스택도 오랜만에 하다보니 가물가물해서 쪼끔 시간이 걸렸다.
이 문제를 통해서 문자열 입력에 대해 다시 공부할 수 있었다.
>>문자열 입력 함수
· scanf("%s", ar)
scanf의 %s는 개행문자(\n), 공백문자, 탭 문자 직전까지를 하나의 문자열로 인식한다.
그래서 scanf를 이용해 "Hello World"를 입력한다면, 출력할때 "Hello"까지밖에 나오지를 않는다.
그리고, 이 scanf가 개행문자 직전까지만 문자열로 입력을 받으므로,
내가 입력했던 엔터('\n')이 버퍼에 덩그러니 남게된다.
그래서!! scanf로 문자열을 입력받고 연속해서 scanf로 정수값을 입력받으려고 하게된다면
사용자로부터 입력을 받지않고 버퍼에 남아있는 개행문자 \n을 던져줘서 그냥 넘어가버리는 상황이 생기는것..
그래서 입력을 받기전에 버퍼를 비워주는 것이 정신건강에 좋다. 이거 몰라서 1학년때 고생좀 했지..
· scanf(" %s", ar); >> %s 앞에 한칸 비우기, 앞에 공백이 있으면 \n을 white space 취급해 넘긴다고 한다..(?)
· getchar(); 추가하기
scanf는 그냥 정수, 실수형이나 짧은 단어 입력 용도로만 사용하자. 긴 문자열 입력에는 부적합.
· gets(char *s)
scanf가 공백문자가 나오면 문자열 입력을 끊어버리니 하나의 긴 문장을 통으로 입력받을 수가 없다.
그래서 나온게 gets 함수. 개행문자('\n') 직전까지 입력된 모든 문자를 저장한다.
그 후에 개행문자 '\n'을 떼고 '\0'을 붙여서 문장의 끝을 표시한다.
근데 이 함수는 보안상의 문제로 표준함수에서 제외되었다고 한다.
버퍼의 크기가 정해져있지 않아서 에러를 뿜어낼 수가 있다고 한다.
VS에서만 돌아가며 백준에서 gets 함수를 사용하면 컴파일 에러를 내더라..
아무튼 그래서 사용해야 하는 것이 fgets 함수이다.
· fgets(char* str, int num, FILE* stream);
· str : 읽어들인 문자열을 저장할 배열, 배열에 입력받는 경우 sizeof(text) / 포인터로 입력받는 경우 크기 직접 입력!
· num : 읽어들일 최대 문자 수(개행문자 '\n', 마지막 '\0' 포함)
· stream : 표준입출력 받기 위해 stdin 사용
쪼끔 어려운데 일반적으로 이걸 사용한다고 한다.
나도 앞으로 문자열 입력받을땐 이걸 사용하는 습관을 들여야겠다.
그리고 fgets 함수를 사용할때 유의할 점.
내가 5글자 APPLE 문자열을 fgets 함수로 입력한다 하자.
그렇다면 나는 APPLE+엔터(\n) 을 입력할 것이고, fgets 는 이를 통째로 받아서 "APPLE\n\0" 이렇게 저장을 하게된다.
따라서 개행문자(\n) + 문자열의 끝(EOF, \0) 두자리를 추가로 마련해줘야 정상적으로 값을 다 받아올 수 있다.
나머지 괄호 맞추는 알고리즘은 간단하다
1. 문자열을 하나씩 반복문 돌면서 '(' 나 '[' 가 입력되면 스택에 push
2. ')' 가 입력되면 스택에서 pop. 이때 pop된 값이 반드시 '(' 여야 짝이 맞음. 안맞으면 chk = 0 하고 break.
3. ']' 에 대해서 짝 '['가 맞는지 위와 동일한 과정
4. 문자열을 모두 돌았을때, 스택에 값이 남아있다 -> 짝이 안맞는다 -> chk = 0
5. chk = 0이면 no, chk = 1이면 yes 출력
6. 스택, chk =1 초기화 후 1부터 반복!
>깨달은점
긴 문장을 받을때는 gets 보다는 fgets를 쓰는 습관을 들여보자
스택을 잘 이해하자
>코드
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#define SIZE 102
typedef struct
{
char stack[SIZE];
int n;
}StackType;
void init_stack(StackType* s)
{
s->n = -1;
}
int is_full(StackType* s)
{
return s->n == SIZE - 1;
}
int is_empty(StackType* s)
{
return s->n == -1;
}
void push(StackType* s, char e)
{
if (is_full(s))
return;
s->stack[++s->n] = e;
}
char pop(StackType* s)
{
if (is_empty(s))
return '!';
char tmp = s->stack[s->n--];
return tmp;
}
int main()
{
StackType s;
init_stack(&s);
int i, chk = 1;
char text[SIZE], e;
while (1)
{
fgets(text, SIZE, stdin);
if (strcmp(text, ".\n") == 0)
break;
for (i = 0; i < strlen(text); i++)
{
if (text[i] == '(' || text[i] == '[')
push(&s, text[i]);
else if (text[i] == ')')
{
e = pop(&s);
if (e != '(')
{
chk = 0;
break;
}
}
else if (text[i] == ']')
{
e = pop(&s);
if (e != '[')
{
chk = 0;
break;
}
}
}
if (!is_empty(&s))
chk = 0;
if (chk == 0)
printf("no\n");
else
printf("yes\n");
s.n = -1;
chk = 1;
}
return 0;
}
'알고리즘 > 기타' 카테고리의 다른 글
[C] 백준 | 10773번 코드 - 제로 (0) | 2021.02.28 |
---|---|
[C] 백준 | 9012번 코드 - 괄호 (0) | 2021.02.28 |
[C] 백준 | 2164번 코드 - 카드2 (0) | 2021.02.27 |
[C] 백준 | 2108번 코드 - *통계학 (1) | 2021.02.26 |
[C] 백준 | 1978번 코드 - 소수찾기 (0) | 2021.02.24 |