C言語の改造

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
赤犬

C言語の改造

#1

投稿記事 by 赤犬 » 14年前

はじめまして。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];                              
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;        
}

 

赤犬

Re: C言語の改造

#2

投稿記事 by 赤犬 » 14年前

もともとのソースはこれです。

コード:


#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;        /* ノヤー・ラ */
}

beatle
記事: 1281
登録日時: 14年前
住所: 埼玉
連絡を取る:

Re: C言語の改造

#3

投稿記事 by beatle » 14年前

C言語のスタックを使わないでっていうのは、つまりstack変数を使わないでっていう意味でしょうか。
だとしたら、簡単なのは関数の再帰呼び出しを使うようにすることですかね。

赤犬

Re: C言語の改造

#4

投稿記事 by 赤犬 » 14年前

スタックに値を残さないで直接結果をだしたいので、stack変数を使わない、popやpushを使わないようにしたいです。
再帰呼び出しですか、どこら辺をどう変えればいいんですか?一応、また改造してみたんですが、やっぱりうまくいかないです。
コンパイルは通るのですが・・・計算の結果が、
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;        /* ノヤー・ラ */
}

non
記事: 1097
登録日時: 15年前

Re: C言語の改造

#5

投稿記事 by non » 14年前

スタック構造を使わずに作りたいということですよね。

で、どう実現するつもりですか?プログラムを読み解くのは面倒なので考えを示してください。
また、スタック構造を使わずに作りたい理由はなんでしょうか?
non

かずま

Re: C言語の改造

#6

投稿記事 by かずま » 14年前

赤犬 さんが書きました:スタックに値を残さないで直接結果をだしたいので、stack変数を使わない、popやpushを使わないようにしたいです。
再帰呼び出しですか、どこら辺をどう変えればいいんですか?
expression → term → factor → expression と呼び出していますから、
再帰呼び出しは既に行われてます。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;
}

閉鎖

“C言語何でも質問掲示板” へ戻る