再帰プログラムで合ってるのか間違ってるのか

このQ&Aのポイント
  • 関数zeromade()を作ってプログラムを完成させよ。
  • プログラムは与えられた値から、0までを順に出力するものである。
  • リカーシブ(再帰)プログラムで作成すること。
回答を見る
  • ベストアンサー

再帰プログラムで合ってるのか間違ってるのか

関数zeromade()を作ってプログラムを完成させよ。 プログラムは与えられた値から、0までを順に出力するものである。 例えば、5を入力したら、 5 4 3 2 1 0 と出力されるものである。 ただし、リカーシブ(再帰)プログラムで作成すること。 (つまりfor文やwhile文は出てこない。) main内部を変更してはならない。 という問題があり #include <stdio.h> #include <stdlib.h> int zeromade(int); int main() { int n; scanf("%d", &n); if (n < 3) { fprintf(stderr, "3 ijou no atai wo nyuuryoku site kudasai\n"); exit(1); } zeromade(n); exit(0); } int zeromade(int x) { if(x < 0){ ; }else{ printf("%d\n",x); return (x * zeromade(x-1)); } } とやってこれが正解なのか不正解なのかわからないので質問させていただきます コンパイルすると 5を入力 5 4 3 2 1 0 と出ます 足りないことがあれば補足で説明します

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

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

実は、再帰を理解するには(少なくとも飲み込むには)ある程度の「いい加減さ」が必要です。 再帰というのは、一種の魔法ですから。 さて、どう書いてあるのかはわかりませんが、とにかく、zeromade(int n) という関数があります。 これは、例えば、 zeromade(5); に対して、 5, 4, 3, 2, 1, 0 という出力をする関数です。 これは、5 を出力したあと、 4, 3, 2, 1, 0 と出力するものです。 で、5 の後の、4, 3, 2, 1, 0 は、要するに、 zeromade(4); の動きです。 つまり、 zeromade(n) は、 ・ n を出力する ・ zeromade(n - 1) を呼び出す (ただし、以上の動作をするのは、n >= 0 のときだけ) という動きをすればいいわけです。 で、何かを返すという必要はおそらくないわけです。 そういう関数を、普通に作ってみれば良いです。

izupawapuro
質問者

お礼

#include <stdio.h> #include <stdlib.h> void zeromade(int); int main() { int n; scanf("%d", &n); if (n < 3) { fprintf(stderr, "3 ijou no atai wo nyuuryoku site kudasai\n"); exit(1); } zeromade(n); exit(0); } void zeromade(int x) { if(x <= 0){ ; }else{ printf("%d\n",x); zeromade(x * zeromade(x-1)); } } コンパイルしたら通りました。 5 4 3 2 1 0 うーん・・・C言語って複雑ですね。

izupawapuro
質問者

補足

#include <stdio.h> #include <stdlib.h> void zeromade(int); int main() { int n; scanf("%d", &n); if (n < 3) { fprintf(stderr, "3 ijou no atai wo nyuuryoku site kudasai\n"); exit(1); } zeromade(n); exit(0); } void zeromade(int x) { if(x <= 0){ ; }else{ printf("%d\n",x); zeromade(x * zeromade(x-1)); } } コンパイルしたら通りました。 5 4 3 2 1 0 うーん・・・C言語って複雑ですね。

その他の回答 (4)

  • asuncion
  • ベストアンサー率33% (2126/6288)
回答No.5

>引数がintできてるのでintで返しました 世の中には、「引数はint型だけど何も返さない」関数とか、 「引数はint型だけどdouble型を返す」関数とか、そういうものがいっぱいあります。 「引数がint型『だから』戻り値もint型にした」というのは、根拠が薄弱です。

izupawapuro
質問者

お礼

回答ありがとうございます

izupawapuro
質問者

補足

>引数はint型だけど何も返さない」関数 前回は携帯からの補足で説明不足でした。 それはvoidでことでいいんでしょうか? intだけどdoubleを返すなど、もちろん専門学校で そういう関数はならってますよ。 根拠といわれても何を根拠にこの説明をすればいいのか私にはわかりません。学校ではそう教えられています

回答No.3

