#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include "stack.h"//自作ヘッダーファイル.
#define STACK_SIZE 100
#define NUM 256
#define DONE 257
static int token(int *val);
static void error_recover(stack_t *stack, char *msg);
int main ( void ){
stack_t *stack;
int tok;
int val, x, y;
//スタックを作成する.
if( (stack = create_stack(STACK_SIZE)) == NULL ){
fprintf(stderr, "failed to create stack.\n");
exit(EXIT_FAILURE);
}
printf("> ");
for(;;){
if((tok = token(&val)) == DONE){
break;
}
switch(tok){
case NUM:
push(stack, val);
break;
case '+':
y = pop(stack); x = pop(stack);
push(stack, x + y);
break;
case '-':
y = pop(stack); x = pop(stack);
push(stack, x - y);
break;
case '*':
y = pop(stack); x = pop(stack);
push(stack, x * y);
break;
case '/':
y = pop(stack); x = pop(stack);
if(y == 0){
error_recover(stack, "divide by zero");
continue;
}
push(stack, x / y);
break;
case '\n':
if(sp_read(stack) == 1){
printf("%d\n", pop(stack));
printf("> ");
break;
}
ungetc(tok, stdin);//ここです。
default: //不正なトークンを検出.
error_recover(stack, "invalid input");
printf("> ");
break;
}
}
free(stack);
return EXIT_SUCCESS;
}
stack_t *create_stack(unsigned int sz){
stack_t *new_stack;
//スタックデータの確保.
new_stack = (stack_t*)malloc( sizeof(stack_t) + sizeof(int)*(sz - 1) );
if(new_stack == NULL){
return NULL;
}
new_stack->top = 0;
new_stack->size = sz;
return new_stack;
}
/*
push:
引数で指定したスタックstackに値numをプッシュする.
*/
void push(stack_t *stack, int num){
//スタックが満杯の場合はメッセージを出力して終了する.
if(is_full(stack)){
fprintf(stderr, "stack overflow.\nss");
exit(EXIT_FAILURE);
}
stack->data[stack->top++] = num;
}
/*
pop:
引数で指定したスタックstackから値をポップする.
*/
int pop(stack_t *stack){
//スタックが空の場合はメッセージを出力して終了する.
if(is_empty(stack)){
fprintf(stderr, "stack underflow.\n");
exit(EXIT_FAILURE);
}
return stack->data[--stack->top];
}
//token: トークンを取得する.
static int token(int *val){
int ch;
while ((ch = getchar()) != EOF){
if(ch == ' ' || ch == '\t'){
continue;
}
else if(isdigit(ch)){
ungetc(ch, stdin);
scanf(" %d", val);
return NUM;
}
else{
return ch;
}
}
return DONE;
}
//error_recover: エラーからの回復処理.
static void error_recover(stack_t *stack, char *msg){
int ch;
fprintf(stderr, "ERROR: %s.\n", msg);
init_stack(stack);//init_stack(st) ((st)->top = 0)
while((ch = getchar()) != EOF){
if(ch == '\n') return;
}
exit(EXIT_FAILURE);
}
typedef struct stack{
int top; //スタックトップの位置.
int size; //データ部の大きさ.
int data[1]; //データ部.
} stack_t;
//スタックの状態を判定するマクロ.
#define is_empty(st) ((st)->top == 0)
#define is_full(st) ((st)->top == (st)->size)
#define sp_read(st) ((st)->top)
#define init_stack(st) ((st)->top = 0)
//スタック操作関数のプロトタイプ宣言.
extern stack_t *create_stack(unsigned int sz);
extern void push(stack_t *st, int num);
extern int pop(stack_t *st);
のようなプログラムがあったとしてungetc(tok, stdin); はどのような機能をもっているんですか??(このプログラム上で)あと、getcharは今まで使ったことがあるのですが今回の様な使い方を見たことがないのでなぜこのプログラムでは文字を入力することができているのかを教えて下さい><;;;(scanfのように)