- 締切済み
再帰
- みんなの回答 (4)
- 専門家の回答
みんなの回答
- Trick--o--
- ベストアンサー率20% (413/2034)
実行される順に a(i){ a(i+1){ ... printf(i+1) } printf(i) } という風に書くと a(0){ a(1){ a(2){ a(3){ a(4){ a(5){ a(6){ a(7){ a(8){ a(9){ a(10){ (ifの条件が偽なのでなにもしない) } printf(9) } printf(8) } printf(7) } printf(6) } printf(5) } printf(4) } printf(3) } printf(2) } printf(1) } printf(0) } これが上から順に実行されるので、最終的な表示が 9876543210 となります
- herbest
- ベストアンサー率42% (15/35)
もっとループ回数を減らして「if ( i < 1 )」ぐらいで 考えてみてはどうですか? もしくは次のように別関数として考えてみるとか。 void a(int i) { if ( i < 2 ){ b ( i + 1 ); printf ( "%d",i ); } } void b(int i) { if ( i < 2 ){ c ( i + 1 ); printf ( "%d",i ); } } void c(int i) { if ( i < 2 ){ printf ( "%d",i ); } } イメージわきました?
お礼
すばやい回答ありがとうございます。 ループの数を減らしてみると、なんとなくイメージがつかめました。 ループ数が増えると、解らなくなりますが。 再帰のなんとなくのイメージは解りました! ありがとうございます。
- crew21
- ベストアンサー率26% (58/222)
No.1さんの仰る通りです。説明上手いなあ。。 再帰ってけっこうイメージしにくくて初心者にはひっかかるところなので、もしNo.1さんの説明で分からないようでしたら、随所にprintf分を入れて実行してみるといいですよ。 例えばa関数に入ってすぐの箇所でprintf("関数に入った iは%d\n", i);とか、関数から抜ける箇所でprintf("関数から抜ける iは%d\n", i);とかやるとプログラムの動きが見えやすくなります。 再帰は一つ間違うとメモリ(スタック)を食いつぶしたりするので、気を付けてくださいね。
お礼
すばやい回答ありがとうございます。 随所にprintf分を入れて実行してみるといいですよ。 これはいいアイデアですね。 いろいろ試してみます。 ありがとうございました。
- rinkun
- ベストアンサー率44% (706/1571)
iが10未満のときprintfは飛び越されるのではなく a(i+1)を実行して帰ってきてから実行されます。 だから a(0), a(1), ..., a(9)ときてa(10)ではa(11)とprintfは実行されず 後は戻りながらa(9)のprintf、a(8)のprintf、と実行されます。 結果として9876543210と表示されることになるわけです。
お礼
すばやい回答ありがとうございます。 よく理解を深めるため参考にさせていただきます。 ありがとうござうました。
関連するQ&A
- 再帰について(C言語)
今、再帰処理を勉強しています。 しかし、以下のプログラムがどうしても理解できません。 流れ的には一体どういう手順になっているのでしょうか? return i * fact( i - 1 )の部分を考えると頭が こんがらがってしまいます。 #include <stdio.h> int main( void ){ printf("5の階乗は %d です", fact(5) ); return 0; } int fact( int i ){ if( i == 1 ) return 1; else return i * fact( i - 1 ); } --------実行結果---------- 5の階乗は 120 です
- ベストアンサー
- C・C++・C#
- 再帰呼び出し
アッカーマン関数の値を出力するプログラム #include void main(void); int ack(int,int); void main(void) { int x,y,i; printf(" data(x) = "); scanf("%d",&x); printf(" data(y) = "); scanf("%d",&y); i = ack(x,y); printf("Ackerman = %d\n",i); } int ack(int a,int b) { int k; if (a == 0) k = b+1; else if (b == 0) k = ack(a-1,1); else k = ack(a-1,ack(a,b-1)); return (k); } この関数を呼び出した回数も出力するようにしたいのですが、どうしたらいいのでしょうか?
- ベストアンサー
- C・C++・C#
- for文~break
break文に達した時、for文から抜けますか?それとも、if { }から抜けるんですか? for文はどこまで影響下にありますか? if ( i==5 ) printf ("サーバーが見つかりません"); まででしょうか? また if ( i == 5 ) で5なら、実行としていますが、 6,や,8など5 以外でも、サーバーが見つかりません と if文が実行される見たいですが、なぜですか? 教えてください。 #include<stdio.h> int main(void) { int array[5][2]={ {1,14}, {2,28}, {3,19}, {4,8}, {5,15}, }; int sever; int i; printf("番号を入力してください"); scanf("%d",&sever); for( i=0 ; i<5 ; i++ ) if ( sever == array[i][0] ){ printf ( "%d 番には, %d 人います。\n",sever,array[i][1]); break; } if (i==5) printf("サーバーが見つかりません"); return 0; }
- ベストアンサー
- C・C++・C#
- 素数 再帰関数
メイン #include<stdio.h> extern void count_primes(void); extern void print_primes(void); int max; int count; int primes[1000] int main(void) { printf("Uper limit: "); scanf("%d",&max); count_primes(); print_primes(); } 素数を求める(関数呼び出し) extern int nextprime(int n); extern int max; extern int count; extern int primes[]; void count_primes(void) { int i; count=0; for(i=2;i<=max;i=nextprime(i)){ primes[count++]=i; } リカーバシブ(次の素数) int nextprime[int n] { int i; for(;;){ n++; for(i=2;i*i<=n;i=nextprime(i)){ if(n%i==0) break; } if(i*i>n) break; } return n; } 素数プリント #include<stdio.h> extern int count; extern int primes[]; void print_primes(void) { int i for(i=0;i<count;i++){ if((i>0)&&(i%10==0) printf("\n"); printf(" %6d",primes[i]); } printf("\n素数の数 %d\n",count); } これら4つのモジュールで素数 nが求められますがアルゴリズム理解できません。この2つの関数のアルゴリズムについて、ご教授ください。め
- 締切済み
- C・C++・C#
- 配列について(C言語)
配列の要素において一番目の要素以外を0にするプログラムを以下のように作成したのですが(while文を*b != 0という条件で作りたい)、while文内のところが間違っているためだと思われるのですが、うまく実行されません(実行しても何も表示されない)。どのようにしたらいいのでしょうか。または、何かが抜けている、ほかの部分が間違っている等もあるためにうまく実行されないということなのでしょうか。 #include <stdio.h> int main(void) { int a[5] = {5, 78, 2, 9, 0}; int i, *b; b = &a[0]; while (*b != 0){ if(*!=a[0]) *ptr=0; else *ptr=a[0]; } for (i = 0; i < 5; i++){ printf("ptr値 =%d ptrアドレス =%p \n", *ptr, ptr); } printf("\n"); return (0); }
- ベストアンサー
- C・C++・C#
- C言語で再帰的処理が出来ない理由
以下のサイトでC言語の勉強をしているのですが、このサイトのソースコードをコピペして実行してみたら上手くいきませんでした。 http://wisdom.sakura.ne.jp/programming/c/c30.html ========================== #include<stdio.h> void func(int ); int main() { func(0); printf("プログラムを終了します"); return 0; } void func(int max) { if (max <= 10000) { printf("%d\r",max); func(max + 1); } } ========================== 実行してみると、何故か4700~4800の辺りで止まってエラーになってしまいます。 どうしてエラーになるのでしょうか?
- ベストアンサー
- C・C++・C#
- 再帰の問題です。
AOJの問題で、C言語で書いています。 ある解答者様のコードが自分の理解に深まると思い、見ているのですが、解答者様の作った関数のところの動作がよくわかりません。 問題です。 http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=0030&lang=jp 解答例です。分かるところ、分からないところを書いていきます。 #include<stdio.h> int n,s,a;//グローバル変数。 void dfs(int i,int sum,int m){//ここでいう、i,sum,mが何を指しているのか分かりません。 if(m==0 && sum==s){a++;return;} if(i==10 || m==0)return; dfs(i+1,sum+i,m-1);/*再帰をしています。しかし、どうしてここに自分と同じ関数を2つ、入れている のか、分かりません。あと、どうしてiを足したり、1引いた数を代入しているのでしょうか?*/ */ dfs(i+1,sum,m); } int main(){ while(scanf("%d%d",&n,&s)!=EOF){//Ctrl+zを押さない限り、無限ループします。 if(n==0 && s==0)break;//問題文通り、2つとも0だったらループを表すwhileから抜けます。 a=0; dfs(0,0,n);//ここもわからないです。ただ、関数dfsの動きが分かれば、分かると思います。 printf("%d\n",a); } return 0; } 再帰は今苦戦していますので、ここでもっと理解を深め、自作関数で使えるようになりたいです。 長文失礼しました。 よろしくお願いします。
- ベストアンサー
- C・C++・C#
- 関数について
C言語の勉強をしているのですが、関数のところがよく理解できません。 ------------------------------ #include <stdio.h> int beki(int a, int b); int main(void) { int n; n=beki(2,3); printf("%d\n",n); printf("%d\n",beki(3,4)); } int beki(int a, int b) { int i,ans; ans=1; for(i=1; i<=b; i++) { ans=ans*a; } return ans; } ---------------------------- 実行結果 8 81 ----------------------------- 上のサンプルで int i,ans; ans=1; for(i=1; i<=b; i++) { ans=ans*a; } の部分は、解説書には「渡されたデータa,bを使って戻り値ansを計算 している」「aのb乗を計算している」などとありましたが、なぜaのb乗を計算しているのでしょうか?実行結果が8と81の何に関係しているのでしょう? ansやa,bの値を求めたら、何の値になるのでしょうか? これらについて、解説をお願いいたします。
- ベストアンサー
- C・C++・C#
お礼
回答どうもありがとうございます。 if条件が偽、 printfで9876543210と戻ってくる所がわかるような、あやふやな感じなんですが、じっくり考えて見ます! ありがとうございました。