まずは、少なくとも、動きを追ってみましょう。 「0」を出力した後、どういう動きをするのか。 ※0 を出力した、その次の呼び出しでは、関数は値を返さない……ということ。 この関数は、再帰の例として、階乗の計算が出されていたので、そのコードをそのまま使ったら動いてしまったというところでしょうか。 Web の内容は基本的すぎるのか~。 「引数の型」と「関数の型」の違いとか、 「値を返さない関数はどう呼び出すのか」とか、 そのあたりでつまずいているような気がしますが。

izupawapuro
質問者

補足

>この関数は、再帰の例として、階乗の計算が出されていたので、そのコードをそのまま使ったら動いてしまったというところでしょうか。 そういうことだと思います。 そうすると再帰とは・・・?を1から学ばないといけませんよね Webの再帰のプログラムを見たほうがいいのでしょうか? >「引数の型」と「関数の型」の違いとか、 違いはプロトタイプで double a(int,int); でdouble a(double,double)ということでしょうか? >「値を返さない関数はどう呼び出すのか」とか voidのことということでよろしいでしょうか?

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.2

「値を返す」関数で値を返さないことがあるわけだから「正解」とは言えないねぇ.

izupawapuro
質問者

補足

>return (x * zeromade(x-1)); これで返してるつもりですが違うということでしょうか となると別にreturnが必要ということでしょうか

  • asuncion
  • ベストアンサー率33% (2126/6288)
回答No.1

呼び出し元では >zeromade(n); zeromade()の戻り値を使っていないですね。 zeromade()の戻り値の型をintにした理由と、 >return (x * zeromade(x-1)); このように書いた理由を教えてください。 # 何だかnの階乗を計算しているように見える。

izupawapuro
質問者

補足

引数がintできてるのでintで返しました >return (x * zeromade(x-1)); 再帰させるために書いたつもりです 確かに階乗と言われると階乗っぽいですね 根本的に関数を通した再帰というのが理解してないのかもしれません。WEBのは基本すぎて参考にならないので。

