• ベストアンサー

小町算

#include<stdio.h> #define KETA 9 #define SIN_SU 3 #define GOOD 100 int next(int symbol[]); void int_set(int symbol[]); void myprint(int symbol[]); int check(int symbol[]); main() { int symbol[KETA]; int_set(symbol); do{ if(check(symbol)) myprint(symbol); }while(next(symbol)); } int next(int symbol[]) { int i=KETA; do { if(++symbol[i]<SIN_SU) return symbol; symbol[i]=0; }while(i--); return 0; } void int_set(int symbol[]) { int i; symbol[0]=1; for(i=1;i<KETA;i++) symbol[i]=0; } void myprint(int symbol[]) { int i; for(i=0;i<KETA;i++) { if(symbol[0]==1) ; else if(symbol[i]==1) printf("+"); else if(symbol[i]==2) printf("-"); printf("%d",i+1); } } int cheak(int symbol[]) { int num=0; int result=0; int i; for(i=0;i<KETA;i++) { if(symbol[i]==0) num=10*num+(i+1); else{ if(symbol[i]==2) { result+=-1*num; num=i+1; } else { result+=symbol[i]*num; num=i+1; } } } if(result==GOOD) return 1; else return 0; } このプログラムの関数nextのところのreturn symbolが 思うとおりに動きません。どなたか教えていただけないでしょうか?

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

  • ベストアンサー
回答No.5

No.2 です。 > いろいろと修正しましてコンパイルできるようになったのですが答えが3つずつ出てしまいます。原因がわかりません・・。どうしてでしょうか? int* next(int symbol[]) { int i=KETA - 1; が正解です。 ここ以外のところでは、symbol[0] から symbol[KETA - 1] までを使っていますよね? symbol[KETA] は、そのさらにひとつ下の桁です。 なので、この桁があふれるまで3回分かかるのです。 int symbol[KETA] で確保して、symbol[KETA] にアクセスすると、良くないことがおきそうですが、たまたま運良く(運悪く)実害が見えなかったのでしょう。

h9well3
質問者

お礼

いろいろとありがとうございます!無事コンパイルできました!

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

その他の回答 (4)

noname#30727
noname#30727
回答No.4

#3です。 訂正します。 >1~9の数字を for (i = 1; i <= KETA; i++) などのループで処理する事を考えると、symbol[0]を使用しない方が自然な形になるかもしれません。 これは無かった事にして下さい(笑

すると、全ての回答が全文表示されます。
noname#30727
noname#30727
回答No.3

小町算は123456789の数字の間に空白または演算記号を入れるって事ですよね? そうすると、int symbol[KETA]; は int symbol[KETA-1]; と宣言するか、symbol[0]またはsymbol[KETA-1]は使用しない事になると思います。 1~9の数字を for (i = 1; i <= KETA; i++) などのループで処理する事を考えると、symbol[0]を使用しない方が自然な形になるかもしれません。 問題のnext関数ですがsymbolを返す必要はありません。symbolに1を加える典型的な方法を記しておきます。(要素数はKETAとしています) int next(int symbol[]) { int a = 1, i, n; for (i = 0; i < KETA; i++) { n = symbol[i] + a; symbol[i] = n % SIN_SU; a = n / SIN_SU; } return !a; }

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

int next(int symbol[]) { int i; symbol[KEKA]++; for (i = KETA; (i >= 2) && (symbol[i] >= SIN_SU); i--) { symbol[i] = 0; symbol[i - 1] ++; } if (symbol[0] != 1) return 0; return 1; } こんな感じでしょうか。(チェックしていません) 気持ちとしては、 ・9個の配列に なにもない、+、-をそれぞれ配置する。 ・この配列を更新するのが楽なように、それじれ、0, 1, 2にした。 ・100100100 なら、1+234+567 (でも、これだと、9桁めが0だと問題ですね) ・問題の next は、今の符号配置から次の符号配置を計算する。これを、3進数の多桁演算でやってみた。 ・多桁演算をして、桁がオーバーフローしなかったら配列を返す という感じですね。 まず、配列は、特殊な事情による、実質参照渡しになります。このため、関数側でいじった内容はそのまま帰ります。従って明示的に配列を返す必要はありません。(そもそも、next が返すのは、int のはず) また、もとの書き方では、「1桁でもOKの桁があれば直ちに終了」しますし、さらに、繰り上がりもしていません。 (その桁が3に達したら、その桁を0にしているだけで、次の桁をインクリメントしていない) というところでしょうか。 あと、「思うとおりに動きません」というのは、通常実行してみたら、動きがおかしいというレベルで使います。 もとのソースは、多分、コンパイルが通っていませんよね。 あと、特に check() の計算は面倒そうですね。

h9well3
質問者

補足

いろいろと修正しましてコンパイルできるようになったのですが答えが3つずつ出てしまいます。原因がわかりません・・。どうしてでしょうか? #include<stdio.h> #define KETA 9 #define SIN_SU 3 #define GOOD 100 #define TRUE 1 #define FALSE 0 int* next(int symbol[]); void int_set(int symbol[]); void myprint(int symbol[]); int check(int symbol[]); main() { int symbol[KETA]; int_set(symbol); do{ if(check(symbol)) myprint(symbol); }while(next(symbol)); } int* next(int symbol[]) { int i=KETA; do { if(++symbol[i]<SIN_SU) return symbol; symbol[i]=0; }while(i--); return 0; } void int_set(int symbol[]) { int i; symbol[0]=1; for(i=1;i<KETA;i++) symbol[i]=0; } void myprint(int symbol[]) { int i; for(i=0;i<KETA;i++) { if(symbol[i]==1) if(i==0); else printf("+"); else if(symbol[i]==2) printf("-"); printf("%d",i+1); } printf(" = %d\n",GOOD); } int check(int symbol[]) { int num=0; int result=0; int tmp=0; int i; for(i=0;i<KETA;i++) { if(symbol[i]==0) num=10*num+(i+1); else{ if(tmp==2) { result+=-1*num; tmp=symbol[i]; num=i+1; } else { result+=tmp*num; tmp=symbol[i]; num=i+1; } } } if(tmp==2) result +=-1*num; else result += tmp*num; if(result==GOOD) { return TRUE; } else return FALSE;

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

next関数の返り値を while(next(symbol)) と使っている所を見ると、0か非0(と言うか、TRUEかFALSE)を返すべき関数として作ったのですよね? なのに、何故 return symbol; などと「配列へのポインタ」を返そうとするのか、理解に苦しみます。 (ぶっちゃけ、何がしたいのか、理解に苦しみます) 「呼び出し元での関数の呼び方」と「関数が返すべき返り値」の整合性が取れておらず、全体の設計が出来ていないと思われます。 フローチャート図の書き方など、プログラムの設計方法の基礎から習得し直すべきです。

h9well3
質問者

お礼

返信ありがとうございます!まだ勉強をはじめたばかりで見苦しくて申し訳ありません。 next関数は100000000~222222222までを調べる関数なのです。これは1が+,2が-,0が何もないと思って内部データをあらわしています。そして最下位から1ずつインクリメントして調べようという関数のつもりで作りました。そこでreturnで配列を返すことによってこの範囲の中ならループを続けるとしたかったのです。 説明も下手で申し訳ありません。もう一度考え直してみます!ありがとうございました!

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

関連するQ&A