• ベストアンサー

助けてください・・・

大学のプログラミングの講義で試験があり、以下の設問がありました。 次のプログラムのprintf文で何が表示されるか? #include<stdio.h> int pow2_a (int); int main (void) { printf("\n%d\n", pow2_a(12)); return 0; } int pow2_a (int n) { int p=1; if (n>0) { int tmp, m; m = n/2; printf("-- call pow2_a(%2d)\n", m); tmp = pow2_a(m); if (n%2==0) { p = tmp*tmp; } else { p = tmp*tmp*2; } } printf("-- return%8d\n", p); return p; } この答えが以下のようになるようです。   -- call pow2_a( 6) -- call pow2_a( 3) -- call pow2_a( 1) -- call pow2_a( 0) -- return 1 -- return 2 -- return 8 -- return 64 -- return 4096 そこで「--return 1 」と書いてあるところまでは分かるのですが、これ以下の表示が何故こうなるか理解できません。 お分かりの方教えてください。m(__)m

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

  • ベストアンサー
  • Dxak
  • ベストアンサー率34% (510/1465)
回答No.3

#2です ごめんです 勘違い・・・ > if (n>0) { n=0で、この中が処理されず > -- return 1 が、戻ってくるのね > -- call pow2_a( 6) ↑call pow2_a(12)で、呼び出された処理 > -- call pow2_a( 3) ↑call pow2_a(6)で、呼び出された処理 > -- call pow2_a( 1) ↑call pow2_a(3)で、呼び出された処理 > -- call pow2_a( 0) ↑call pow2_a(1)で、呼び出された処理 > -- return 1 ↑call pow2_a(0)で、呼び出された処理 > -- return 2 ↑call pow2_a(1)で、呼び出された処理 > -- return 8 ↑call pow2_a(3)で、呼び出された処理 > -- return 64 ↑call pow2_a(6)で、呼び出された処理 > -- return 4096 ↑call pow2_a(12)で、呼び出された処理 と、言う話になります

その他の回答 (2)

  • Dxak
  • ベストアンサー率34% (510/1465)
回答No.2

