- ベストアンサー
ユーザ関数
ユーザ関数を使って scanfで数式(1+1、2*2、3-3、4/4)などを入力して printfで「入力した数式=答え」と表示するプログラムはどう作ればよいでしょうか?
- みんなの回答 (6)
- 専門家の回答
質問者が選んだベストアンサー
>この場合は「1 + 1」のように空白が必要ですか? 空白を入れた方が簡単に作れますので、空白を入れることにします。 >一番わからないのは、「2.次に、入力された式を A,演算子、Bに分解します。」の部分なのでそのあたりを詳しく教えてください。 strtok関数を使うと、空白で区切られた文字列を、分割して取り出すことができます。詳しくは、strtokをマニュアルなどで調べてください。 以下は、strtokを用いて文字列を分割するサンプルです。 ------------------------------------ #include <stdio.h> #include <stdlib.h> #include <string.h> int split1(char *moji) { // strtokを使用するバージョン // A 演算子 B はスペースで区切られていることが前提 // 分割したものを画面に表示する char *tok; tok = strtok(moji," "); while(tok != NULL){ printf("%s\n",tok); tok = strtok(NULL," "); } return 0; } int main(int argc, char *argv[]) { printf("TEST1\n"); split1("234 + 523"); printf("TEST2\n"); split1("234+523"); return 0; } ------------------------------------------ 上記を実行すると、 TESTのケースでは、234,+,523の順に文字列が取り出され印字されます。 TEST2のケースでは、234+523が1つの文字として取り出されます。 もし、空白を入れない(又は空白はあってもなくて良い)仕様で、文字列を分割すると、プログラムは、劇的に難易度が高くなります。(strtokは役に立ちません)もし、そのケースを望まれるなら、その旨を補足してください。
その他の回答 (5)
- jacta
- ベストアンサー率26% (845/3158)
演算子とオペランドの間に空白類文字を許すコードだけ、参考に書いておきます。 int lhs, rhs; char op[2]; scanf("%d%*[ \t\v\f\n]%1[*/+-]%*[ \t\v\f\n]%d", &lhs, op, &rhs);
- BLUEPIXY
- ベストアンサー率50% (3003/5914)
昔に作ったプログラムで、あんまり良いプログラムでもないですけど、 なんかの参考に ---------------------------------------------------------------- #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #define MAXLEN 80 #define STACKSIZE 3 int calc(char *str){ /* (3+5)*7-2 のような文字列を計算する */ char cstack[STACKSIZE]; /* 演算子スタック */ int vstack[STACKSIZE]; /* 値スタック */ int vsp,csp; int level; int sign=0; int wk=0; char buff[MAXLEN]; char *p,*pwk,cwk; /* trim */ for(pwk=p=str;*p;p++) if(*p=='\t' || *p==' ') continue; else *pwk++=*p; *pwk=*p; vsp=csp=STACKSIZE; cstack[--csp]='@';/* empty mark */ p=str; while(*p){ if(isdigit(*p)){ if(sign==0)sign=1; wk=wk*10+ *p++ - '0'; } else { /* 数字以外の文字が現れた時は、数が決定する */ if(sign!=0)vstack[--vsp]=sign*wk; /* 数をスタックに積む */ wk=0; /* wkを次の数の読み取りのために初期化する */ sign=0; switch(*p){ case '*': case '/': cwk=cstack[csp]; if(cwk=='@' || cwk=='+' || cwk=='-') cstack[--csp]=*p; else{ if(cwk=='*') vstack[vsp+1]*=vstack[vsp]; else if(cwk=='/') vstack[vsp+1]/=vstack[vsp]; vsp++; cstack[csp]=*p; } p++; break; case '-': if(str==p){ sign=-1; p++; break; } else if(NULL!=strchr("*/+-",*(p-1))){ sign=-1; p++; break; } case '+': cwk=cstack[csp]; if(cwk=='@') cstack[--csp]=*p; else { switch(cwk){ case '+': vstack[vsp+1]+=vstack[vsp];break; case '-': vstack[vsp+1]-=vstack[vsp];break; case '*': vstack[vsp+1]*=vstack[vsp];break; case '/': vstack[vsp+1]/=vstack[vsp];break; } vsp++; cstack[csp]=*p; } p++; break; case '(': /* カッコ中身でcalcを呼び出す */ p++; level=1; sign=1; for(pwk=buff;*p;p++){ if(*p==')'){ if(--level==0){ *pwk='\0'; wk=calc(buff); break; } } else if(*p=='('){ level++; } *pwk++=*p; } if(level){/* カッコの数が合っていない時 */ *pwk='\0'; wk=calc(buff); } else p++; break; case ')':/* ありえないはず */ p++; fprintf(stderr,"閉じカッコが多すぎる\n"); break; default: fprintf(stderr, "使用できない文字[%c]がある\n",*p++); } } } vstack[--vsp]=sign*wk; while('@'!=(cwk=cstack[csp++])){ switch(cwk){ case '+': vstack[vsp+1]+=vstack[vsp];break; case '-': vstack[vsp+1]-=vstack[vsp];break; case '*': vstack[vsp+1]*=vstack[vsp];break; case '/': vstack[vsp+1]/=vstack[vsp];break; } vsp++; } return (vstack[vsp]); } void main(void){ char buff[MAXLEN]; gets(buff); printf("=%d\n", calc(buff)); exit(EXIT_SUCCESS); }
- tatsu99
- ベストアンサー率52% (391/751)
最も簡単なケースです。 式は、以下のケースのみとします。 A 演算子 B 1.ここで、Aは、数字のみから構成される文字列 演算子は、+、-、*、/の何れか Bは数字のみから構成される文字列 とします。 2.次に、入力された式を A,演算子、Bに分解します。 更にAからその値を求め、int型の変数(a)に格納します。 更にBからその値を求め、int型の変数(b)に格納します。 3.次に演算子に従い、演算を行います。 演算子が+の時、c=a+b 演算子が-の時、c=a-b 演算子が*の時、c=a*b 演算子が/の時、c=a/b cはint型の変数です。 4.答えの表示でcを表示します。
- jacta
- ベストアンサー率26% (845/3158)
2値の四則演算だけなら簡単だと思いますが、どの辺りが分からないのでしょうか? もし質問が「作成依頼目的」であれば禁止事項に該当しますので、せっかく回答を書いても削除されてしまいます。
- jacta
- ベストアンサー率26% (845/3158)
入力可能な数式は、どの程度複雑なものまで想定していますか? 例えば、2値の四則演算のみであれば簡単ですし、四則演算のみでも優先順位まで考慮するのであれば、かなり複雑になります。累乗やら、三角関数やら、仕様が膨らめばそれだけ複雑さが増します。 また、扱う数値ですが、整数だけでしょうか?実数を扱うのでしょうか?その場合、doubleやlong doubleで表現できない場合は多倍長演算を使ってでも正確に計算すべきなのでしょうか?あるいは、複素数まで扱うのでしょうか? 「scanfで数式(1+1、2*2、3-3、4/4)などを入力してprintfで「入力した数式=答え」と表示するプログラム」を作るには、そういった仕様を固めることがまず先決です。
補足
四則演算のみです。 整数値のみで実数は扱いません。 よろしくお願いします!
補足
この場合は「1 + 1」のように空白が必要ですか? 一番わからないのは、「2.次に、入力された式を A,演算子、Bに分解します。」の部分なのでそのあたりを詳しく教えてください。