アプリ版:「スタンプのみでお礼する」機能のリリースについて

答えを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;
}

A 回答 (5件)

 こんにちは。



 早速のお礼ありがとうございます。

 この問題は“+、-のみ”等の規制をどんどん外していくことで
難易度がだんだん上がっていきます。
そして自分で問題を設定して考えていくことは、演習問題をただこなして
いくよりも何倍もの価値があります。

 最初は難しいかもしれませんが、頑張って是非解決してください。
プログラミングへの自信と実力が必ずつきます。
    • good
    • 0
この回答へのお礼

c言語を勉強し始めて1年、プログラミングに向いていないのかと正直自信をなくすこともありますがそう言っていただけるととてもやる気が出ます。
とりあえず今は目先の小町算を解くことに集中してみますね。

ありがとうございました。

お礼日時:2009/02/03 19:38

「数式を評価するルーチン」を使ってみた。



#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);
}
}
}
}
}
}
}
}
}
    • good
    • 0
この回答へのお礼

数式を評価するルーチンというものがあるんですね…。
ルーチンの意味が分からず辞書で探してしまうくらい勉強が足りない私ですが、早くこんなプログラムが組めるように頑張ります。
参考にさせていただきますね。
回答ありがとうございました。

お礼日時:2009/02/03 19:35

 こんにちは。



 質問の題名は“C言語で小町算”とか“小町算”にしてください。
閲覧するかどうか、見る人がすぐに判断できますので。

 私だったら設計からやり直します。掛け算、割り算に対応できないからです。
今のソースはあくまで左から演算できることが前提となっています。

 設計する前に、まず手計算をする場合の基本を考えます。
 パッと考えた結果、以下の規則が思い浮かびました。
 ・基本的に左から演算する
 ・×、÷>+、-
 ・カッコがあった場合はカッコ内を先にする

 これを元に考えて以下の処理の流れにします。
 1.数値と演算子に分ける
 2.演算子に順位を付ける
 3.順位の高い演算子から演算を行う

 通常はカッコを付けないと思いますが、付けても順位を上げることで
対処が可能だと思います。
あとは処理を細かくしてソースを書けば終わりです。

 ご参考までに。
    • good
    • 0
この回答へのお礼

ご指摘ありがとうございます。
次回から気をつけます。

私の説明不足で申し訳ありません。
足し算・引き算のみの計算での小町算です。
しかしとても参考になりました。
今のプログラムが完成したら掛け算・割り算の小町算も作ってみようと思います。
ありがとうございました。

お礼日時:2009/01/27 15:46

>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] は定義範囲の外です。
こういった点を含めて、

>最初から組み直した方がよいのでしょうか…

そのとおりだと思います。
    • good
    • 0
この回答へのお礼

指摘されるまで気づきませんでした。
行き当たりばったりで組んでいたのもあり、お恥ずかしいかぎりです。
やはり最初から組み直してみますね。
ありがとうございました。

お礼日時:2009/01/27 15:43

次のページを参考にしてみたら?



http://www.sra.co.jp/people/miyata/algorithm/kom …
    • good
    • 0
この回答へのお礼

一度ネットで検索してそのページも見たのですが、自分のやり方と全く違うようでしたのでその時はあまり読まなかったのです…。
やはり自分だけではできないので一度しっかり読んでみますね。
ありがとうございました。

お礼日時:2009/01/27 15:40

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!