すみません 再帰の問題だとは、思うのですが・・・ > m = n/2; なので、2行前の > if (n>0) { で、nにマイナスが来ることが考えられないのですが・・・ プログラムの記載は、間違ってませんか? > -- return 1 のところが、出てくることは無く > tmp = pow2_a(m); が、m=0で、呼び続けて無限ループに入ってしまうような気がしてます プログラムの記載確認、お願いできませんか? 私のほうの勘違いなら、良いのですが・・・

  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.1

--- return 1 で戻るのは tmp = pow2_a(m); の代入文です 1が返されるのは pow1_aの引数nが0のときでありこの呼び出し行った時点でのnは3だということが-- call pow2_a(0)の前の出力から判断出来ます となると この後のif文の条件は不成立になり temp = temp * temp * 2 = 2*2*2 = 8 となります このように順に--- call pow2_aの引数とif文を順次照らしていけばこの出力の意味がわかると思います 命令を実行される順に書き出し その時点での変数の値を書き出しながら確認してみましょう Excelなどの表計算ソフトで A列に命令、B列にそのときの変数の値 サブルーチン(関数)に移行したら2列右に記入 関数から戻ったら2列左にもどる といった表を作ってみましょう

関連するQ&A

  • 組み合わせ

    n個の集合からp個を取る組み合わせの総数を出力するプログラムなんですが nCp=n!/p!(n-p)!という式を使い #include<stdio.h> int kaijo(int m); int comb(int n,int p); int main(void) { int i,j; printf("n="); scanf("%d",&i); printf("p="); scanf("%d",&j); printf("comb(%d,%d)=%d\n",i,j,comb(i,j)); } int kaijo(int m) { if(m>0) return(m*kaijo(m-1)); else return 1; } int comb(int n,int p) { if(n>0) return((n*kaijo(n-1))/(p*kaijo(p-1)*(n-p)*kaijo(n-p-1))); else return 1; } と書いてみたのですがこれではnが大きいとC言語のint型で扱える最大値を超えてしまい正しい結果が出力されません。  そこでint型を使ったままでnやpが大きい場合でもある程度出力できるようにしたいのですがどう改良したらよいのでしょうか? おそらくnCp=n*(n-1)*・・・*(n-p+1)/p!という式を使うのですがよく分かりません。よろしくお願いします。

  • 構造体のメンバ変数が途中で変化してしまう

    下にあるプログラムでコメントが書いてある部分の"Tmp->x"の値が途中で期待していない変化をします。何回も見ても特に操作していないと見てしまいますが、構造体変数の扱い方がおかしいのでしょうか? struct zahyo *MpCalculate(struct zahyo *P,int a,int multiple,int prime) { struct zahyo *kp,*Tmp; int i,u,r; kp=(struct zahyo*)malloc(sizeof(struct zahyo)); kp->x=P->x; kp->y=P->y; if(multiple == 1) return kp; u=myu(P,a,prime); kp->x=x3_PequalQ(P->x,u,prime); kp->y=y3(P,kp,u,prime); if(multiple == 2) return kp; printf("2Py(%d,%d)\n",kp->x,kp->y); //P≠Q for(i=3; i<=multiple; i++){ /*Tmp->xを表示させているDの部分で値が期待しない変化をします*/ Tmp=kp; A: printf("A:Tmp->x=%d\n",Tmp->x); r=rmd(Tmp,P,prime); B: printf("B:Tmp->x=%d\n",Tmp->x); kp->x=x3_PnotQ(Tmp,P,r,prime); D: printf("D:Tmp->x=%d\n",Tmp->x); kp->y=y3(Tmp,kp,r,prime); printf("%dPy(%d,%d)\n",i,kp->x,kp->y); } return kp; } int rmd(struct zahyo *P,struct zahyo *Q,int prime) { unsigned int m,n; m=mod(Q->x - P->x,prime); n=mod(Q->y - P->y,prime); exeuclid(m,prime,1,0,0,1); return mod(aa*n,prime); } int x3_PnotQ(struct zahyo *P,struct zahyo *Q,int rmd,int p) { /*ここでもTmp->x(P->x)の値は操作されていません*/ C:printf("C:Tmp->x = %d\n",P->x); return mod((int)pow(rmd,2) - P->x - Q->x,p); } 実行結果 A:Tmp->x=10 B:Tmp->x=10 C:Tmp->x=10 D:Tmp->x=5 常にDの部分で変わってしまいます。 このように変化する原因が分かる方、回答よろしくお願いします。

  • Gaussの消去法のプログラムなんですがこれを利用して、消去法による行

    Gaussの消去法のプログラムなんですがこれを利用して、消去法による行列式の計算プログラムをつくりたいのですが難しくてよくわかりません。。。 教えていただきたいです。 困ってるのでよろしくお願いします。 int gauss(double *x, double *a, double *b, int n) { int i,j,k,m; double tmp,p,sum; for(k=0; k<n-1;k++){ printf("---- Step %d ----\n",k+1); printf("-- before --\n"); for( m = k;m < n;m++){ printf("%lf\n",a[n * m + k]); } printf("-- --\n"); j = pivot(a,n,k); if(j == ERROR) { return ERROR; } else { if(j != k) { for(i=0; i<n; i++){ tmp = a[n*k+i]; a[n*k+i] = a[n*j+i]; a[n*j+i] = tmp; } tmp=b[j]; b[j]=b[k]; b[k]=tmp; } } printf("-- after --\n"); for( m = k;m < n;m++){ printf("%lf \n",a[n * m + k]); } for(i=k+1; i<n; i++){ p=a[n*i+k]/a[n*k+k]; for(j=0; j<n; j++){ a[n*i+j]=a[n*i+j]-p*a[n*k+j]; printf("a[%d %d]=%lf",i,j,a[n*i+j]); } b[i]=b[i]-p*b[k]; printf("b[%d]=%lf\n",i,b[i]); } printf("k=%d\n",k); /*--------------------------------------------------------------------------*/ } /* step 2: 後退代入 */ for(k=n-1; k>=0; k--){ if(fabs(a[n*k+k]) < EPS){ return(ERROR); } sum=0.0; for(j=k+1; j<n; j++){ sum+=a[n*k+j]*x[j]; } x[k]=(b[k] - sum)/a[k*n+k]; } return 0; } int pivot(double *a, int n, int k) { int i,m; double d; /* ピボットの探索 */ m = k; d = fabs(a[k*n+k]); for(i=k+1; i<n; i++){ if(fabs(a[n*i+k]) > d){ m = i; d = fabs(a[n*i+k]); } } if(fabs(d) < EPS) { return ERROR; } else { return m; } }

  • 基本選択法

    宜しくお願いします。 基本選択法のプログラムを書いていますが、コンパイルは通りますが、うまくソートされません。 改良点をご教示ください。 #課題ではありません。 #include <stdio.h> int getMin(int in[], int n, int a); void swap(int *m, int *n); int main(void) {   int a[10] = { 84, 121, 43, 93, 140, 83, 14, 93, 181, 58};   int i, j, k;   for(i=0; i<10; i++){     k = getMin(a, 10, i);     swap(&a[i], &a[k]);     for(j=0; j<10; j++){       printf("a[%d] = %d ", j, a[j]);     }     printf("\n");   }   return 0; } void swap(int *m, int *n) {   int tmp;   tmp = *m;   *m = *n;   *n = tmp; } int getMin(int in[], int n, int a) {   int i, ret, min;   min = in[a];   ret = 0;   for(i = a; i < n; i++)   {     if(in[i] < min){       min = in[i];       ret = i;     }   }   return ret; }

  • 組み合わせ

    aに100、bに20や2を入力すると プログラムが停止します。 計算できるように御指摘お願いします。 以下のプログラムです。 #include<stdio.h> int factrical(int n){ if(n>0){ /*printf("%d\n",n);*/ return (n*factrical(n-1)); } else{ return(1);} } int combination(int n ,int r){ return(factrical(n)/(factrical(n-r)*factrical(r))); } int main (void){ int a,b,c; printf("二つの数を入力してください。\n"); do{ printf("大きい方の数を入力してください。\n"); scanf("%d",&a); scanf("%d",&b); }while(a<b); c=combination(a,b); printf("%d",c); return(0);}

  • アッケルマン関数

    アッケルマン関数 ack(m,n)={ n+1 m=0のとき      { ack(m-1,1) m>0,n=0のとき { ack(m-1,ack(m,n-1)) m>0,n>0のとき をプログラムしたいのですが、再帰を使ったプログラムがうまく実行できません。どこがいけないのでしょうか? #include<stdio.h> int m,n; int ack(int m, int n) { if (m = 0) return n + 1; if ((m > 0) && (n = 0)) return ack(m - 1, 1); else return ack(m - 1, ack(m, n - 1)); } main() { int m,n; printf("アッケルマン関数ack(m,n)を計算します。\n"); printf("自然数m,nを入力してください\n"); scanf("%d",&m); scanf("%d",&n); printf("アッケルマン関数ack(%d,%d)の値は%dです。\n", m, n, ack(m,n)); }

  • 階乗の出力について

    Cを勉強中の者です。再起コールを使った階乗計算の結果を出力するプログラムをつくったのですが、もし再起コール(関数 kaijyo)を使わずにfor文などを使って同じように、階乗計算を行いたい場合どのようにすればいいでしょうか? 以下がそのソースコードです。説明が不足であればまた付け加えますのでよろしくおねがいします。 #include <stdio.h> int kaijyo(int a); int main(void) { int a; a = kaijyo(6); printf("6! = %d\n", a); return 0; } int kaijyo(int n) { if(n == 1) return 1; else return n*kaijyo(n-1); /*これを使わずに6!の結果を出したい/* }

  • CからVB

    以下のプログラムはC言語で作成されています。 これをVBで作成したいです。 教えてください。 #include <stdio.h> #include <stdlib.h> double *alloc(int r,int n,int m); void input(double *p,int r,int n,int m); void sumup(double *p,int r,int n,int m); int main(void){ int r, n, m; double *p; // 行列サイズ入力 printf("input r n m "); scanf("%d %d %d",&r,&n,&m); // 行列領域取得 p = alloc(r,n,m); // 行列要素入力 input(p,r,n,m); // 行列の和 sumup(p,r,n,m); //終了,行列領域解放 free(p); return 0; } double *alloc(int r,int n,int m){ double *p; printf("MATRIX[r=%d][n=%d][m=%d]\n\n",r,n,m); p = (double*)malloc(sizeof(double)*r*n*m); if( p == NULL){ printf("error! malloc failed.\n"); exit(-1); } return p; } void input(double *p,int r, int n,int m) { int i,j,k; for(i = 0; i < r; i++){ for(j = 0;j < n; j++){ for(k = 0; k < m; k++){ printf("input MATRIX[%d][%d][%d]= ",i,j,k); scanf("%lf",&p[i*(n*m)+j*m+k]); } } } printf("\n"); } // 行列の和 void sumup(double *p,int r,int n,int m){ int i, j, k; // 0.0, not 0!!! double sum = 0.0; printf("sum of %d matrices:\n",r); for(j = 0; j< n; j++){ for(k = 0;k < m; k++){ sum=0; for(i = 0;i < r;i++){ sum += p[i*(n*m)+j*m+k]; } printf("\n%2f",sum); } } printf("\n"); }

  • C言語なんですがうまくうごきません。

    X=1においてX^nをm回微分した値を求めるプログラムを作っているのですが、 何度も考えて訂正したりしてるのですが、どこが悪いのかわかりません 再帰関数を使ってます。 デバッグして調べてみてるのですが、うまくいってるようにみえるのですが、最後の値が0になります。 nを大きい値にすると、マイナスになったりするんです。 よくわかりません。 ちなみにnとmは正で、mは10までの数を入力します。 このプログラムの基本形を変えないで問題改善することはできるのでしょうか? わかる人いましたら教えてください。 #include <stdio.h> double differentiate(double n, int m); int main(void) { int a, b; printf("Input 2 number\n"); fflush(stdout); scanf("%d %d", &a, &b); printf( "a = %d\nb = %d\n", a, b ); printf("Answer = %d\n", differentiate(a, b)); return 0; } } double differentiate(double n, int m) { if(m == 1){ return n; }else{ return n * n-1 * differentiate(n-1, m-1); } }

  • 万年カレンダー

    万年カレンダーの日にちが、一日ずれて表示されますのでその原因を教えてください。 void main() { int nen,tuki,niti; int ff,i,n; int carender[6][7]; niti=0; for(i=0;i<6;i++)for(n=0;n<7;n++) carender[i][n]=0; printf("西暦(4桁)→"); scanf("%d",&nen); printf("month:"); scanf("%d",&tuki); ff=youbi_chk(nen,tuki,1); for(i=ff;i<7;i++) {carender[0][i]=niti;++niti;} for(n=1;n<6;n++){ for(i=0;i<7;i++){ if(niti<=niti_chk(tuki,nen)) {carender[n][i]=niti;++niti;}} } printf(" SUN MON TUE WED THU FRI SAT\n"); for(n=0;n<6;n++){ for(i=0;i<7;i++) if(carender[n][i]==0)printf(" ");else printf("%4d",carender[n][i]); printf("\n");} } int youbi_chk(int y,int m,int d) { int youbi; if(m<3) {y--; m+=10;} else {m-=2;} youbi=(y+(y/4)-(y/100)+(y/400)+(13*m-1)/5+d)%7; return youbi; } int uru_chk(int y) { if(y%400==0) return 1; if(y%100==0) return 0; if(y%4==0) return 1; return 0; } int niti_chk(int m,int y) { int hi[12]={31,28,31,30,31,30,31,31,30,31,30,31}; hi[1]+=uru_chk(y); return hi[m-1]; } プロトタイプ宣言は、省いてます。