関連するQ&A

  • プログラムについてですが・・・

    今、画像処理の最小二乗法のプログラムを作成しているのですが、どうも上手く出力されません。以下のプログラムが、メインのプログラムでして、余分な #include は気にしないでください。画像の表示自体のプログラムは特に問題はありませんでしたので省きました。このプログラムにどんな問題があるか、わかりません。どなたか教えてください。 お願いします。 #include <math.h> #include <windows.h> #include <commdlg.h> #include <memory.h> #include <dos.h> #include <time.h> #include <wchar.h> #include <stdio.h> #include <iostream.h> #include "../DibFile.h" #include "ImageSDK.h" int n,n4,n5,n6,n7,n8,n9 ; double n10,n11 ; int n0[1000],n1[1000],n2[1000],n3[1000] ; n = 0 ; for(y = 0 ; y < h ; y++){   for(x = 0 ; x < w ; x++){ i = x+y*w ; if( *(buff1+i) == 0x00 ){                n0[n] = x ;                n1[n] = y ;                n2[n] = x*x ;                n3[n] = x*y ;                ++n ; } } } n5 = 0 ; n6 = 0 ; n7 = 0 ; n8 = 0 ; n9 = 0 ; for(n4 = 0 ; n4 < n ; n4++){ n5 += n2[n4] ; n6 += n0[n4] ; ++n7 ; n8 += n3[n4] ; n9 += n1[n4] ; } if((n6*n6-n7*n5) != 0){  n10 = ((n9*n6)-(n7*n8)) / ((n6*n6)-(n7*n5)) ;  n11 = (n8-(n5*n10)) / n6 ; for(x = 0 ; x < w ; x++){   y = (int) (n10*x+n11) ;    if(y < h && y > 0){  *(buff1+(x+y*w)) = 0x80 ;    } }

  • 再帰プログラム

    #include<stdio.h> int rstrlen(char*); int main(void) { char str[100]; printf("文字列を入力してください\n"); gets(str); printf("文字数は %d です\n",rstrlen(str)); return 0; } int rstrlen(char *p) { if(*p){ p++; return 1+rstrlen(p); } else return 0; } 文字数を計算するプログラムです。 if(*p)の*pとはNULLを表しているのですか?

  • 再帰呼び出し

    アッカーマン関数の値を出力するプログラム #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); } この関数を呼び出した回数も出力するようにしたいのですが、どうしたらいいのでしょうか?

  • 再帰プログラム

    strに格納されている文字数を数えるプログラムです。 #include<stdio.h> int rstrlen(char *); int main(void) { char str[] = {"abcdefghijk"}; printf("文字数:%d\n",rstrlen(str)); return 0; } int rstrlen(char *p) { if(*p) { p++; printf(p); return 1 + rstrlen (p); } else return 0; } return 1 + rstrlen (p);の部分で再帰をし1をプラスすることにより文字数をカウントしmainのprintfで文字数を表示しているのですがカウントしている値はどこに格納していてどのようにmainに返しているのかが分かりませんでした。教えてください。

  • C言語<素数を求めるプログラム>

    #include<stdio.h> int j; int prime(int n) { int i; if(n < 2) return 0; if(n == 2) return 1; if(n%2 == 0) return 0; for(i = 3; i*i<= n; i += 2){ if(n%i == 0) return 0; } return 1; } int main(void) { int n; for(n=1; n <= 1000; n++) { if(prime(n)){ printf("%d\n",n); j++; } } printf("素数の個数は全部で %d 件見つかりました。\n",j); return 0; } このプログラムは1から1000までの素数のみを表示させるプログラムでありますが、このアルゴリズムが全くわかりません。 int prime(int n)の中身のアルゴリズムがどういう仕組みになっているのかお分かりになりますでしょうか?

  • 大文字を小文字に、小文字を大文字にするプログラム

    問題は、 ファイルにあるアルファベットの大文字を小文字に変換し、小文字は大文字に変換して、ファイルに保存するプログラムを作りなさい というものです。 色々考えて、 #include <stdio.h> #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> #include <stdlib.h> #include <unistd.h> #include <ctype.h> int main(int argc,char **argv){ int fd,flag1,flag2; int i,n; char buffer[512],x; fd = open(argv[1],O_RDWR); if(fd == -1) perror("open"); while((n = read(fd,buffer,sizeof(buffer)))>0){ x = buffer[i]; flag1 = islower(x); flag2 = isupper(x); for(i=0;i<n;++i) if(flag1 == 1){ buffer[i] = toupper(buffer[i]); }else if(flag2 == 1){ buffer[i] = tolower(buffer[i]); } write(fd,buffer,n); } close(fd); exit(0); } のようなプログラムを考えましたが、うまくいきません。 toupperのような関数を使ったのは初めてなのでよく使い方が分からずこのようなプログラムになってしまいました。 どうか正しく動くようなプログラムを教えてください。お願いします。

  • c言語初心者です

    うまくできません C言語プログラム初心者です 問題で 関数sub()を作ってプログラムを完成させよ。 この関数は、第1引数で与えられた引数の配列の要素の、 第2引数から第3引数までの要素の合計の値を返すものである。 例えば、0と0を入力したら結果は1、3と4を入力したら、16となる ものである。 main内部のfprintf文のxxxxxxxxxxxxxxxxxxxxxxxxの部分には、 エラーの意味が分かるようにエラーメッセージを書いておくこと。 #include <stdio.h> #include <stdlib.h> #define BUFMAX 12 int sub(int [],int,int); int main() { int a[BUFMAX], start, end; a[0] = 1; a[1] = 3; a[2] = 5; a[3] = 7; a[4] = 9; a[5] = 11; a[6] = 2; a[7] = 4; a[8] = 6; a[9] = 8; a[10] = 10; a[11] = 12; scanf("%d", &start); scanf("%d", &end); if (start < 0 || start >= BUFMAX) { fprintf(stderr, "start no atai ga okasii desu.\n"); exit(1); } if (end < 0 || end >= BUFMAX) { fprintf(stderr, "end no atai ga okasii desu.\n"); exit(1); } if (end < start) { fprintf(stderr, "xxxxxxxxxxxxxxxxxxxxxxxxxxx.\n"); exit(1); } printf("%d\n", sub(a, start, end)); exit(0); } int sub(int a[],int start,int end) { int atai atai = a[start]+a[end]; return atai; } if文で同じ値の場合・・・などと考えたのですが、手付かずです よろしくお願いします

  • 合ってるのか合ってないのか。C言語

    これで正解なのかどうなのか・・・ 関数sub()を作ってプログラムを完成させよ。 この関数は、第1引数で与えられた引数の配列の要素の、 第2引数から第3引数までの要素の合計の値を返すものである。 例えば、0と0を入力したら結果は1、3と4を入力したら、16となる ものである。 main内部のfprintf文のxxxxxxxxxxxxxxxxxxxxxxxxの部分には、 エラーの意味が分かるようにエラーメッセージを書いておくこと。 0と0入力したら2だと思うのですが、これは問題のミスでしょうか コード↓ #include <stdio.h> #include <stdlib.h> #define BUFMAX 12 int sub(int [],int,int); int main() { int a[BUFMAX], start, end; a[0] = 1; a[1] = 3; a[2] = 5; a[3] = 7; a[4] = 9; a[5] = 11; a[6] = 2; a[7] = 4; a[8] = 6; a[9] = 8; a[10] = 10; a[11] = 12; scanf("%d", &start); scanf("%d", &end); if (start < 0 || start >= BUFMAX) { fprintf(stderr, "start no atai ga okasii desu.\n"); exit(1); } if (end < 0 || end >= BUFMAX) { fprintf(stderr, "end no atai ga okasii desu.\n"); exit(1); } if (end < start) { //fprintf(stderr, "xxxxxxxxxxxxxxxxxxxxxxxxxxx.\n"); fprintf(stderr,"start ga end yori ookii no de error desu.\n"); exit(1); } printf("%d\n", sub(a, start, end)); exit(0); } int sub(int a[],int start,int end) { int i,atai; for(i=0;i<BUFMAX;i++) { atai = a[start]+a[end]; } return atai; }

  • 素数のプログラムについて教えてください

    3000000以下の素数を降順に表示するプログラムをつくりたいのですが、int mainのところがわかりません。 #include <iostream> int PRIME(int m) int main() { int m, j; for(m = 3000000; m <= 2; m--) } int prime( int n ) { int i; for ( i = 2; i < n; i++ ) { if ( n % i == 0 ) { return 0; } } return 1; } 誰か教えていただけないでしょうか? よろしくお願いします。

  • 二分法のプログラムについて

    下の用なプログラムを作ったのですがどうしても正しい答えを導くことができません。自分でもいろいろ調べてみましたがわかりません。誰かご教授宜しくお願いします。 #include<stdio.h> #include<stdlib.h> #define MAX 10 int n , count; double c[MAX+1]; double a,b,e; void nyuuryoku(void) { int i; printf("nの入力>"); scanf("%d",&n); if(n>MAX){printf("最大次数を超えている");exit(1);} else if(n<0){printf("nが負");exit(2);} else{for(i=0;i<=n;i++){printf("係数の値>");scanf("%lf",&c[i]);} }} double f(double x) {double y; int i; y = c[0]; for(i=1;i<=n;i++){ y=y*x+c[i];} return y; } void hani(void){ printf("aの値>");scanf("%lf",&a); printf("bの値>");scanf("%lf",&b); printf("eの値>");scanf("%lf",&e); if(e<=0){printf("eが0または負"); exit(3);} if(f(a)==0){printf("%f",f(a)); exit(4);} if(f(b)==0){printf("%f",f(b)); exit(5);} if(f(a)*f(b)>0){printf("初期値異常"); exit(6);}} double nibun(void) {double c; if(b>a){ while(b-a>e){ count++; c=(a+b)/2; if(f(c)==0){ return c;} if(f(a)*f(c)<0){b=c;} if(f(b)*f(c)<0){a=c;} } return a;} if(a>b){ while(a-b>e){ count++; c=(a+b)/2; if(f(c)==0){ return c;} if(f(b)*f(c)<0){a=c;} if(f(a)*f(c)<0){b=c;} } return a;} } void syutsuryoku(double x){ printf("x=%lf\n",x); printf("f(x)=%lf\n",f(x)); printf("繰り返し回数=%d\n",count); } int main(void){ double ans; count=0; nyuuryoku(); hani(); ans = nibun(); syutsuryoku(ans); }

専門家に質問してみよう