• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:C言語で電卓を作成する。修正お願いします。)

C言語で電卓を作成する修正方法

このQ&Aのポイント
  • C言語で電卓を作成するプログラムの修正方法についてお知らせします。
  • 現在のプログラムでは、割り算が最初に出てくる場合に計算結果がおかしくなってしまう問題があります。
  • この問題を解決するために、int型の変数宣言を変更せずに計算結果が正しく出るようにする方法をご指導します。

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

  • ベストアンサー
  • R_Earl
  • ベストアンサー率55% (473/849)
回答No.8

ANo.2, 7です。 ANo.7ではcalc関数を修正しない方が良いと言いましたが、 ちゃんと計算できるように追加コード部分を修正してみました。 修正箇所は if((*op == '/') && (*(op + 1) == '*')){/*op='/'、op+1='*'が入った時*/  *x = (*x) * (*(x + 2));  printf("answer1 = %d\n",*x);  *(x + 2) = *x / *(x + 1) ;  printf("answer2 = %d\n",*(x + 2));  return *x; } の部分です。これを if((*op == '/') && (*(op + 1) == '*')){/*op='/'、op+1='*'が入った時*/  *x = (*x) * (*(x + 2));  printf("answer1 = %d\n",*x);  *(x + 2) = *x / *(x + 1) ;  printf("answer2 = %d\n",*(x + 2));  // return文は不要  // 以下5行が追加コード  *x = 0;  *(x + 1) = 0;  x = x + 2;  op = op + 2;  continue; } と直すと上手くいきます (インデントに全角スペースを使っているので注意して下さい)。 *x = 0や*(x + 1) = 0が必要な理由は、 calc関数内のswitch文で*x = 0が実行されている理由と同じなのですが、 何故このコードが必要なのかは分かりますか? この修正をすれば10/4*4のように、 「わり算1回、かけ算1回を行う式」には上手く対応できます。 しかし10/4/5*5*4や10/4/5*4*5のように、 「わり算が2回以上連続して続いた後にかけ算がある式」には対応できません。 これは追加コードでは、隣り合うわり算、かけ算のみを処理しているのが原因です。 例えば10/4/5*5*4では/5と*5は追加コード部分でうまく処理されるのですが、 位置が離れている/4と*4は処理されません。 これで妥協するかどうかは質問者さんに任せます。 妥協したくないなら、このコードを更に修正するか、 あるいは別の方法を取る事になります。

すると、全ての回答が全文表示されます。

その他の回答 (7)

  • R_Earl
  • ベストアンサー率55% (473/849)
回答No.7

追加コードの部分にreturnがあります。 これではwhileループで全ての数を処理する前に calc関数を抜けてしまいます。 計算結果がおかしくなるのはそのためだと思います。 こういう面倒なことがあるので、並び替えの処理は calc関数の中でやらない方がいいと思います。 並び替えだけを行う関数を作り、main関数の中で (1) 並び替え関数 (2) calc関数(mode =1) (3) calc関数(mode =0) の順番で関数を呼び出せば良いと思いますが…。

すると、全ての回答が全文表示されます。
  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.6

掛け算を先にやったらオーバーフローの可能性があるんだけど, そこには目をつむるってのが理解できん. たとえば, int が 32ビットの環境で 1000000 / 100001 * 100001 を計算すると掛け算を先にやっても割算を先にやっても「期待した結果」にはならないはずなんだけど, そんなんでいいのか?

dezaemon1120
質問者

補足

いいです。 高精度な計算結果は求めていません。 自分が途中まで出来たのを入れます。 条件分岐を入れてみましたが、最終的な結果はおかしくなってしまいます。 下記にソースを入れます。修正箇所を教えて頂けますか? #include <stdio.h> #include <stdlib.h> /* int check_num(int *x, char *op) { int i; while(*op != '=') { for(i=0; i<10; i++) { x[i] == *(x + i); if(*(op + i) == '='){ calc(x, op , 1); } } } } */ int calc(int *x, char *op, int mode) /* x=項、op=演算子、mode=0か1で処理を分岐*/ { while (*op != '=') { /*opに'='が代入されるまで回す*/ if (mode==0) { /*mode=0の処理(mode=1で得た計算結果を最後に加算する)*/ *(x + 1) = *(x+1) + (*x); x++; /*配列に入れられた値を更新*/ op++; /*'='が出されるまでopを更新*/ } if (mode==1) { /*mode=1の処理(乗算、除算、減算を行って、計算結果を配列に入れる)*/ if((*op == '/') && (*(op + 1) == '*')) { /*op='/'、op+1='*'が入った時*/ *x = (*x) * (*(x + 2)); printf("answer1 = %d\n",*x); *(x + 2) = *x / *(x + 1) ; printf("answer2 = %d\n",*(x + 2)); return *x; } switch (*op) { /*乗算*/ case '*': *(x + 1) = (*x) * (*(x + 1)); /*例:x+1=4(x)×2(x+1)*/ *x = 0; break; /*除算*/ case '/': *(x + 1) = *x / *(x + 1); /*例:x+1=4(x)÷2(x+1)*/ *x = 0; break; /*減算*/ case '-': /*例:x+1=2×(-1)*/ *(x + 1) = *(x+1) * (-1); /*最後に加算を行うので値をマイナスにして配列に入れる*/ break; } x++; op++; } } return *x; } int main(void) { int x[10]; /* 項 */ char op[10]; /* 演算子 */ int i; while (1) { printf("式を入力してください\n"); printf("例:1*2+5=enter \n"); printf("式:"); for (i = 0; i<10; i++) { /*10項まで計算可*/ scanf("%d %c", x + i, op + i); if (*(op + i) == '=') /*op='='が代入されるまで回し続ける*/ break; } calc(x, op, 1); printf("答え:%d\n", calc(x, op, 0)); /*mode=0の処理へ移行(最後に加算をして結果を出力)*/ } /* return 0;*/ }

すると、全ての回答が全文表示されます。
  • TT414
  • ベストアンサー率18% (72/384)
回答No.5

>割り算と掛け算の順序を逆転させるという、 >数式解析のむずかしい技を使ってまで >int型にこだわる理由が全くわかりません。 >講師の方がこういう課題を出してきました。結構、天邪鬼なかたなので。 まともなプログラマなら少数または分数処理するものを、整数にこだわる講師はまともでありません。講師本人の知識を披露したいだけのバカです。 この手のくだらない事に頭を使わずに、学校に抗議して講師を変えてもらったほうが良いです。

すると、全ての回答が全文表示されます。
  • asuncion
  • ベストアンサー率33% (2127/6290)
回答No.4

割り算と掛け算の順序を逆転させるという、 数式解析のむずかしい技を使ってまで int型にこだわる理由が全くわかりません。 もしよかったら、その理由を教えていただけますか?

dezaemon1120
質問者

補足

自分も正直そう思います。 しかし、講師の方がこういう課題を出してきました。結構、天邪鬼なかたなので。 ヒントでは左辺に'÷'右辺に'×'がきたら掛け算を行うということらしいですが、貼り付けてあるソースは 計算された値を一度配列に格納してから、最後に加算しているので難しいと思います。 すみませんが、お力添えをお願いします。

すると、全ての回答が全文表示されます。
  • phoenix343
  • ベストアンサー率15% (296/1946)
回答No.3

固定小数という考え方があります。 32bitのint型なら、左側16bitが整数部、右側16bitが小数部として扱う。 この方法ですと整数型で計算することが可能ですが、ただし有効桁数が 浮動小数のfloat、doubleに比べ小さいことに留意しましょう。。 固定小数点演算 http://www2.muroran-it.ac.jp/circle/mpc/front/old1/program/algorithm/fixedpoint/index.html

参考URL:
http://www2.muroran-it.ac.jp/circle/mpc/front/old1/program/algorithm/fixedpoint/index.html
すると、全ての回答が全文表示されます。
  • R_Earl
  • ベストアンサー率55% (473/849)
回答No.2

計算をする前に因数の順番を入れ換えれば良いと思います。 かけ算わり算で繋がっているところを見つけ、 その部分を、かけ算がわり算よりも左側に来るように並べかえるんです。 この前処理さえしてしまえば、 計算処理をするコードを書き換える必要はなくなります。 ただこの方法でも、1 / 2 + 1 / 2のような式には対応できません。 こういった式も処理したいなら、int型整数を2つ使って分数を表現し、 分数を使って計算処理をするという方法が考えられます。

すると、全ての回答が全文表示されます。
  • papapa0427
  • ベストアンサー率25% (371/1472)
回答No.1

無理です。 int型では常に少数部のカットが行われるのでどうしようもありません。言語仕様ですから、どうしても「10/4*4」の計算で常に「10」と正しい答えを出したいのならフロート型かダブル型を使用して最終的に少数部切ってください。

すると、全ての回答が全文表示されます。

関連するQ&A