• ベストアンサー

関数について

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の値を求めたら、何の値になるのでしょうか? これらについて、解説をお願いいたします。

  • choobn
  • お礼率62% (121/194)

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

  • ベストアンサー
  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.3

★なぜ? ・『aのb乗を計算している』っていうのは『beki』関数の『ans=ans*a;』の式を解読すると分かります。 ・まず、最初に『ans=1;』で『ans』変数を初期化していますね。まず、ここが重要です。 ・そして、『ans=ans*a;』の式ですが、これは前回の『ans』に『a』の数を掛けたものを『ans』変数に  また、代入していますよね。これを分かりやすくするためにfor文の繰り返し動作を下に表示します。 ●beki(2,3);のとき、a=2、b=3ですよね。 (1)ans=1; ←最初の初期化 (2)ans=ans * a; ←ans=1 * 2 (3)ans=ans * a; ←ans=2 * 2 (4)ans=ans * a; ←ans=4 * 2 ←b=3 なので3回ループしますよね。 (5)つまり、(((1×2)×2)×2)となるわけですよ。分かりますか? ●beki(3,4)のとき、a=3、b=4ですよね。 (1)ans=1; ←最初の初期化 (2)ans=ans * a; ←ans=1 * 3 (3)ans=ans * a; ←ans=3 * 3 (4)ans=ans * a; ←ans=9 * 3 (5)ans=ans * a; ←ans=27 * 3 ←b=4 なので4回ループしますよね。 (6)つまり、(((1×3)×3)×3)×3)となるわけですよ。分かりますよね。 回答: ・よって、上記の (((1×2)×2)×2) や (((1×3)×3)×3)×3) の動作は、『a』を『b』回掛け算を  する仕組みが『beki』関数の『ans=ans*a;』の式です。 ・これは、b=3 のとき a×a×a となったり、b=4 のとき a×a×a×a となるため『aのb乗』って事に  なります。分かりますか?→『a』を『b』の数だけ掛け算します。これが『aのb乗』ってことだよ。 最後に: ・繰り返し文の処理は、初期値の値と、その後の処理を紙やメモ帳に書き出して探ると  分かりやすくなります。→そのうち、『頭』の中でできる様になります。イメージの問題ですね。 ・以上。解説終わり。参考になったか感想を下さいな。それでは、さようなら。

choobn
質問者

お礼

a,bが、beki(2,3)やbeki(3,4)に対応してることがわかったので、計算も理解できました。 回答ありがとうございました。

その他の回答 (2)

  • venzou
  • ベストアンサー率71% (311/435)
回答No.2

疑問に思ったら、printfなどで変数の内容を表示してみましょう。 改造例: int beki(int a, int b) { int i,ans; printf("beki(%d,%d)が呼ばれました\n",a,b); ans=1; for(i=1; i<=b; i++) { ans=ans*a; printf("forループで計算中 i = %d ans = %d \n",i,ans); } printf("beki(%d,%d)の結果は %d です\n",a,b,ans); return ans; } 改造の結果 beki(2,3)が呼ばれました forループで計算中 i = 1 ans = 2 forループで計算中 i = 2 ans = 4 forループで計算中 i = 3 ans = 8 beki(2,3)の結果は 8 です 8 beki(3,4)が呼ばれました forループで計算中 i = 1 ans = 3 forループで計算中 i = 2 ans = 9 forループで計算中 i = 3 ans = 27 forループで計算中 i = 4 ans = 81 beki(3,4)の結果は 81 です 81

choobn
質問者

お礼

回答ありがとうございました。

  • edomin
  • ベストアンサー率32% (327/1003)
回答No.1

「なぜaのb乗を計算しているのでしょうか?」 ansの初期値は1です。 それに、aをb回掛けている(for文で1からbまで回している)ので、aのb乗になります。 8=2^3(2の3乗) 81=3^4(3の4乗) 最初にbeki(2,3)で a=2;b=3 になり 2回目のbeki(3,4)で a=3;b=4 になるので、それぞれの計算が出力されます。

choobn
質問者

お礼

a,bが、beki(2,3)やbeki(3,4)に対応してることがわかったので、計算も理解できました。 回答ありがとうございました。

