プロが教える店舗&オフィスのセキュリティ対策術

#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が
思うとおりに動きません。どなたか教えていただけないでしょうか?

A 回答 (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] にアクセスすると、良くないことがおきそうですが、たまたま運良く(運悪く)実害が見えなかったのでしょう。
    • good
    • 0
この回答へのお礼

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

お礼日時:2005/10/23 10:49

#3です。


訂正します。

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

これは無かった事にして下さい(笑
    • good
    • 0

小町算は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;
}
    • good
    • 0

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() の計算は面倒そうですね。

この回答への補足

いろいろと修正しましてコンパイルできるようになったのですが答えが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;

補足日時:2005/10/22 15:39
    • good
    • 0

next関数の返り値を


while(next(symbol))
と使っている所を見ると、0か非0(と言うか、TRUEかFALSE)を返すべき関数として作ったのですよね?

なのに、何故
return symbol;
などと「配列へのポインタ」を返そうとするのか、理解に苦しみます。
(ぶっちゃけ、何がしたいのか、理解に苦しみます)

「呼び出し元での関数の呼び方」と「関数が返すべき返り値」の整合性が取れておらず、全体の設計が出来ていないと思われます。

フローチャート図の書き方など、プログラムの設計方法の基礎から習得し直すべきです。
    • good
    • 0
この回答へのお礼

返信ありがとうございます!まだ勉強をはじめたばかりで見苦しくて申し訳ありません。

next関数は100000000~222222222までを調べる関数なのです。これは1が+,2が-,0が何もないと思って内部データをあらわしています。そして最下位から1ずつインクリメントして調べようという関数のつもりで作りました。そこでreturnで配列を返すことによってこの範囲の中ならループを続けるとしたかったのです。

説明も下手で申し訳ありません。もう一度考え直してみます!ありがとうございました!

お礼日時:2005/10/21 15:43

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