※ 筑波大学渡辺紀生作成の演習ページから一部修正・転載。
今回は、テキスト5章の2次元配列と、6章の関数について学びます。
多次元配列はテキスト5-2(p.102)を参考にしてください。多次元配列の初期化方法は、1次元配列と同様の規則に従います。
整数型の2次元配列宣言では
int a[5][5]; /* 領域は確保されるが値は不定 */ int a[2][2] = {{1, 2}, {3, 4}}; int a[5][5]= {0}; /* 全て0で初期化される */ int a[][3] = {{1, 2, 3}, {4, 5,6}}; /* a[2][3]が確保され指定の数値で初期化される。*/ /* 初期化子が与えられている場合、最初の要素数を省略することが可能 */
という宣言方法があります。int の部分をdoubleとすれば倍精度浮動小数点型の配列が確保されます。
テキストp.102, List5-14の行列を加算するプログラムを実行してみましょう。
/* 2行3列の行列を加算する */ #include int main(void) { int i, j; int ma[2][3] = { {1, 2, 3}, {4, 5, 6} }; int mb[2][3] = { {6, 3, 4}, {5, 1, 2} }; int mc[2][3] = { 0 }; for (i = 0; i < 2; i++) for (j = 0; j < 3; j++) mc[i][j] = ma[i][j] + mb[i][j]; for (i = 0; i < 2; i++) { for (j = 0; j < 3; j++) printf("%3d", mc[i][j]); putchar('\n'); } return (0); }
配列ma, mbを初期化子を与えて初期化し、両者を加えた結果をmcに代入しています。配列mcも初期化子を与えて0で初期化していますが、これは特に必要ありません。
これまで、 printf( ) , scanf( ) といったC言語が提供するライブラリ関数を使ってきました。これらの関数と同様の関数をプログラム作成者が作ることが出来ます。複雑なC言語プログラムを作成する場合には、プログラム全体をそれぞれが単純な機能を持つ部分に分解して関数に割り当てることによって、見通しよくプログラムを作成することが出来ます。
返却値型 関数名(仮引数リスト){ 関数の本体 }
下の関数では、返却値型がint, 関数名がmaxof, 仮引数リストがint x, int y となっています。2つの整数値を引数として受け取って、大きいほうの値を返す関数です。
int maxof( int x, int y) { if ( x > y) return (x); else return (y); }
関数をプログラム中で使用するには、
関数名(実引数リスト)
という形で関数を呼び出します。
上記の maxof( ) 関数を用いて整数3, 5のうち大きいほうの値を求めてxという変数に代入するには、プログラム中で以下のように書きます。
x = maxof(3, 5);
次のプログラム(P.115, List6-1)は、上の関数を用いて入力した2つの整数のうち大きいほうを出力するプログラムです。
/* 二つの整数の大きい方の値を返す関数 */ #include <stdio.h> /*--- 大きい方の値を返す ---*/ int maxof(int x, int y) { if (x > y) return (x); else return (y); } int main(void) { int na, nb; int x = 10; puts("二つの整数を入力してください。"); printf("整数1:"); scanf("%d", &na); printf("整数2:"); scanf("%d", &nb); printf("大きい方の値は%dです。\n", maxof(na, nb)); printf(" x = %d\n", x); return (0); }
関数の定義部分は、その関数を使用しているmain( )関数より前にある必要があります。関数呼び出しでコンパイラが実引数の型や数をチェックするため、その情報を前もって知っている必要があるからです。
次のプログラムは、2つの引数をとって前者の値を後者の値の回数だけ掛け合わせた値を返す関数を使っています。
/* べき乗を求める */ #include <stdio.h> /*--- dxのno乗を返す ---*/ double power(double dx, int no) { int i; double tmp = 1.0; for (i = 1; i <= no; i++) tmp *= dx; return (tmp); } int main(void) { int n; double x; printf("実数を入力してください:"); scanf("%lf", &x); printf("整数を入力してください:"); scanf("%d", &n); printf("%.2fの%d乗は%.2fです。\n", x, n, power(x, n)); return (0); }
この関数呼び出し power(x, n) で与えた実引数 x, n は関数実行に際して値が関数側の変数にコピーされて実行されるため、関数内部で仮引数dx, noの値を書き換えても呼び出し元の変数 x, n の値は全く変化しません。このように値がコピーされる変数の受け渡し方法を、値渡し(pass by value) と呼びます。そのため、関数内部で仮引数を使って以下のように power( ) 関数を書くことも出来ます。(p.121, List6-5)
/*--- dxのno乗を返す(第2版) ---*/ double power(double dx, int no) { double tmp = 1.0; while (no-- > 0) tmp *= dx; return (tmp); }
値を返さない場合の返却値型=>void 値を返さない関数の例 (p122, List6-7) void put_stars(int no); no個の*を表示
/* 直角三角形(左下が直角)を表示(関数版) */ #include <stdio.h> /*--- *をno個連続表示 ---*/ void put_stars(int no) { while (no-- > 0) putchar('*'); } int main(void) { int i, ln; printf("何段ですか:"); scanf("%d", &ln); for (i = 1; i <= ln; i++) { put_stars(i); putchar('\n'); } return (0); }
void 関数の例(p.124, List6-9) int scan_uint( void )
/* 読み込んだ非負の整数値を逆順に表示 */ #include <stdio.h> /*--- 非負の整数を読み込んで返す ---*/ int scan_uint(void) { int tmp; do { printf("非負の整数を入力してください:"); scanf("%d", &tmp); if (tmp < 0) puts("\a負の数を入力しないでください。"); } while (tmp < 0); return (tmp); } /*--- 非負の整数を逆転した値を返す ---*/ int rev_int(int num) { int tmp = 0; if (num > 0) { do { tmp = tmp * 10 + num % 10; num /= 10; } while (num > 0); } return (tmp); } int main(void) { int nx = scan_uint(); //関数の返却値で変数を初期化することも可能 printf("反転した値は%dです。\n", rev_int(nx)); return (0); }
下の2つの行列 x, y の積を求めるプログラムを作成せよ。
、
ただし、それぞれの行列を
double x[ ][ ] = { { 1, 2, 3}, { 4, 5, 6}}; double y[ ][ ] = { { 1, 5}, { 5, 3}, { 8, 1}};
と宣言して用いること。 結果は2行2列の行列となるが、結果を z[i][j] とすると、z[i][j] = x[i][0]*y[0][j] + x[i][1]*y[1][j] + x[i][2]*y[2][j] となる。結果の表示は以下のようにすれば良い。
printf("*** 結果 ***\n"); printf(" %3d %3d\n", z[0][0], z[0][1]); printf(" %3d %3d\n", z[1][0], z[1][1]); printf("***********\n");
物体を初速度 velocity(m/s)、仰角 angle 度で投げ出した場合の水平到達距離 (m) を求めるプログラムを作成する。velocity と angle を引数として受け取って水平到達距離を返す関数
double hdist( double velocity, double angle);
を作成し、その関数を用いてキーボードから初速度 velocity(m/s) 、仰角 angle 度を入力して水平到達距離 (m) を求めるプログラムを作成せよ。ただし、重力加速度は9.8m/s2 とし、また空気抵抗は無視するものとする。また、標準ライブラリ関数の double sin (double ) を用いるには、#include <math.h> でヘッダーファイル math.h を読み込んでおくこと。
※ このページは渡辺紀生先生の筑波大学応用理工学情報処理(1クラス)用のページを転載したものです。
オリジナルページは以下のURLから。 http://www.u.tsukuba.ac.jp/~watanabe.norio.fw/C2-8.htm