#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
typedef enum {
Print, Lparen, Rparen, Plus, Minus, Multi, Divi,
Assign, VarName, IntNum, EofTkn, Others
} Kind;
typedef struct {
Kind kind;
int val;
} Token;
void input(void);
void statement(void);
void expression(void);
void term(void);
void factor(void);
Token nextTkn(void);
int nextCh(void);
void operate(Kind op);
void push(int n);
int pop(void);
void chkTkn(Kind kd);
#define STK_SIZ 20
int stack[STK_SIZ+1];
int stkct;
Token token;
char buf[80], *bufp;
int ch;
int var[26];
int errF;
int main(void)
{
while (1) {
input();
token = nextTkn();
if (token.kind == EofTkn) exit(1);
statement();
if (errF) puts(" --err--");
}
return 0;
}
void input(void)
{
errF = 0; stkct = 0;
buf[0] = '\0';
fgets(buf, 80, stdin);
bufp = buf;
ch = nextCh();
}
void statement(void)
{
int vNbr;
switch (token.kind) {
case VarName:
vNbr = token.val;
token = nextTkn();
chkTkn(Assign); if (errF) break;
token = nextTkn();
expression();
var[vNbr] = pop();
break;
case Print:
token = nextTkn();
expression();
chkTkn(EofTkn); if (errF) break;
printf(" %d\n", pop());
return;
default:
errF = 1;
}
chkTkn(EofTkn);
}
void expression(void)
{
Kind op;
term();
while (token.kind==Plus || token.kind==Minus) {
op = token.kind;
token = nextTkn(); term(); operate(op);
}
}
void term(void)
{
Kind op;
factor();
while (token.kind==Multi || token.kind==Divi) {
op = token.kind;
token = nextTkn(); factor(); operate(op);
}
}
void factor(void)
{
switch (token.kind) {
case VarName:
push(var[token.val]);
break;
case IntNum:
push(token.val);
break;
case Lparen:
token = nextTkn();
expression();
chkTkn(Rparen);
break;
default:
errF = 1;
}
token = nextTkn();
}
Token nextTkn(void)
{
int num;
Token tk = {Others, 0};
while (isspace(ch))
ch = nextCh();
if (isdigit(ch)) {
for (num=0; isdigit(ch); ch = nextCh())
num = num*10 + (ch-'0');
tk.val = num;
tk.kind = IntNum;
}
else if (islower(ch)) {
tk.val = ch - 'a';
tk.kind = VarName;
ch = nextCh();
}
else {
switch (ch) {
case '(': tk.kind = Lparen; break;
case ')': tk.kind = Rparen; break;
case '+': tk.kind = Plus; break;
case '-': tk.kind = Minus; break;
case '*': tk.kind = Multi; break;
case '/': tk.kind = Divi; break;
case '=': tk.kind = Assign; break;
case '?': tk.kind = Print; break;
case '\0': tk.kind = EofTkn; break;
}
ch = nextCh();
}
return tk;
}
int nextCh(void)
{
if (*bufp == '\0') return '\0'; else return *bufp++;
}
int operate(kind op, d1, d2) {
int d;
int d2 = pop(), d1 = pop();
if (op==Divi && d2==0) { puts(" division by 0"); errF = 1; }
if (errF) return;
switch (op) {
case Plus: d = d1+d2;
case Minus: d = d1-d2;
case Multi: d = d1*d2;
case Divi: d= d1/d2 ;
}
return d;
}
void push(int n)
{
if (errF) return;
if (stkct+1 > STK_SIZ) { puts("stack overflow"); exit(1); }
stack[++stkct] = n;
}
int pop(void)
{
if (errF) return 1;
if (stkct < 1) { puts("stack underflow"); exit(1); }
return stack[stkct--];
}
void chkTkn(Kind kd)
{
if (token.kind != kd) errF = 1;
}
C言語の改造
-
赤犬
C言語の改造
はじめまして。C言語のスタックを使った電卓のプログラムをスタックを使わないで、結果を直接リターンしたいのですがどうすればいいのでしょうか?このプログラムは私が現在、改造中のプログラムです。
-
赤犬
Re: C言語の改造
もともとのソースはこれです。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
typedef enum { /* ・ネ。シ・ッ・ホシ・・*/
Print, Lparen, Rparen, Plus, Minus, Multi, Divi,
Assign, VarName, IntNum, EofTkn, Others
} Kind;
typedef struct {
Kind kind; /* ・ネ。シ・ッ・ホシ・・*/
int val; /* ターソヘ */
} Token;
void input(void);
void statement(void);
void expression(void);
void term(void);
void factor(void);
Token nextTkn(void);
int nextCh(void);
void operate(Kind op);
void push(int n);
int pop(void);
void chkTkn(Kind kd);
#define STK_SIZ 20 /* ・ケ・ソ・テ・ッ・オ・、・コ */
int stack[STK_SIZ+1]; /* ・ケ・ソ・テ・ッ */
int stkct; /* ・ケ・ソ・テ・ッエノヘ */
Token token; /* ・ネ。シ・ッ・ハヌシ */
char buf[80], *bufp; /* ニホマヘム */
int ch; /* シ霹タハクサ妤ハヌシ */
int var[26]; /* ハムソ-z */
int errF; /* ・ィ・鬘シネッタク */
int main(void)
{
while (1) {
input(); /* ニホマ */
token = nextTkn(); /* コヌス鬢ホ・ネ。シ・ッ・・*/
if (token.kind == EofTkn) exit(1); /* スェホサ */
statement(); /* ハクシツケヤ */
if (errF) puts(" --err--");
}
return 0;
}
void input(void)
{
errF = 0; stkct = 0; /* ス魘・゚ト・ */
buf[0] = '\0';
fgets(buf, 80, stdin); /* 80ハクサ嵓ハニ筅ホニホマ */
bufp = buf; /* タ霹ャハクサ妤ヒーフテヨ、ナ、ア */
ch = nextCh(); /* コヌス鬢ホハクサ恝霹タ */
}
void statement(void) /* ハク */
{
int vNbr;
switch (token.kind) {
case VarName: /* ツ衄ハク */
vNbr = token.val; /* ツ衄タ靆ンツク */
token = nextTkn();
chkTkn(Assign); if (errF) break; /* '=' 、ホ、マ、コ */
token = nextTkn();
expression(); /* アヲハユキラササ */
var[vNbr] = pop(); /* ツ衄シツケヤ */
break;
case Print: /* printハク(?) */
token = nextTkn();
expression();
chkTkn(EofTkn); if (errF) break;
printf(" %d\n", pop());
return;
default:
errF = 1;
}
chkTkn(EofTkn); /* ケヤヒチ・ァ・テ・ッ */
}
void expression(void) /* シー */
{
Kind op;
term();
while (token.kind==Plus || token.kind==Minus) {
op = token.kind;
token = nextTkn(); term(); operate(op);
}
}
void term(void) /* ケ・*/
{
Kind op;
factor();
while (token.kind==Multi || token.kind==Divi) {
op = token.kind;
token = nextTkn(); factor(); operate(op);
}
}
void factor(void) /* ーメ */
{
switch (token.kind) {
case VarName: /* ハムソ・ */
push(var[token.val]);
break;
case IntNum: /* ターソ・・*/
push(token.val);
break;
case Lparen: /* ( シー ) */
token = nextTkn();
expression();
chkTkn(Rparen); /* ) 、ホ、マ、コ */
break;
default:
errF = 1;
}
token = nextTkn();
}
Token nextTkn(void) /* シ。・ネ。シ・ッ・・*/
{
int num;
Token tk = {Others, 0};
while (isspace(ch)) /* カノ、゚シホ、ニ */
ch = nextCh();
if (isdigit(ch)) { /* ソ・*/
for (num=0; isdigit(ch); ch = nextCh())
num = num*10 + (ch-'0');
tk.val = num; /* テヘウハヌシ */
tk.kind = IntNum;
}
else if (islower(ch)) { /* ハムソ・*/
tk.val = ch - 'a'; /* ハムソヨケ・-25 */
tk.kind = VarName;
ch = nextCh();
}
else {
switch (ch) {
case '(': tk.kind = Lparen; break;
case ')': tk.kind = Rparen; break;
case '+': tk.kind = Plus; break;
case '-': tk.kind = Minus; break;
case '*': tk.kind = Multi; break;
case '/': tk.kind = Divi; break;
case '=': tk.kind = Assign; break;
case '?': tk.kind = Print; break;
case '\0': tk.kind = EofTkn; break;
}
ch = nextCh();
}
return tk;
}
int nextCh(void) /* シ。、ホ1ハクサ・*/
{
if (*bufp == '\0') return '\0'; else return *bufp++;
}
void operate(Kind op) /* ア鮟サシツケヤ */
{
int d2 = pop(), d1 = pop();
if (op==Divi && d2==0) { puts(" division by 0"); errF = 1; }
if (errF) return;
switch (op) {
case Plus: push(d1+d2); break;
case Minus: push(d1-d2); break;
case Multi: push(d1*d2); break;
case Divi: push(d1/d2); break;
}
}
void push(int n) /* ・ケ・ソ・テ・ッタムケ */
{
if (errF) return;
if (stkct+1 > STK_SIZ) { puts("stack overflow"); exit(1); }
stack[++stkct] = n;
}
int pop(void) /* ・ケ・ソ・テ・ッシ霓ミ */
{
if (errF) return 1; /* ・ィ・鬘シサ、マテア、ヒ1、ヨ、ケ */
if (stkct < 1) { puts("stack underflow"); exit(1); }
return stack[stkct--];
}
void chkTkn(Kind kd) /* ・ネ。シ・ッ・・フウホヌァ */
{
if (token.kind != kd) errF = 1; /* ノヤー・ラ */
}
Re: C言語の改造
C言語のスタックを使わないでっていうのは、つまりstack変数を使わないでっていう意味でしょうか。
だとしたら、簡単なのは関数の再帰呼び出しを使うようにすることですかね。
だとしたら、簡単なのは関数の再帰呼び出しを使うようにすることですかね。
-
赤犬
Re: C言語の改造
スタックに値を残さないで直接結果をだしたいので、stack変数を使わない、popやpushを使わないようにしたいです。
再帰呼び出しですか、どこら辺をどう変えればいいんですか?一応、また改造してみたんですが、やっぱりうまくいかないです。
コンパイルは通るのですが・・・計算の結果が、
a=3
b=4
c=a+b
? c
4248700
と表示されて・・・計算ができないです。
再帰呼び出しですか、どこら辺をどう変えればいいんですか?一応、また改造してみたんですが、やっぱりうまくいかないです。
コンパイルは通るのですが・・・計算の結果が、
a=3
b=4
c=a+b
? c
4248700
と表示されて・・・計算ができないです。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
typedef enum { /* ・ネ。シ・ッ・ホシ・・*/
Print, Lparen, Rparen, Plus, Minus, Multi, Divi,
Assign, VarName, IntNum, EofTkn, Others
} Kind;
typedef struct {
Kind kind; /* ・ネ。シ・ッ・ホシ・・*/
int val; /* ターソヘ */
} Token;
void input(void);
void statement(void);
int expression(void);
void term(void);
void factor(void);
Token nextTkn(void);
int nextCh(void);
int operate(Kind op,int d1,int d2);
void chkTkn(Kind kd);
Token token; /* ・ネ。シ・ッ・ハヌシ */
char buf[80], *bufp; /* ニホマヘム */
int ch; /* シ霹タハクサ妤ハヌシ */
int var[26]; /* ハムソ-z */
int errF; /* ・ィ・鬘シネッタク */
int main(void)
{
while (1) {
input(); /* ニホマ */
token = nextTkn(); /* コヌス鬢ホ・ネ。シ・ッ・・*/
if (token.kind == EofTkn) exit(1); /* スェホサ */
statement(); /* ハクシツケヤ */
if (errF) puts(" --err--");
}
return 0;
}
void input(void)
{
errF = 0; /* ス魘・゚ト・ */
buf[0] = '\0';
fgets(buf, 80, stdin); /* 80ハクサ嵓ハニ筅ホニホマ */
bufp = buf; /* タ霹ャハクサ妤ヒーフテヨ、ナ、ア */
ch = nextCh(); /* コヌス鬢ホハクサ恝霹タ */
}
void statement(void) /* ハク */
{
int vNbr;
int a;
switch (token.kind) {
case VarName: /* ツ衄ハク */
vNbr = token.val; /* ツ衄タ靆ンツク */
token = nextTkn();
chkTkn(Assign); if (errF) break; /* '=' 、ホ、マ、コ */
token = nextTkn();
expression(); /* アヲハユキラササ */
/* ツ衄シツケヤ */
break;
case Print: /* printハク(?) */
token = nextTkn();
a=expression();
chkTkn(EofTkn); if (errF) break;
printf(" %d\n",a);
return;
default:
errF = 1;
}
chkTkn(EofTkn); /* ケヤヒチ・ァ・テ・ッ */
}
int expression(void) /* シー */
{
Kind op;
int d1;
int d2;
term();
while (token.kind==Plus || token.kind==Minus) {
op = token.kind;
token = nextTkn(); term(); operate(op,d1,d2);
}
}
void term(void) /* ケ・*/
{
Kind op;
int d1;
int d2;
factor();
while (token.kind==Multi || token.kind==Divi) {
op = token.kind;
token = nextTkn(); factor(); operate(op,d1,d2);
}
}
void factor(void) /* ーメ */
{
switch (token.kind) {
case VarName: /* ハムソ・ */
break;
case IntNum: /* ターソ・・*/
break;
case Lparen: /* ( シー ) */
token = nextTkn();
expression();
chkTkn(Rparen); /* ) 、ホ、マ、コ */
break;
default:
errF = 1;
}
token = nextTkn();
}
Token nextTkn(void) /* シ。・ネ。シ・ッ・・*/
{
int num;
Token tk = {Others, 0};
while (isspace(ch)) /* カノ、゚シホ、ニ */
ch = nextCh();
if (isdigit(ch)) { /* ソ・*/
for (num=0; isdigit(ch); ch = nextCh())
num = num*10 + (ch-'0');
tk.val = num; /* テヘウハヌシ */
tk.kind = IntNum;
}
else if (islower(ch)) { /* ハムソ・*/
tk.val = ch - 'a'; /* ハムソヨケ・-25 */
tk.kind = VarName;
ch = nextCh();
}
else {
switch (ch) {
case '(': tk.kind = Lparen; break;
case ')': tk.kind = Rparen; break;
case '+': tk.kind = Plus; break;
case '-': tk.kind = Minus; break;
case '*': tk.kind = Multi; break;
case '/': tk.kind = Divi; break;
case '=': tk.kind = Assign; break;
case '?': tk.kind = Print; break;
case '\0': tk.kind = EofTkn; break;
}
ch = nextCh();
}
return tk;
}
int nextCh(void) /* シ。、ホ1ハクサ・*/
{
if (*bufp == '\0') return '\0'; else return *bufp++;
}
int operate(Kind op,int d1,int d2) /* ア鮟サシツケヤ */
{
int d;
if (op==Divi && d2==0) { puts(" division by 0"); errF = 1; }
if (errF) return;
switch (op) {
case Plus: d = d1+d2;
case Minus: d = d1-d2;
case Multi: d = d1*d2 ;
case Divi: d = d1/d2 ;
}
return d;
}
void chkTkn(Kind kd) /* ・ネ。シ・ッ・・フウホヌァ */
{
if (token.kind != kd) errF = 1; /* ノヤー・ラ */
}
Re: C言語の改造
スタック構造を使わずに作りたいということですよね。
で、どう実現するつもりですか?プログラムを読み解くのは面倒なので考えを示してください。
また、スタック構造を使わずに作りたい理由はなんでしょうか?
で、どう実現するつもりですか?プログラムを読み解くのは面倒なので考えを示してください。
また、スタック構造を使わずに作りたい理由はなんでしょうか?
non
-
かずま
Re: C言語の改造
expression → term → factor → expression と呼び出していますから、赤犬 さんが書きました:スタックに値を残さないで直接結果をだしたいので、stack変数を使わない、popやpushを使わないようにしたいです。
再帰呼び出しですか、どこら辺をどう変えればいいんですか?
再帰呼び出しは既に行われてます。push, pos を使わないようにするには
それらの関数が値を返すようにすればよいだけです。 割り算の結果が
不自然なので int ではなく double にしておきました。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
typedef enum {
Print, Lparen, Rparen, Plus, Minus, Multi, Divi,
Assign, VarName, Num, EofTkn, Others
} Kind;
typedef struct {
Kind kind;
double val;
} Token;
void input(void);
void statement(void);
double expression(void);
double term(void);
double factor(void);
Token nextTkn(void);
int nextCh(void);
double operate(Kind op, double d1, double d2);
void chkTkn(Kind kd);
Token token;
char buf[80], *bufp;
int ch;
double var[26];
int errF;
int main(void)
{
while (1) {
input();
token = nextTkn();
if (token.kind == EofTkn) exit(1);
statement();
if (errF) puts(" --err--");
}
return 0;
}
void input(void)
{
errF = 0;
buf[0] = '\0';
fgets(buf, 80, stdin);
bufp = buf;
ch = nextCh();
}
void statement(void)
{
int vNbr;
double val;
switch (token.kind) {
case VarName:
vNbr = token.val;
token = nextTkn();
chkTkn(Assign); if (errF) break;
token = nextTkn();
var[vNbr] = expression();
break;
case Print:
token = nextTkn();
val = expression();
chkTkn(EofTkn); if (errF) break;
printf(" %.15g\n", val);
return;
default:
errF = 1;
}
chkTkn(EofTkn);
}
double expression(void)
{
Kind op;
double val = term();
while (token.kind==Plus || token.kind==Minus) {
op = token.kind;
token = nextTkn(); val = operate(op, val, term());
}
return val;
}
double term(void)
{
Kind op;
double val = factor();
while (token.kind==Multi || token.kind==Divi) {
op = token.kind;
token = nextTkn(); val = operate(op, val, factor());
}
return val;
}
double factor(void)
{
double val;
switch (token.kind) {
case VarName:
val = var[(int)token.val];
break;
case Num:
val = token.val;
break;
case Lparen:
token = nextTkn();
val = expression();
chkTkn(Rparen);
break;
default:
errF = 1;
}
token = nextTkn();
return val;
}
Token nextTkn(void)
{
int num;
Token tk = {Others, 0};
while (isspace(ch))
ch = nextCh();
if (isdigit(ch)) {
tk.val = strtod(bufp - 1, &bufp);
tk.kind = Num;
ch = nextCh();
}
else if (islower(ch)) {
tk.val = ch - 'a';
tk.kind = VarName;
ch = nextCh();
}
else {
switch (ch) {
case '(': tk.kind = Lparen; break;
case ')': tk.kind = Rparen; break;
case '+': tk.kind = Plus; break;
case '-': tk.kind = Minus; break;
case '*': tk.kind = Multi; break;
case '/': tk.kind = Divi; break;
case '=': tk.kind = Assign; break;
case '?': tk.kind = Print; break;
case '\0': tk.kind = EofTkn; break;
}
ch = nextCh();
}
return tk;
}
int nextCh(void)
{
if (*bufp == '\0') return '\0'; else return *bufp++;
}
double operate(Kind op, double d1, double d2)
{
if (op==Divi && d2==0) { puts(" division by 0"); errF = 1; }
if (errF) return 1;
switch (op) {
case Plus: return d1 + d2;
case Minus: return d1 - d2;
case Multi: return d1 * d2;
case Divi: return d1 / d2;
}
return 1;
}
void chkTkn(Kind kd)
{
if (token.kind != kd) errF = 1;
}