関連するQ&A

  • 2次元配列を引数とする関数について

    2次元配列を引数とする関数について 私は今、2次元配列を引数とする関数の表を作るという課題に取り組んでいます。 条件として、int a[数字][数字]={{1,2,3...}}という配列の宣言と同時の初期化は使わず、 関数内で表の値を代入し、値を表示する関数を作り、事実上二つの関数を作るというものです。 私は以下のようなプログラムを作り、動かしましたが、[数字][数字]=********のような本来 あるべき実行結果とは異なる数字の羅列が出てきてしまいました。 ↓ #include <stdio.h> void func(int a[][6]); void fund(int b[4][6]); void main(void) { int a[4][6]; fund(a); func(a); } void func(int a[][6]) { int i,j,b[4][6]; fund(b); for(i=0;i<4;i++)        { for(j=0;j<6;j++) { printf("a[%d][%d]=%d\n",i,j,a[i][j]); printf("\n"); } } } void fund(int b[4][6]) { int i,j; for(i=0;i<4;i++) { for(j=0;j<6;j++)          { scanf("b[%d]*[%d]=%d\n",&i,j,b[i][j]); } } } 本来の実行結果 1 2 3 4 5 6 2 4 6 8 10 12 3 6 9 12 15 18 4 8 12 16 20 24 紙にも書いて何回も見直しましたが、どこがおかしいのかわかりませんでした。 どうすれば良いのでしょうか? 何か良いアドバイスをよろしくお願いします。

  • cプログラム

    #include<stdio.h> /*Calc MAX of (a,b)*/ int max(int x,int y) { if(x>y) return x; else return y; } /*Calc n!*/ void fact(int n) { int i,ans; ans=1; for(i=n;i>=1;i--){ ans*=i; } printf("ans=%d\n",ans); } /*END*/ void end() { printf("Thanks\n"); exit(0); } /*Main*/ int main() { int key; int a,b,saidai; int n; while(1){ puts("\n=====Main MENU ====="); puts("1.......max(a,b)"); puts("2.......n!"); puts("9.......END\n"); printf("Input No(1,2,9)=?"); scanf("%d",&key); switch(key){ case 1: printf("Inputs:a,b?"); scanf("%d,%d",&a,&b); saidai=max(a,b); //Call max(a,b) printf("max(%d,%d)=%d\n",a,b,saidai); break; case 2: printf("Input:n?"); scanf("%d",&n); fact(n); break; case 9: end(); break; default: printf("!!!!!Miss Input_No!!!!!\n"); break; } } のプログラムなのですが、1の処理を行った場合max(a,b)の値が正しく表示されません どこを直せばいいでしょうか? return(0);

  • 配列のプログラミングを作ったのですが「

    問題:10問の計算問題を解いて、以下のような成績表を表示するプログラムを作成せよ 例) 第一問 ○ 第二問 × 第三問 × ・・・ 自分が作った解答)#include<stdio.h> #include<stdlib.h> void main() { int a,b,ans,i; int seikai=0; int huseikai=0; int kaitou[10]; srand((unsigned)time(NULL)); printf("暗算\n"); for(i=0;i<10;i++); { printf("%問\n",i+1); a=rand()%10; b=rand()%10; printf("%d+%dは?\n",a,b); scanf_s("%d",&ans); if(ans==a+b) kaitou[i+1]=seikai; else kaitou[i+1]=huseikai; } for(i=0;i<10;i++) { printf("第%d問",i+1); if(kaitou[i+1]==seikai) printf("○\n",seikai); else printf("×\n",huseikai); } } のように作成したのですが、コンパイルは成功しますが思い通りの解答になりません。 どこが間違っているのか指摘してください。

  • 配列の疑問。

    もうすぐC言語のテストがあるので適当に自分で問題を作って プログラムを作る練習をしていたのですが配列の所でちょっと疑問に思いました。 問題 ひとつずつ数字を入力していき、それまでの数字の合計と平均を求めるプログラム。 0を入力するとプログラム終了(配列、ポインタ、関数を用いること) #include <stdio.h>    int wa(int *a,int b); main() {    int a[10],ans,i=0,c;    double ave=0,j;    while(1)    {      scanf("%d",&a[i]);      c=a[i];      i++;      if(c==0){         exit(1);      }      ans=wa(&a[0],i);      printf("合計%d\n",ans);      j=i;      ans=wa(&a[0],i);      ave=ans/j;      printf("平均%lf\n",ave);      printf("計算回数%d回\n",i);    } } int wa(int *a,int b) {    int ans=0,i;    for(i=0;i<b;i++){      ans+=*(a+i);    }    return ans; } このようなプログラムで一応自分の期待通りには動いてくれたのですが、 こういう「0」を入力しない限り終わらないプログラムのときに配列を利用すると どれぐらい領域を取っておくかがわからないんですよ。 今回はa[10]としてますが、結局10しか確保してないから10回しか入力できないかな? っと思って実行してみますが普通に10回以上でもエラーがでることもなく実行できるんですよね。 これはなぜでしょうか? 私の配列の考え方がまちがっているのでしょうか?

  • 高速フーリエ変換に関すること

    皆様、こんばんわ。 今日は、お聞きしたいことが会ってここに質問しにきました。 まず、こちらを見てください。 これは、「毎回異なる計算結果を、順次足していく」、 そのための練習用プログラムです。 #include<stdio.h> int main(void){ int i,j; int z[3]={0}; int a[5]={1,2,3,4,5}; int b[5]={5,4,3,2,1}; for(i=0;i<3;i++){ for(j=0;j<5;j++) Z[i] += a[j]*b[j]; if (i==1) z[i]=z[1] else (i>1) z[i]+z[i-1] } printf("a = {%d,%d,%d,%d,%d}\n",a[0],a[1],a[2],a[3],a[4]); printf("b = {%d,%d,%d,%d,%d}\n",b[0],b[1],b[2],b[3],b[4]); for(i=0;i<3;i++) printf("z[%d] = %d\n",i,z[i]); return(0); } 流れとしては、 (1)2つの配列の各要素の積の計算をする。 (2)そして、計算して出た積(全部で5つ)を足す。 (3) (1)~(2)の計算を繰り替えす。 (但し、1回目以降は前回の計算結果を足す) そして最終的に、 a[5] = {1,2,3,4,5} b[5] = {5,4,3,2,1} Z1 = 35 Z2 = 70 Z3 = 105 という結果を出力したいんです。 ですが、どうしてもエラーが起きて実行できません。 たぶんですが、if-else文の辺りが違うと思うのですが・・・。 どういう風に変更したらいいのでしょうか? ちなみに使っているコンパイラVidualC++2008です。 OSはVistaです。

  • 関数化について

    何度も質問しているんですがまた行き詰ってしまいました 以前解答をいただき自分なりに進めていき以下のことができるようになりました 1、多項式の係数を入力し、多項式(A)をつくる。 2、それを微分したもの(A’)で割る。→A÷A’=商・・・余りB 3、出てきた余り(B)を割る数、ひとつ前の作業で割る数だったもの(A’)を割られる数にする。 4、割る数(B)の最高次の係数の2乗をしたもの(a^2)を割られる数(A’)にかける。(擬除法) 5、割り算を行う。→(a^2)×A’÷B 6、余りが0になるまで3~5を繰り返す。(0にならなければ終わり) 7、割り切れたときの割る数がAとA’の最大公約数Dとなる(正確には最大公因数?) とここまでできるようになりました。 で、次にさらにまた 8、A÷D=E 9、DとEでユークリッドの互除法により最大公約数Gを求める 10、E÷G=P→PがAのi次の平方因子 11DをAとしDが無平方になるまで1~10を繰り返す。 といったことをやらなければいけないんですが、 いい加減関数を使わないと長すぎるので同じ作業を簡略化するため関数化することにしました。 で、微分のプログラムは関数化できたんですが、ユークリッドの互除法のプログラムが難しくて関数化できません。 わかる方お願いしますm(_ _)m 以下プログラム #include <stdio.h> #include <math.h> int main(void){ int m,m2,i,j,k,l,n,p,q; int a[1000],b[1000],c[1000],d[1000],e[1000]; puts("何次の多項式ですか?"); printf("何次:"); scanf("%d",&m); puts("多項式の係数を入力してください。"); for(i=m;i>=0;i--){ scanf("%d",&a[i]); //e[i]=a[i]; //printf("e[i]=%d\n",e[i]); } derivative(&m,a,&m2,b); printf("微分された多項式は:"); for(i=m2;i>=0;i--){ printf("%dx^%d+ ",b[i],i); } printf("\n\n"); q = 1; l = 0; while(q == 1){ printf("割られる数は:"); for(i=m;i>=0;i--){ a[i]=a[i]*(b[m2]*b[m2]); printf("%dx^%d + ",a[i],i); } q = 0; printf("\n上のは割る数の最高の次数の係数の2乗をかけたもの:b[m2]=%d\n",b[m2]); printf("--\n"); printf("%d回目の商は\n",l+1); for(k=m-m2;k>=0;k--){ c[k] = a[m - (m - m2 - k)] / b[m2]; printf("%dx^%d + ",c[k],k);//商の表示 j = m2; for(i = m - (m - m2 - k);i>= m - (m - m2 - k) - m2 ;i--){ d[i]=a[i]-c[k]*b[j]; a[i] = d[i]; j = j - 1; } } printf("\n"); for (k = m2;k >=0 ;k--){ a[k] = b[k]; } printf("余り:"); for (k = m2-(m-m2);k >=0 ;k--){ b[k] = d[k]; printf("%dx^%d + ",b[k],k); if (d[k] != 0){ q = 1; } } for (k = 0;k <= 1000;k++){ d[k] = 0; } printf("q:%d\n",q); p = m2 - 1; m = m2; m2 = p; l = l + 1; printf("\n"); while(b[m2] == 0){ m2 = m2 - 1; } if (m2 <= 0){ break; } } if (q == 0){ printf("割り切れた"); }else{ printf("割り切れなかった"); } return(0); } int derivative(int *m, int a[],int *m2, int b[]) { int i; for(i=*m;i>0;i--){ b[i-1]=i*a[i]; } *m2=*m-1; return(0); }

  • 行列の積を関数を使って求める・・?

    2つの行列の行と列を入力し、積を計算するプログラムを関数を使って書きたいのですが、上手く行きません。どこをどのように直したらよいか教えてください!お願いします!! 以下が私が書いたプログラムです。 #include<stdio.h> #define NUMBER 10 int first(int x1,int x2,int y1,int y2,int i,int j,int k) { int a[NUMBER][NUMBER] = {0}; int b[NUMBER][NUMBER] = {0}; int c[NUMBER][NUMBER] = {0}; do{ printf("2つの行列の行と列を入力してください\n"); scanf("%d", &x1); scanf("%d", &x2); scanf("%d", &y1); scanf("%d", &y2); if(x1 != y2){ printf("行列の積は計算できません\n"); } }while(x1 != y2); printf("行列Aの要素を入力してください\n"); for(i=0; i<x1; i++){ for(j=0; j<x2; j++) scanf("%d", &a[i][j]); } printf("行列Bの要素を入力してください\n"); for(j=0; j<y1; j++){ for(k=0; k<y2; k++) scanf("%d", &b[j][k]); } } int second(int x1,int x2,int y1,int y2,int i,int j,int k) { int a[NUMBER][NUMBER] = {0}; int b[NUMBER][NUMBER] = {0}; int c[NUMBER][NUMBER] = {0}; for(i=0; i<x1; i++){ for(k=0; k<y2; k++){ for(j=0; j<x2; j++) c[i][k] = c[i][k] + a[i][j]*b[j][k]; } } for(i=0; i<x2; i++){ for(k=0; k<y2; k++) printf("%3d", c[i][k]); printf("\n"); } } int main(void) { int a[NUMBER][NUMBER] = {0}; int b[NUMBER][NUMBER] = {0}; int c[NUMBER][NUMBER] = {0}; printf("行列の積を計算します\n %d\n", first(x1,x2,y1,y2,i,j,k)); printf("行列Aと行Bの積は\n %3d",second(x1,x2,y1,y2,i,j,k)); }

  • C言語の関数の定義について質問します

    struct monster{ int type; /* タイプ */ char trick[25]; /* 技 */ char trick2[25]; /* 技2 */ int tricktype; /* 技1のタイプ */ int tricktype2; /* 技2のタイプ */ int trickeffect; /* 技1の威力 */ int trickeffect2; /* 技2の威力 */ char name[10]; /* 名前 */ int power; /* 攻撃力 */ int diffence; /* 防御力 */ int speed; /* 素早さ */ int HP; /* 体力 */ /* 1,fire 2,water 3,nature 4,thunder 5,wind */ }; main(){ int a[2][3]; struct monster monster[5] = { { 1, "a", "b", 1, 2, 120, 80, "v", 60, 60, 60, 100}, { 2, "a", "b", 2, 3, 120, 80, "w", 60, 60, 60, 100}, { 3, "a", "b", 3, 4, 120, 80, "x", 60, 60, 60, 100}, { 4, "a", "b", 4, 5, 120, 80, "y", 60, 60, 60, 100}, { 5, "a", "b", 5, 1, 120, 80, "z", 60, 60, 60, 100}, }; struct monster monster2[5] = { { 1, "a", "b", 1, 2, 120, 80, "v", 60, 60, 60, 100}, { 2, "a", "b", 2, 3, 120, 80, "w", 60, 60, 60, 100}, { 3, "a", "b", 3, 4, 120, 80, "x", 60, 60, 60, 100}, { 4, "a", "b", 4, 5, 120, 80, "y", 60, 60, 60, 100}, { 5, "a", "b", 5, 1, 120, 80, "z", 60, 60, 60, 100}, }; inputmonster(a, monster); printf("これからバトルを開始します\n\n"); printf("player1は%sをくりだした。\n", monster[a[0][0]-1].name); printf("player2は%sをくりだした。\n", monster2[a[1][0]-1].name); battle(a); return 0; } void inputmonster(int x[][3], struct monster monster) { int i, s, t, m, n; for(t = 0; t < 2; t++){ s = 0; while (s < 1){ printf("player%dは好きなモンスターを3つ選んでください\n\n", t+1); for (i = 0; i<3; i++){ printf("%d体目を選んでください。\n\n", i+1); for(m = 0; m < 5; m++) printf("%d, %s\n", m+1, monster[m].name); scanf("%d", &x[t][i]); printf("%d体目 : %s\n\n", i+1, monster[x[t][i]-1].name); } printf("これでよろしいですか?\n"); for(i = 0; i<3; i++) printf("%d体目 : %s ", i+1, monster[x[t][i]-1].name); printf("1、はい 2、いいえ\n"); scanf("%d", &n); if(n == 1) s = 1; else s = 0; } } } 上記のようにプログラムをコンパイルしたところ、 monsterbattle.c: 関数 ‘inputmonster’ 内: monsterbattle.c:497:63: エラー: 添字が付けられた値が、配列、ポインタまたはベクト ルではありません for(m = 0; m < 5; m++) printf("%d, %s\n", m+1, monster[m].name); ^ monsterbattle.c:499:45: エラー: 添字が付けられた値が、配列、ポインタまたはベクト ルではありません printf("%d体目 : %s\n\n", i+1, monster[x[t][i]-1].name); ^ monsterbattle.c:503:68: エラー: 添字が付けられた値が、配列、ポインタまたはベクト ルではありません for(i = 0; i<3; i++) printf("%d体目 : %s ", i+1, monster[x[t][i]-1].na me); というような結果が返ってきました。 どうやら定義がうまくなっていないようなのですが、どこを改善すればうまく動くようになるのでしょうか? お手数ですが、よろしくお願いいたします。

  • 2進→10進数

    2進数から10進数に変換するプログラムを作りたいんですが #include<stdio.h> main() { int a[8],i=0,ans=0,end; start: printf("2進数を10進数に変換するプログラム\n開始する場合は1を入力終了する場合は0を入力してください。\n"); scanf("%d",&end); if(end==1) { goto s1; } else if(end==0) { goto end; } { s1: for(i=0;i<8;i++) { scanf("%d",&a[i]); } for(i=0;i<8;i++) { a[i]=2^i; } for(i=0;i<8;i++) { ans=ans+a[i]; } printf("二進数"); for(i=8;i<=4;i--) { printf("%d",a[i]); } printf(" "); for(i=4;i<=0;i--) { printf("%d",a[i]); } printf("は%dです。\n",ans); goto start; } end: printf("終了します\n"); } 期待した結果が得られないのですがどこが違っているのか教えていただきたいです、お願いします。

  • C言語プログラム 配列

    C言語プログラム初心者です。以下のプログラムに対して、実行結果がなぜそうなるかがわからないので、詳しく教えてください。 #include<stdio.h> int func(int a[ ],int b[ ],int n); main(){ int i,k; static int a[12] ={1,2,3,4,5,(省略)・・・,12};  static int b[12] ={21,22,23,24,(省略)・・・,32}; k = func(a,b,6); k = func(b+3,a+3,6); printf("a = "); for(i=0;i<12;i++)printf("%d",a[i]); printf("\n = b"); for(i=0;i<12;i++)printf("%d",b[i]); printf("\n k = %d\n",k); } int func(int a[ ],int b[ ],int n){ int i,x=0; for(i=0;i<n;i++);{ a[i] = b[i]; x = x+a[i]; } return(x); } 結果: a = 21 22 23 .... 26 7 8 9 10 11 12 b = 21 22 23 .... 26 7 8 9 30 31 32 k = 99

専門家に質問してみよう