第5回C言語講座 ~ポインタと配列
今回なにやるか ・ポインタと配列 →前回引き続きポインタを使って配列を弄ります ・乱数 →ランダムな値を取り出す。ゲームなどに応用が 効く便利なものです。
先週の復習(ポインター) ・int* ポインタ変数 (int* aなど) →int型のポインタ変数を宣言している ・&変数 (&aなど) →変数のアドレスを表している、アドレスを渡し たい時などに使用 ・*ポインタ変数(*a など) →ポインタ変数の中身
以上を踏まえて今回は・・・ 配列を導入していきます!
配列とポインターって何か関係あるの? int number[]={0,1,2}; main文の中に上のように配列を定義する。 そこで printf(“%d\n”,*number); と入力してみてください。 すると・・・
・・・前ページの続き “0”が表示された。つまり・・・ *numberはnunber[0]と同義である!
・・・さらに 先程の printf(“%d\n”,*number); の下に printf(“%d\n”,*(number+1)); と入力してみよう。 すると・・・
“0,1“と表示された。 →*(number+1)とはnumber[1]と同じである! 以上をまとめると・・・
配列を用いたポインタ a[b]=*(a+b) まずこれだけは覚えてください!
【応用】こんなこともできます int main(){ int number[3]={1,2,3}; int *p= number; for(int i=0;i<3;i++){ printf(“number[%d]:%d\n”,i,*(number+i)); }
関数に配列を渡す!【重要】 前回、swap(&a,&b)のようにアドレスを関数に渡 すことによってポインタを関数で扱った。 では、今回は配列を関数に渡してみよう!!
不可能です。 配列を渡す!? ・・・と言っても配列をそのまま渡すことは じゃあどうすればいいの? →配列の先頭のアドレスだけなら渡せます!!!
配列の先頭のアドレスの渡し方 ~配列の先頭のアドレスの渡し方~ 関数number()と配列a[]があるとすると number(a) これだけで配列の先頭のアドレスが渡せます!
関数内での配列の使用(ポインタ) void print_number(int number[]){ printf(“number[0]:%d”,number[0]); } int main(){ int number[3]={0,1,2}; print_number(number); 配列の先頭が表示された
また、void numberの中身を下記のように変えて みよう void print_number(int number[]){ for(int i=0;i<3;i++){ printf("number[%d]:%d\n",i,number[i]); }
すると・・・ 関数を使用して配列の中身を表示できた! やったね!
演習1 int number[4]={0,1,2,3} 配列を受け取るswap関数を自作し、上の配列の中 身を逆順にしなさい
解答1 #include <stdio.h> void swap(int a[]){ int i, tmp; printf("swap中・・・\n"); for(i=0;i<4/2;i++){ tmp = a[i]; a[i]=a[4-1-i]; a[4-1-i] = tmp; } int main(){ int number[4]={0,1,2,3}; int i; for(i=0;i<4;i++) printf("number[%d]:%d\n",numb er[i],number[i]); swap(number); return 0;
解答1
【時間あったら】乱数 実用的なプログラムを書く上で必要となるであろ うもののひとつである乱数。読んで字のごとく、 ランダムな数値のことである。 この講座でも何回か触れているが、あえて詳しく 解説してみようと思う。
#include<stdlib.h> 乱数を使用する前に・・・ #include<stdlib.h> まずはこれを導入しよう! ※stdlib・・・Standard libraryのこと、まあ気に しなくて良い
乱数を使用する前に・・・(2) 次に乱数を生成するために必要なSEED値(種) を設定する。 srand(); srandの()の中にSEED値を入れることで乱数の初 期設定となる。
乱数を使用する前に・・・(3) なんでSEED値なんて設定するの? →SEED値を設定するのは乱数を生成するための 初期設定だと思ってください。 SEED値って何? →SEED値が同じだと同じ結果になってしまいま す。SEED値を変えずに何回も生成してみると分 かります。
これだけ! 乱数を生成する 乱数の生成はとっても簡単! #include<stdio.h> #include<stdlib.h> int a; srand(1); a=rand(); これだけ!
それでは、本当に生成できてるか確認してみま しょう! 先程のプログラムの乱数を何回か生成してみよう。 すると、下記のような結果となる。
SEED値を時刻によって変更する srand((unsigned int)time(NULL)); 方法は簡単!srand()を下記に変え、 #include<time.h>を加えるだけである。 srand((unsigned int)time(NULL)); おまじないみたいなものだと思って覚えよう。
自由自在な範囲で乱数を生成する ここまでやってきた方法では、「1~10までの 乱数を作りたい!」など任意の範囲での乱数の生 成はできない・・ →なら、乱数を加工して自分で作ってしまおう!
a=rand() ← ここを加工する! 試しに、先程作った乱数のプログラムのa=rand() をa=rand()%10 に変えてみよう! すると・・・以下のように生成できる。
結果のように1~10の乱数を生成できた、 ようにみえるがa=rand()%10では、10で割ったと きのあまりであるので0~9の乱数となってしま う。 1~10までの乱数を生成するにはどうすればいい か?簡単である。rand()を以下のように書き換え る。 a=1+rand()%10
以上のように1~10の乱数を生成できた。 ・・・このように、rand()を四則演算で加工することによって任意の範囲の乱数を生成することができる! 覚えておいて損はない。
演習2 乱数により1~9同士の足し算の問題を表示し、そ の答えを入力させて正解かどうかを判定するプロ グラムを作りなさい。 余力があれば正解数をカウントし、表示させなさ い
解答2 #include <stdio.h> #include <stdlib.h> #include <time.h> #include <Windows.h> int main(){ int ran1, ran2, i, input, cnt; cnt = 0; srand((unsigned int)time(NULL)); for(i=0;i<5;i++){ ran1=rand()%9+1; ran2=rand()%9+1; printf("%d + %d = ",ran1 ,ran2); scanf("%d",&input); if(ran1+ran2==input){ printf("正解!\n"); cnt++; } else{ printf("不正解...\n"); Sleep(500);//0.5秒だけ処理を待たせ る printf("%d問正解!\n",cnt); return 0;
解答2
演習3 #define N 7 int array[N] = {6,5,2,7,4,8,4} 以上の配列の平均値、最大値、最小値を返す関数 float ave(int a[]) int max(int a[]) int min(int a[]) をそれぞれ実装しなさい
解答3 #include <stdio.h> #define N 7 float ave(int a[]){ int i; float ave = 0; for(i=0;i<N;i++){ ave+=a[i]; } ave/=N; return ave; int max(int a[]){ int max = 0; if(max==0 || max<a[i]){ max = a[i]; return max; int min(int a[]){ int min = 0; if(min==0 || a[i]<min){ min = a[i]; return min; int main(){ int array[7] = {6,5,2,7,4,8,4}; printf("平均値:%.2f\n",ave(array)); printf("最大値:%d\n",max(array)); printf("最小値:%d\n",min(array));
解答3
解答3
おわり 以上、お疲れ様でした^~