• ベストアンサー

四則演算プログラム(入力式の表示版)

プログラミング初心者の大学生です。よろしくお願いいたします。  計算式入力し、計算結果を表示するプログラムの作成方法がわかりません。 条件としては、数値は実数の入力を可能とし、括弧の利用は考えないとのことです。    【実行例】  ・計算式="5.2+20*2-3"  ・結果=42.2  いきなり難易度が上がっため、自分の手には負えませんでした…。 どなたか、良いお答えをよろしくお願いいたします。

質問者が選んだベストアンサー

  • ベストアンサー
  • Directxq
  • ベストアンサー率42% (8/19)
回答No.3

今頃このような問題をしているという事は大学1年生位でしょうかね? 確かにこの前始めた人にこの問題は結構辛いですね。 回答例・・というか99%答えなんですけど^^; サンプルプログラムを書きましたんで、見てください。 入門者さんみたいなのでなるべく簡単な関数や書き方で書きました。 #include<stdio.h> #include<string.h> int num[20],atainokosu; char input_str[100],enzanshi[10],str[10][20]; int a2i(char*str){ int cnt; int num=0; for (cnt = 0; (str[cnt] >= '0') && (str[cnt] <= '9') ; cnt++) { num = 10 * num + (str[cnt]-'0'); } return num; } int getch(){ int i=0; while( ( input_str[i] = getchar() ) != EOF) i++; input_str[i-1]='\0'; return 0; } int divch(){ int i=0,j=0,s=0; while(input_str[i]!='\0'){ if(input_str[i] == '+' || input_str[i]=='-' || input_str[i]=='*' || input_str[i] =='/'){ enzanshi[j]=input_str[i]; j++; s=0; } else{ str[j][s]=input_str[i]; s++; } i++; } atainokosu=j; for(i=0;i<=j;i++) num[i]=a2i(str[i]); return 0; } int calc(){ int i=0,j; while(i<=atainokosu){ if(enzanshi[i]=='*'){ num[i]=num[i]*num[i+1]; j=i; while(j<=atainokosu){ num[j+1]=num[j+2]; enzanshi[j]=enzanshi[j+1]; j++; } atainokosu--; } else if(enzanshi[i]=='/'){ num[i]=num[i]/num[i+1]; j=i; while(j<=atainokosu){ num[j+1]=num[j+2]; enzanshi[j]=enzanshi[j+1]; j++; } atainokosu--; } else i++; } i=0; while(0<atainokosu){ if(enzanshi[i]=='+'){ num[i]=num[i]+num[i+1]; j=i; while(j<=atainokosu){ num[j+1]=num[j+2]; enzanshi[j]=enzanshi[j+1]; j++; } atainokosu--; } else if(enzanshi[i]=='-'){ num[i]=num[i]-num[i+1]; j=i; while(j<=atainokosu){ num[j+1]=num[j+2]; enzanshi[j]=enzanshi[j+1]; j++; } atainokosu--; } else i++; } return 0; } int main(){ int i; getch(); divch(); calc(); printf("計算式=\"%s\"\n結果=%d\n",input_str,num[0]); return 0; } これは整数の四則演算ができるプログラムです。 浮動小数点には対応していません。 例: 「10/5+2*5」と入力し、エンターを押す。その後Ctrl + Zを押してエンターを押す。すると計算結果が表示される。 100%答えを書いてしまってはよくないので(といっても99%答えですけど) ココまでプログラム書いたんで、今度は小数点も計算できるように改良してください。 ヒントは#2さんが既におっしゃっています。 4.strtod して値を返す この辺をヒントに頑張ってください。 わかれば1分で完成すると思います。 プログラムの中身は次に説明します。 頑張ってください。

その他の回答 (7)

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.8

