![](http://oshiete.xgoo.jp/images/v2/pc/qa/question_title.png?a65a0e2)
C言語を用いて三項まで計算できる電卓を作りたいのですが、どうも上手くいきません。
四則演算(+、-、×、÷)の優先順位を用いたプログラミング方法が分かりません。
以下に自分で作成したソースを添付します。
このソースに修正や追加して3項までの四則演算できるプログラミングを教えていただけますか?
宜しくお願いします。
#include <stdio.h>
int main(void)
{
int answer;/*答え*/
int x,y,z;/*x=第一項,y=第二項,第三項*/
char op1,op2;/*演算子1、演算子2*/
while(1){
printf("式を入力してください\n");
printf("式:");
scanf("%d %c %d %c %d" ,&x,&op1,&y,&op2,&z);
if((op1=='+'|'-'|'*'|'/') && (op2=='+'|'-'|'*'|'/')){
switch(op2){
case '+':
answer=y+z;
break;
case '-':
answer=y-z;
break;
case '*':
answer=y*z;
break;
case '/':
if(z==0){
printf("ERROR\n");
return 0;
}
answer=y/z;
break;
default:
printf("ERROR\n");
return 0;
}
switch(op1){
case '+':
answer=x+answer;
break;
case '-':
answer=x-answer;
break;
case '*':
answer=x*answer;
break;
case '/':
if(y==0){
printf("ERROR\n");
return 0;
}
answer=x/answer;
break;
default:
printf("ERROR\n");
return 0;
}
printf("答え:%d\n",answer);
}
else {
switch(op1){
case '+':
answer=x+y;
break;
case '-':
answer=x-y;
break;
case '*':
answer=x*y;
break;
case '/':
if(y==0){
printf("ERROR\n");
return 0;
}
answer=x/y;
break;
default:
printf("ERROR\n");
return 0;
}
printf("答え:%d\n",answer);
}
}
}
左辺に×、÷が来ても優先的に計算されません。
![](http://oshiete.xgoo.jp/images/v2/common/profile/M/noimageicon_setting_04.png?a65a0e2)
No.4ベストアンサー
- 回答日時:
どこまでの道具が使えるのかどうかにはよりますが、雰囲気からすれば、2項の「電卓」はコードがあるようですね。
これを、3項に拡張する場合、だらだらとコードを付け加えてゆくよりは、今ある部分を機能的に独立させる方が見通しは良くなります。
たとえば、こんな感じ。
int calc2term(int a, char op, int b)
{
// a op b の値を返す
}
int comp_op(char op1, char op2)
{
// op1 と op2 優先順序を確認する
// op1 が優先なら、-1 を
// op2 が優先なら、1 を
// 優先順序が同じなら 0 を返す。
}
int main()
{
int answer;
// ここまでで、z, y,z op1, op2 が入力されたものとする
if (comp_op(op1, op2) == 1) // 特別扱いするのは、op2 のほうが優先順序が高いときだけ
{
answer = calc2term(y, op2, z);
answer = calc2term(x, op1, answer);
// op2 のほうが優先順位が高いので x op1 (y op2 z) を計算する。
}
else // それ以外の時は、op1 op2 の優先順序が同じ時も含めて、左から順に計算すればいい
{
answer = calc2term(x, op1, y);
answer = clac2term(answer, op2, z);
// (x op1 y) op2 z を計算する
}
// answer の値を表示する。
return 0;
}
この回答への補足
回答ありがとうございます。
3項だけの計算で出来ました。
さらに質問で申し訳ありませんが、以下のプログラムを基に3項だけの計算を2項以上10項以下で可能にしたいのですが、アドバイスをお願いします。
以下に参考のプログラムを貼り付けます。
#include <stdio.h>
#include <stdlib.h>
int calc(int a, int b, int op)/*計算を行ってる関数*/
{
int answer;
switch(op){
case '+':
answer=a+b;
break;
case '-':
answer=a-b;
break;
case '*':
answer=a*b;
break;
case '/':
if(b==0){
printf("0で割ることは出来ません\n");
exit(1);
}
answer=a/b;
break;
default:
printf("ERROR\n");
exit(1);
}
return answer;
}
int main(void)
{
int answer; /*答え*/
int x,y,z; /*x=第一項,y=第二項,第三項*/
char op1,op2; /*演算子1、演算子2*/
while(1){
printf("式を入力してください\n");
printf("式:");
scanf("%d %c %d %c %d" ,&x,&op1,&y,&op2,&z);
if(((op1=='+') || (op1=='-')) && ((op2=='*') || (op2=='/'))) /*右辺と左辺の計算の優先順位の判断*/
{
answer = calc(y, z, op2);/*右辺を初めに計算*/
answer = calc(x, answer, op1);/*右辺の計算後に左辺を計算*/
printf("答え:%d\n",answer);
}
else
{
answer = calc(x, y, op1);/*左辺を計算*/
answer = calc(answer, z, op2);/*右辺を計算*/
printf("答え:%d\n",answer);
}
}
return 0;
}
![](http://oshiete.xgoo.jp/images/v2/common/profile/M/noimageicon_setting_04.png?a65a0e2)
No.5
- 回答日時:
No.4 です。
残念ながら、この方針では3項限定でしか処理ができません。
まず、入力からして、数字が3つであることを前提にしていますね。
これ以上項数を増やすためには、「繰り返し」または、「再帰」という仕掛けを導入する必要があります。
※その意味では、No.4 の回答も、柔軟性を欠くものです。
なので、知るべき事は多く、簡単なアドバイスでどうにかなるというレベルではない気がします。
とりあえず、一度配列に読み込んで、乗除算の部分だけ前もって計算して別の配列に移し、最後に加減の計算をするという方針で作ってはみました。
紙の上に、式を書いて何をやっているか追いかけてみれば、流れはわかると思います。
あと、入力の最後は、= です。 1+2*3+4= とか。
int main()
{
int num[10];
char op[10];
int numCount;
int num_wk[10];
char op_wk[10];
int wkCount;
int i;
int j;
int result;
int wk;
int leftTerm;
int rightTerm;
op[0] = '+';
scanf("%d", &num[0]);
for(i = 1; i < 10; i++)
{
scanf("%c", &op[i]);
if (op[i] == '=') break;
scanf("%d", &num[i]);
}
for(j = 0; j < i; j++)
printf("%c %d\n", op[j], num[j]);
// 計算開始
numCount = wkCount = 0;
while(1)
{
if ((op[numCount + 1] != '*') && (op[numCount + 1] != '/'))
{ // 優先順序を意識する必要は無い
op_wk[wkCount] = op[numCount];
num_wk[wkCount] = num[numCount];
numCount++;
wkCount++;
}
else
{
// 優先順序を意識する(乗除の部分を項として計算する)
op_wk[wkCount] = op[numCount]; // 項の前の符号を最初に保持
wk = num[numCount];
numCount++;
while((op[numCount] == '*') || (op[numCount] == '/')) // 次の項が始まるまで
{
wk = calc(wk, num[numCount], op[numCount]);
numCount++;
}
num_wk[wkCount] = wk;
wkCount++;
}
if(op[numCount] == '=') break;
}
printf("--------------------------------\n");
// ここまでで、乗除は部分的に計算されて、wk_num, wk_op に確保されている
for(i = 0; i < wkCount; i++)
{
printf("%c %d\n", op_wk[i], num_wk[i]);
}
// 最終の計算
printf("--------------------------------\n");
result = 0;
for(i = 0; i < wkCount; i++)
{
result = calc(result, num_wk[i], op_wk[i]);
}
printf("Answer = %d", result);
return 0;
}
No.3
- 回答日時:
こまかく見てないけど
> if((op1=='+'|'-'|'*'|'/') && (op2=='+'|'-'|'*'|'/')){
PHPかなんかで正規表現の経験があるんですかね?
でも、C言語で、しかも、条件式として使うなら間違っています。
| 一つはビット毎のorを計算します。
'+'|'-'|'*'|'/' だと、
+を表わす文字コード or -を表わす文字コード or *を表わす文字コード or /を表わす文字コード
になります。
この書き方でするなら
((op1=='+') || (op1=='-' ) || (op1=='*' ) || (op1=='/' ))
とする必要があります。(わかりやすくするために括弧を付けました。)
他にもstrchrを使うとか方法はあります。
で、このifが成りたつときに、y○z を先に計算するようですけど
今までは条件が異常だったので、真になることが無く、全部x△yを先に計算していましたが、上の修正をすると、op1,op2の全ての組合せで真になるので、逆に、x△yを先に計算することがなくなります。
どちらを先に計算するのか、もう一度、条件をよく考えてみましょう
No.2
- 回答日時:
> 左辺に×、÷が来ても優先的に計算されません。
そんなコードは書かれていないので、当然です。
また、
> if((op1=='+'|'-'|'*'|'/') && (op2=='+'|'-'|'*'|'/')){
このコードは、あなたが意図してる動作とは違うと思います。
No.1
- 回答日時:
C言語はものすごく大昔にやったので文法的な間違いは指摘できません。
まず
if((op1=='+'|'-'|'*'|'/') && (op2=='+'|'-'|'*'|'/')){
の部分ですが、これですとop1,op2が+-*/のどの組み合わせでも
後ろのyとzの計算をしてしまうと思います。
条件的には[op1が+もしくは-]かつ[op2が*もしくは/]であれば
後ろのyとzの計算を優先する、としなければいけないと思います。
また、上の条件に当てはまらない場合のルートではxとyの計算のみを行って
zの計算が抜けているのでそれも追加する必要があると思います。
さらにanswerがint型であるため割り算のときに割り切れない数字の組み合わせですと
なにやら不都合が出ると思われます。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# c言語の問題です 3 2023/01/10 16:15
- C言語・C++・C# カードシャッフルのブログラムを使ってc言語でブラックジャックをしたい 2 2022/04/12 15:13
- C言語・C++・C# プログラミングの授業の課題です 1 2023/01/17 22:15
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
- JavaScript jsで、switch文で書かれた分をif文にできませんか。 1 2022/07/28 15:10
- C言語・C++・C# C++のcase文の書き方 4 2023/02/24 20:50
- Excel(エクセル) 2つのVBAを一緒にしたら機能しなくなりました(エクセル) 7 2022/06/02 12:41
- JavaScript switch文のswitch(n)の部分を複数の値にするか、if文に変えてほしいです。 1 2022/07/27 17:18
- C言語・C++・C# C言語のエラーについて 2 2022/07/11 13:56
- JavaScript セレクトボックスを2つ設けて選択して初めてメッセを表示 1 2022/07/27 12:15
このQ&Aを見た人はこんなQ&Aも見ています
-
見学に行くとしたら【天国】と【地獄】どっち?
みなさんは、一度だけ見学に行けるとしたら【天国】と【地獄】どちらに行きたいですか? 理由も聞きたいです。
-
何回やってもうまくいかないことは?
みなさんには、何回やってもうまくいかないことはありますか?
-
今の日本に期待することはなんですか?
目まぐるしく、日本も世界も状況が変わる中、あなたが今の日本に期待することはなんですか?
-
あなたなりのストレス発散方法を教えてください!
自分なりのストレス発散方法はありますか?
-
一番好きなみそ汁の具材は?
みんなで大好きなみそ汁の具材について語り合おうよっ!
-
C言語で電卓を作成する。修正お願いします。
C言語・C++・C#
-
switch文を使った四則演算 どこかおかしいです
C言語・C++・C#
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・一番好きなみそ汁の具材は?
- ・泣きながら食べたご飯の思い出
- ・「これはヤバかったな」という遅刻エピソード
- ・初めて自分の家と他人の家が違う、と意識した時
- ・いちばん失敗した人決定戦
- ・思い出すきっかけは 音楽?におい?景色?
- ・あなたなりのストレス発散方法を教えてください!
- ・もし10億円当たったら何に使いますか?
- ・何回やってもうまくいかないことは?
- ・今年はじめたいことは?
- ・あなたの人生で一番ピンチに陥った瞬間は?
- ・初めて見た映画を教えてください!
- ・今の日本に期待することはなんですか?
- ・集中するためにやっていること
- ・テレビやラジオに出たことがある人、いますか?
- ・【お題】斜め上を行くスキー場にありがちなこと
- ・人生でいちばんスベッた瞬間
- ・コーピングについて教えてください
- ・あなたの「プチ贅沢」はなんですか?
- ・コンビニでおにぎりを買うときのスタメンはどの具?
- ・おすすめの美術館・博物館、教えてください!
- ・【お題】大変な警告
- ・洋服何着持ってますか?
- ・みんなの【マイ・ベスト積読2024】を教えてください。
- ・「これいらなくない?」という慣習、教えてください
- ・今から楽しみな予定はありますか?
- ・AIツールの活用方法を教えて
- ・最強の防寒、あったか術を教えてください!
- ・歳とったな〜〜と思ったことは?
- ・モテ期を経験した方いらっしゃいますか?
- ・好きな人を振り向かせるためにしたこと
- ・スマホに会話を聞かれているな!?と思ったことありますか?
- ・それもChatGPT!?と驚いた使用方法を教えてください
- ・見学に行くとしたら【天国】と【地獄】どっち?
- ・これまでで一番「情けなかったとき」はいつですか?
- ・この人頭いいなと思ったエピソード
- ・あなたの「必」の書き順を教えてください
- ・14歳の自分に衝撃の事実を告げてください
- ・人生最悪の忘れ物
- ・あなたの習慣について教えてください!!
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
#if 1 #elseの意味について
-
構文エラー";"が型の前にあり...
-
C言語の二分法のプログラムにつ...
-
配列を関数に渡す方法
-
プログラミングで二番目に大き...
-
VHDLで、case文とwhen文のどち...
-
販売金額の合計などを求める問題
-
C言語で、2007年度が残り何日か...
-
scanf関数を用いての加減乗除%...
-
初歩的なC言語に関する質問です...
-
for文の中にswitch文はいれられ...
-
Aの値からBの値を除するとは??
-
エクセルで可視セルにのみ値貼...
-
信頼区間の1.96や1.65ってどこ...
-
マイナスからプラスへ転じた時...
-
「指定されたキャストは有効で...
-
DWORDの実際の型は何でしょうか
-
C言語での引数の省略方法
-
複数桁10進数の*桁目だけを抽出...
-
【gcc・cygwin】multiple defin...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
構文エラー";"が型の前にあり...
-
#if 1 #elseの意味について
-
for文の中にswitch文はいれられ...
-
配列を関数に渡す方法
-
getcの改行判定
-
プログラム
-
C言語階乗の総和を求める
-
for文について
-
C言語の二分法のプログラムにつ...
-
配列を使って魔方陣
-
VHDLで、case文とwhen文のどち...
-
初心者です。for文、if文を使っ...
-
C言語でのトランプシャッフルに...
-
全角文字の判定
-
C言語初心者です。次の問題で質...
-
10進数からN進数に変換するプロ...
-
C言語プログラムが理解できなくて…
-
c言語のwhile文を使った計算で...
-
scanf関数を用いての加減乗除%...
-
1からnまでの和を求めるプログ...
おすすめ情報