- 締切済み
c言語
答えを0にするこまち算のプログラムを組んでみたのですが、ここからどうしても進まなくなってしまいました。 自分ではいけるかなと思ったのですが、9-8-7+65-4321=9など答えがありえない数になってしまいます。 どこがいけないか教えてください。むしろ最初から組み直した方がよいのでしょうか… #include <stdio.h> int cul(); int num[9] ={9,8,7,6,5,4,3,2,1}; int total;/**/ int kigou[8]={0,0,0,0,0,0,0,0}; int main(){ for(kigou[0]=0;kigou[0]<3;kigou[0]++){ for(kigou[1]=0;kigou[1]<3;kigou[1]++){ for(kigou[2]=0;kigou[2]<3;kigou[2]++){ for(kigou[3]=0;kigou[3]<3;kigou[3]++){ for(kigou[4]=0;kigou[4]<3;kigou[4]++){ for(kigou[5]=0;kigou[5]<3;kigou[5]++){ for(kigou[6]=0;kigou[6]<3;kigou[6]++){ for(kigou[7]=0;kigou[7]<3;kigou[7]++){ keisan(); } } } } } } } } return 0; } int keisan(){ int n =0; int flag = 0; int t = 0; int i = 0; total = num[0]; /* for (n=0;n<9;n++) printf("kigou[%d] == %d",n,kigou[n]);確かめ*/ for(;n<8;n++){ if(kigou[n] == 0 && n == 0){ total = total * 10 + num[n+1]; for(flag=1;kigou[n+flag]==0 && (n+flag)<9 ;flag++){ total = total * 10 + num[n+flag+1]; } n = n + flag; } flag=0; if(kigou[n]!= 0){ for(flag=1;kigou[n+flag]==0 && (n+flag)<9 ;flag++){ t = num[n+1] * 10 + num[n+flag+1]; } n = n+ flag; total = total + t; } } /*0になる計算式の表示*/ kigou[8]=2;/*表示しないために空白を入れる*/ if(total==0){ for(i=0;i<9;i++){ printf("%d",num[i]); if(kigou[i]==0) printf("+"); if(kigou[i]==1) printf("-"); if(kigou[i]==2) printf(""); } printf("=%d\n",total); } return 0; }
- みんなの回答 (5)
- 専門家の回答
みんなの回答
こんにちは。 早速のお礼ありがとうございます。 この問題は“+、-のみ”等の規制をどんどん外していくことで 難易度がだんだん上がっていきます。 そして自分で問題を設定して考えていくことは、演習問題をただこなして いくよりも何倍もの価値があります。 最初は難しいかもしれませんが、頑張って是非解決してください。 プログラミングへの自信と実力が必ずつきます。
- chie65536(@chie65535)
- ベストアンサー率44% (8740/19838)
「数式を評価するルーチン」を使ってみた。 #include <stdlib.h> #include <stdio.h> #include <string.h> double expr(char *buf,char **p); double expr3(char *buf,char **p) { double a; *p=buf; while (**p == ' ') (*p)++; a=strtod(*p,p); while (**p == ' ') (*p)++; return a; } double expr2(char *buf,char **p) { double a; *p=buf; switch (**p) { case '(': while (**p == ' ') (*p)++; a=expr(++(*p),p); while (**p == ' ') (*p)++; if (**p==')') (*p)++; return a; case '+': return expr(++(*p),p); case '-': return -1.0 * expr(++(*p),p); } return expr3(*p,p); } double expr1(char *buf,char **p) { double a,b; *p=buf; while (**p == ' ') (*p)++; a=expr2(*p,p); for(;**p;) { while (**p == ' ') (*p)++; switch (**p) { case '*': b=expr2(++(*p),p); a*=b; continue; case '/': b=expr2(++(*p),p); a/=b; continue; } break; } return a; } double expr(char *buf,char **p) { double a,b; *p=buf; while (**p == ' ') (*p)++; a=expr1(*p,p); for(;**p;) { while (**p == ' ') (*p)++; switch (**p) { case '+': b=expr1(++(*p),p); a+=b; continue; case '-': b=expr1(++(*p),p); a-=b; continue; } break; } return a; } void main(void) { double ans; int i,o1,o2,o3,o4,o5,o6,o7,o8; char str[] = {"9 8 7 6 5 4 3 2 1\0"}; char ope[] = {" +-*/"}; char buf1[256]; char buf2[256]; char *p,c; strcpy(buf1,str); for (o1 = 0;o1 < 5;o1++) { buf1[1] = ope[o1]; for (o2 = 0;o2 < 5;o2++) { buf1[3] = ope[o2]; for (o3 = 0;o3 < 5;o3++) { buf1[5] = ope[o3]; for (o4 = 0;o4 < 5;o4++) { buf1[7] = ope[o4]; for (o5 = 0;o5 < 5;o5++) { buf1[9] = ope[o5]; for (o6 = 0;o6 < 5;o6++) { buf1[11] = ope[o6]; for (o7 = 0;o7 < 5;o7++) { buf1[13] = ope[o7]; for (o8 = 0;o8 < 5;o8++) { buf1[15] = ope[o8]; for (i = 0,p = buf2;;i++) { c = *p = buf1[i]; if (c != ' ') p++; if (c == '\0') break; } ans = expr(buf2,&p); if (*p) printf("%s以降が構文エラー\n",p); if (ans == 0.0) printf("%s=0\n",buf2); } } } } } } } } }
お礼
数式を評価するルーチンというものがあるんですね…。 ルーチンの意味が分からず辞書で探してしまうくらい勉強が足りない私ですが、早くこんなプログラムが組めるように頑張ります。 参考にさせていただきますね。 回答ありがとうございました。
こんにちは。 質問の題名は“C言語で小町算”とか“小町算”にしてください。 閲覧するかどうか、見る人がすぐに判断できますので。 私だったら設計からやり直します。掛け算、割り算に対応できないからです。 今のソースはあくまで左から演算できることが前提となっています。 設計する前に、まず手計算をする場合の基本を考えます。 パッと考えた結果、以下の規則が思い浮かびました。 ・基本的に左から演算する ・×、÷>+、- ・カッコがあった場合はカッコ内を先にする これを元に考えて以下の処理の流れにします。 1.数値と演算子に分ける 2.演算子に順位を付ける 3.順位の高い演算子から演算を行う 通常はカッコを付けないと思いますが、付けても順位を上げることで 対処が可能だと思います。 あとは処理を細かくしてソースを書けば終わりです。 ご参考までに。
お礼
ご指摘ありがとうございます。 次回から気をつけます。 私の説明不足で申し訳ありません。 足し算・引き算のみの計算での小町算です。 しかしとても参考になりました。 今のプログラムが完成したら掛け算・割り算の小町算も作ってみようと思います。 ありがとうございました。
- asuncion
- ベストアンサー率33% (2127/6289)
>for(flag=1;kigou[n+flag]==0 && (n+flag)<9 ;flag++){ >total = total * 10 + num[n+flag+1]; >} n+flag は 最大 8 になる場合があるのですね。ということは、 num[n+flag+1] は num[9] にアクセスする場合がありますね。 ところが、 >int num[9] ={9,8,7,6,5,4,3,2,1}; num[8] までしかありません。num[9] は定義範囲の外です。 こういった点を含めて、 >最初から組み直した方がよいのでしょうか… そのとおりだと思います。
お礼
指摘されるまで気づきませんでした。 行き当たりばったりで組んでいたのもあり、お恥ずかしいかぎりです。 やはり最初から組み直してみますね。 ありがとうございました。
- cametan_42
- ベストアンサー率62% (162/261)
次のページを参考にしてみたら? http://www.sra.co.jp/people/miyata/algorithm/komachi.txt
お礼
一度ネットで検索してそのページも見たのですが、自分のやり方と全く違うようでしたのでその時はあまり読まなかったのです…。 やはり自分だけではできないので一度しっかり読んでみますね。 ありがとうございました。
お礼
c言語を勉強し始めて1年、プログラミングに向いていないのかと正直自信をなくすこともありますがそう言っていただけるととてもやる気が出ます。 とりあえず今は目先の小町算を解くことに集中してみますね。 ありがとうございました。