逆ポーランド記法に変換してからあとでまとめて計算しなくても スタックに中間結果をつみながら変換(と計算)をできないこともありません。 Cで書くと答えになっちゃうのでPerlで。 use strict; use warnings; my @src = split /([\/*+-])/, <DATA>; my @stack; my %fn_tbl = (   '+' => sub {my ($lhs, $rhs) = @_; $lhs + $rhs},   '-' => sub {my ($lhs, $rhs) = @_; $lhs - $rhs},   '*' => sub {my ($lhs, $rhs) = @_; $lhs * $rhs},   '/' => sub {my ($lhs, $rhs) = @_; if ($rhs != 0) {$lhs / $rhs}         else {warn "divide by 0\n"; 0}} ); sub do_calc {   return if @stack < 3;   my $arg2 = pop @stack;   my $op  = pop @stack;   my $arg1 = pop @stack;   push @stack, $fn_tbl{$op}->($arg1, $arg2); } foreach my $item (@src) {   $item =~ s/^\s+//;   $item =~ s/\s+$//;      if ($item =~ m/\d+/) {     push @stack, $item;     next;   }   if ($item =~ m/[+-]/) {     do_calc if @stack > 3 and $stack[-2] =~ m/[*\/+-]/;     push @stack, $item;   }   elsif ($item =~ m/[*\/]/) {     push @stack, $item;   } } do_calc while @stack > 1; print join ':', @stack; __END__ 5.2+20*2-3

  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.7

#2>3.左から*または/を探し2分割する、return eval(左部分)*(/)eval(右部分); の部分、間違ってました。 これだと右結合になってしまいます。 3.右から*または/を探し2分割する、return eval(左部分)*(/)eval(右部分); ですね。(+、-は、ぶっちゃけどっちでも変わらないけど) #5>//3.左から*または/を探し2分割する、return eval(左部分)*(/)eval(右部分); #5>pos=strpbrk(buff, "*/"); を //3.右から*または/を探し2分割する、return eval(左部分)*(/)eval(右部分); pos =strrchr(buff, '*'); pos2=strrchr(buff, '/'); if(pos<pos2) pos=pos2; に修正

  • luckymako
  • ベストアンサー率55% (29/52)
回答No.6

逆ポーランド法と検索してみて下さい。 どんな入力式に対しても優先順位を一つずつ考慮して計算するルーチンを作るのは骨が折れると思います。 逆ポーランド法を用いるとすべての演算を同じルーチンにかけるだけで優先順位を考慮して計算できるので解りやすく、バグも少なく出来ると思います。 同時にスタックやキューの勉強も出来て一石二鳥です。 プログラムの構造を大きく分けると、 1.数式を格納した文字列を数値、演算子ごとに配列に格納する 2.配列を逆ポーランド記法に並び替える 3.逆ポーランド法に従って計算する という三段構成です。 1の部分は他の方の回答を参考に出来ると思います。 2と3はアルゴリズムが書籍やwebで明確に示されているのでプログラムを起こすのは容易に出来ると思います。 この方法を用いるとすべての演算をひとつのアルゴリズムで行えるため他の演算子(たとえばmod)や関数(たとえばsin,cos,tan,nPr)、括弧などへの拡張が驚くほど簡単です。 参考サイトはVisualBasicのコードしかありませんがCも探せばあるはずです。アルゴリズムもスタックの図を用いて説明してありますので自分で起こすことも出来ると思います。

参考URL:
http://www.nextftp.com/swlabo/m1_vbnet/hp_tips/hp_tips_81_math/t8108.htm
  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.5

#2の方針のプログラム #include <stdio.h> #include <string.h> #include <ctype.h> #include <math.h> double eval(char *exp){ int len; char *buff, *pd, *ps; char *pos; //0.全てのスペース文字を取り除く buff=strdup(exp); for(pd=buff,ps=exp;*ps;ps++){ if(isspace(*ps))continue; *pd++=*ps; } *pd=*ps; //1.左から+を探し2分割する、return eval(左部分)+eval(右部分); pos=strchr(buff, '+'); if(NULL!=pos){ *pos='\0'; return eval(buff)+eval(pos+1); } //2.先頭の-は、無視して-を探し2分割する、return eval(左部分)-eval(右部分); pos=strchr(buff+1, '-'); if(NULL!=pos){ *pos='\0'; return eval(buff)-eval(pos+1); } //3.左から*または/を探し2分割する、return eval(左部分)*(/)eval(右部分); pos=strpbrk(buff, "*/"); if(NULL!=pos){ if(*pos=='*'){ *pos='\0'; return eval(buff)*eval(pos+1); } else { *pos='\0'; return eval(buff)/eval(pos+1); } } //4.strtod して値を返す return atof(buff);//手抜き、本当はstrtod で全て消費したか、エラーがないか調べる //手抜き2,retvalue = eval(左) 演算子 eval(右);free(buff);return retvalue; すべき } void main(void){ char buff[128]; printf("計算式="); fgets(buff, 128, stdin); printf("結果=%g\n",eval(buff)); }

  • Directxq
  • ベストアンサー率42% (8/19)
回答No.4

下の補足です。 プログラムの中身について説明します。 実際にプログラムを上から順に見ながら説明をみてください。 まずa2i()関数は無理に理解しなくて結構です。 この関数名を検索したらヒットする有名な 「文字列としての数字」から「int型の数字」に変換する関数です。 いつもコピペで使えば良いので構造を無理に覚えなくて大丈夫です。 getch()関数で入力文字列を取得します。 getcharは標準関数なので自分で調べてください。 EOFは^Zが入力された時判断するものです。 Ctrl Z を押すのはそのためです。 なぜinput_str[i-1]に\0を代入しているかと言うと文字列は終端記号が必要で、しかも^Zする前に1回エンターを押しているせいで\n改行記号が1つ前にはいっているため、このような代入をしています。 divch()関数は演算子ごとに塊をわけています。 数字文字列は数字文字列、記号は記号の配列に代入しています。 atainokosuに項数を格納します。いくつ項があるか数えています。 終わったら、文字列としての数字をint型の数字にa2iで変換します。 calc()関数で実際に計算しています。 ちょっとこれは説明が難しいですね~・・。 まず四則演算って+-*/のうち*/を先にしないといけないですね。 whileをその2つに大分します。 */を全部計算しおわったら+-の計算をしています。 今の項と次の項を計算し計算結果を今の項に代入します。 代入し終わったら計算した次の甲を順次左によせていきます。 例: num[0]に3 num[1]に2 num[2]に10 num[3]に2 が入っているとする。 num[0]*num[1]の計算結果をnum[0]に代入する。 後は左よせする。 num[1]に10 num[2]に2 を代入。 3 * 2 + 10 - 2 ↓ 6 + 10 - 2 こんな感じです。 演算子も enzanshi[0]=='*' だったものを enzanshi[0]=enzanshi[1]して+に変化させています。 つまり左よせしています。 四則演算すべてを計算し終わったらnum配列は[0]だけに計算結果が残るので これを出力すればよい。 プログラムの流れは以上です。 解らない事があれば、聞いてください。

Sulley-Y
質問者

お礼

本当に御丁寧にありがとうございました。 一度、このプログラムを回してみて、それから何とかしてみます。 本当にありがとうございます!

  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.2

double eval(char *); 0.前後のスペース文字を取り除く(あるいは、全てのスペース文字を取り除く) 1.左から+を探し2分割する、return eval(左部分)+eval(右部分); 2.先頭の-は、無視して-を探し2分割する、return eval(左部分)-eval(右部分); 3.左から*または/を探し2分割する、return eval(左部分)*(/)eval(右部分); 4.strtod して値を返す

回答No.1

1. */を挟む2数を見つけ、掛ける/割る 2. (1)で見つけた部分をその積/商に置き換える 3. (1)(2)を*/がなくなるまで繰り返す。 4. +-だけになったので、そのまま足す/引く

Sulley-Y
質問者

お礼

要点をまとめて説明していただき、ありがとうございました。

関連するQ&A

  • プログラム(演算)

    プログラミング初心者です。 「1+3*(2+4)」などのように1桁の正整数と加算、乗算、カッコからなる式がキーボードから入力されるとき、その計算結果を画面に表示するプログラムを作成せよ。ただし、再帰を使用しないこと。 というのが問題なのですが、手の付け方がまったく思いつきません。分かる方がいればヒントをくだされば幸いです。

  • 値を入力し、入力した値から最大値、最小値、平均を導くプログラム

    Javaのプログラムの質問です。 プログラム実行後4つの数値を入力し入力された数値の中で 最大値、最小値、4つの数値の平均を表示するプログラムの作成のしかたを教えていただけますでしょうか? 例 プログラム実行 1つ目は? 2 2つ目は? 50 3つ目は? 32 4つ目は? 17 最大値は50です。 最小値は2です。 平均は25.25です。 という感じにするにはどうすればいいのでしょうか? よろしくお願いします。

  • python四則演算の問題

    python初心者の者です。 ある問題で、input()を使って入力した数字を百倍して表示するという問題があって、以下が作成したプログラムです。 ~省略~ line = input print(line * 100) 例で10をlineに代入したとして実行すると、1000ではなく、10が100個表示されるのですが、これはprint()内のlineが文字として認識されているから100かけれないんですか? 昨日始めたばかりでエラーについて全然わからないもので、 教えてください!

  • 四則演算の順番

    引き算と割り算では結合法則が成り立たないから左から計算するとのことですが、特に引き算について 証明(1) (a-b)-c=a-b-c 証明(2) a-(b-c)=a-b+c なので結合法則が成立しないというのが理由らしいのですが、 例として 1-1-1= という計算は左から計算しても右の部分から計算しても 計算結果は -1 になると思います。 証明(2)のように1-(1-1)=1 と計算する人はいないと思うのですが、どうして上記のような証明になるのでしょうか? (※括弧をつけて計算するなら、1-(1+1)=-1 となると思うのですが…?) 教えていただけると幸いです。宜しくお願いします。

  • C言語で四則演算を使って結果が10になる数式

    C言語のプログラミングについて質問です。 四つの一桁の数字を入力して四則演算を使って結果が10になる数式を作りたいのですが、イメージが湧きません。 教えていただけますか? 例:1234enterkey 答え2*3+1*4 数値の変数はint型でお願いします。int型ですので小数点以下を使って10になる結果は出さなくて宜しいです。お願いします。

  • Pascalにて入力した式の演算

    タイトルのとおり、Pascalにて入力した式の演算を行うプログラムを作ろうと考えています。 例えば 1 + 3 * 3 = と入力すると10と出力されるようなものです。 そこで、アルゴリズムとしては 式を全てcharとしてread 括弧があるか探し、あるなら括弧閉じるを探す 括弧内で乗除算を探す その右と左の数をintegerなりに変換して演算 以下同様に計算 …という風に考えました。 そこで質問なのですが、 式のreadをするとき、変数は配列型でいいのでしょうか 配列型だとひとつの配列に二桁以上の数ひとつだけ、という風にしか収納出来ないと思うので、これでは不可能な気もします。 また配列型では不可ならどうすればいいでしょうか。 次に、式をreadした後、そのreadをどのようにして終わらせるか 以上二点がよく分からないので、よろしければお答え願います。 また私の考えが大きく違う時等も御指示お願いします。

  • C言語の課題で困っています。その1.四則演算

    二つの整数値を読み込んで、前者を後者で割り、その結果の商と余りを表示するプログラムを作成。 実行例にあるよう、ゼロで割るような場合への対処も考慮する。 実行例1: 整数の除算を行います。整数を入力してください。 整数A:13 整数B:5 13 ÷ 5 = 2 あまり 3 実行例2: 整数の除算を行います。整数を入力してください。 整数A:10 整数B:0 0でわることはできません! (注)プログラム実行時にキーボードからどんな整数を入力してもいいように作成すること。 という課題に取り組んでいますが、途中までしか記述できません。 どなたか助けてください。 下記が途中までの記述です。 /*二つの整数値を読み込んで、前者を後者で割り、その結果の商と余りを表示*/ #include <stdio.h> int main(void) { int na, nb; printf("shimasaki kazunori \n"); puts("整数の除算を行います。整数を入力してください。: \n"); printf("整数A:"); scanf("%d", &na); printf("整数B:"); scanf("%d", &nb); printf("na ÷ nb = %d あまり %d \n", na / nb, nb, na % nb); return(0); }

  • C言語の四則演算

    C言語で次のようなプログラムを作りたいのですが ソースを教えていただけないでしょうか? 四則演算のみの計算式を標準入力から受け取り計算式の通りに計算を行い計算式と答えを標準出力に出力する どなたか教えてください

  • Delphi で動的な計算式の答えを簡単に出すには?

    Delphi初心者です。 ユーザーに任意の計算式【例:(100+50)*12】をEditなどに文字列入力させ、その答え【1800】を計算するプログラムを簡単に作成できないでしょうか?括弧を多用する長い式でもエクセルの様に式全体を一度に評価できる方法があればベストなのですが?

  • 子ウィンドウへ引数の受け渡し

    Javascriptを使った計算式を作成しております。 計算式のほうは完成しており、ソース内の「A= 」~「F= 」の部分に数値を直接入力し実行すると、 答えが表示される状態になっています。 最終的に6つのTEXTBOXに数値を入力し、送信ボタンを押すと子ウィンドウが開き、 その数値を引数とした計算の答えが表示されるプログラムを作成したいと思っていますが、 計算式を作成したところで、力尽きてしまいました。 どうか、プログラムを完成させるお力添えをお願いします。

専門家に質問してみよう