第12章 関数と配列 1次元配列 2次元配列 配列を使って結果を返す 演習問題 レポート課題 9.4 配列変数とポインタ (再掲) C では、配列変数はポインタ変数 を用いてアクセスすることが多い &a[0] は1000、 &a[1] は1004 int *a_p; a_p = &a[0]; a_p は、整数型変数のアドレスが入る ポインタ型変数で(1行目)、配列 a の 先頭の要素の番地を代入する(2行目) 1000 1004 1008 ・ ・ ・ a[0] a[1] a[2] a[3] a[4] a_p 1000 ポインタと配列変数との間の関係 a_p = &a[0]; は、 a_p = a; と書いても良い ポインタ定数 上記の文で、 a_p には、配列 a の先頭の要素 a[0] の番地を代入するよ、 という意味。 図示すると、 1000 1004 1008 ・ ・ ・ a[0] a[1] a[2] a[3] a[4] a_p a_p 1000 a[0] 1000 10.9 関数と配列 プログラム例 10.9.1 … value = sum(count, &a[0]); … main で関数 sum を呼び 出す時、a の先頭アドレス (ポインタ定数)を引数と している float sum(int n, float *x_p) { 関数 sum の引数は、 int i; 配列の要素数 n とポインタ float s; s = 0.; for (i = 0; i < n; i++) { s += *x_p; x_p++; a[0], a[1], ... の値が加算される。 } ポインタ自体は、 return s; } &a[0], &a[1], … と変化する 10.9 関数と配列 プログラム例 10.9.1 float sum(int n, float *x_p) { int i; float s; s = 0.; for (i = 0; i < n; i++) { s += *x_p; x_p++; } return s; } s x_p 0 &a[0] i=0のループ終了時 a[0] &a[1] i=1のループ終了時 a[0]+a[1] &a[2] ループに入る時 i=2のループ終了時 a[0]+a[1]+a[2] &a[3] ・ ・ ・ ・ ・ ・ ・ ・ ・ 10.9 関数と配列 プログラム例 10.9.1 の main の4行目 value = sum(count, &a[0]); 上記の文は、下のように書いても同様 (この方が一般的) value = sum(count, a); 12.1 1次元配列 プログラム例 10.9.1 改 #include <stdio.h> double sum(int n, double x[]); *x_p のかわりに x[] int main(void) { double a[5] = {1.56, 3.24, 5.24, 3.24, 6.23}; int count = 5; double value; value = sum(count, a); printf("総和 = %f\n", value); return 0; } *x_p のかわりに x[] double sum(int n, double x[]) { int i; double s; s = 0.; for (i = 0; i < n; i++) *x_p; x_p++ のかわりに x[i] s += x[i]; return s; } 12.1 1次元配列 プログラム例 12.1.1 #include <stdio.h> void disp_1D_array(int n, double x[]); int main(void) 初期値があればサイズは省略可 { double a[] = {3.24, 1.76, 5.32, 2.37, 4.33, 1.26}; int asize = 6; disp_1D_array(asize, a); return 0; } void disp_1D_array(int n, double x[]) { int i; for (i = 0; i < n; i++) printf("%f\n", x[i]); } 10.10 関数と2次元配列 プログラム例 10.10.1 #include <stdio.h> void disp_2D_array(int nrow, int ncol, double *a_p); int main(void) 内側の波カッコは人が読みやすくするため { int nrow = 3, ncol = 3; double a[3][3] = {{1.56, 3.24, 5.24}, {3.24, 6.23, 8.16}, {7.32, 2.86, 4.12}}; disp_2D_array(nrow, ncol, &a[0]); return 0; } void disp_2D_array(int nrow, int ncol, double *a_p) { int i, j; for (i = 0; i < nrow; i++) { for (j = 0; j < ncol; j++) { printf(" %7.2f", *a_p); a_p++; } printf("\n"); } } 12.2 2次元配列 行の大きさは省略できるが、列の大きさは省略できない x[3][3] → x[][3] 記憶領域→1次元的 a[m][n] の行列表現 1行目 2行目 a12 ・・・ a21 a22 ・・・ a11 ・ ・ ・ m行目 ・ ・ ・ am1 am2 a1n a2n ・ ・ ・ ・・・ a11 amn 1行目 a12 ・ ・ ・ a1n a21 ・ ・ ・ 折り返し場所の情 報は省略できない 12.2 2次元配列 プログラム例 12.2.1 #include <stdio.h> void disp_2D_array(int n, double x[][3]); int main(void) { int nrow = 3; double a[3][3] = {{3.24, 1.76, 5.32}, {2.37, 4.33, 1.26}, {1.86, 1.86, 3.64}}; disp_2D_array(nrow, a); return 0; } void disp_2D_array(int n, double x[][3]) { int i, j; for (i = 0; i < n; i++) { for (j = 0; j < 3; j++) { printf(" %7.2f", x[i][j]); } printf("\n"); 3 という数字があちこちに散逸 } } 12.2 2次元配列 プログラム例 12.2.2 #include <stdio.h> #define NROW 3 行数、列数を集中管理 #define NCOL 3 void disp_2D_array(double x[][NCOL]); int main(void) { double a[NROW][NCOL] = {{3.24, 1.76, 5.32}, {2.37, 4.33, 1.26}, {1.86, 1.86, 3.64}}; disp_2D_array(a); return 0; } void disp_2D_array(double x[][NCOL]) { int i, j; for (i = 0; i < NROW; i++) { for (j = 0; j < NCOL; j++) { printf(" %7.2f", x[i][j]); } printf("\n"); } } 呼び出し側の配列へデータを返す プログラム例 10.10.2 c11 c12 c13 c21 c22 c23 c31 c32 c33 = a11 a12 a13 a21 a22 a23 a31 a32 a33 = a11+b11 a12+b12 a13+b13 a21+b21 a22+b22 a23+b23 a31+b31 a32+b32 a33+b33 + b11 b12 b13 b21 b22 b23 b31 b32 b33 関数 sum: 配列 a と b から、上記のように新しい配列 c を計算。 配列 c (新しいデータ)を main に返すには? 呼び出し側の配列へデータを返す プログラム例 10.10.2 … sum(nr, nc, &a[0][0], &b[0][0], &c[0][0]); … sum の呼び出し前: 配列 c[i][j] は 未定 sum の呼び出し後: 配列 c[i][j] には a[i][j] + b[i][j] が入る void sum(int nrow, int ncol, float *a_p, float *b_p, float *c_p) { int i, j; for (i = 0; i < nrow; i++) for (j = 0; j < ncol; j++) { *c_p = *a_p + *b_p; a_p++; b_p++; c_p++; } } 12.3 配列を使って結果を返す プログラム例 12.3.1 #include <stdio.h> #define NROW 3 #define NCOL 3 void sum(int x[][NCOL], int y[][NCOL], int z[][NCOL]); void disp_2D_array(int u[][NCOL]); int main(void) { int a[NROW][NCOL] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}; int b[NROW][NCOL] = {{11, 12, 13}, {14, 15, 16}, {17, 18, 19}}; int c[NROW][NCOL]; disp_2D_array(a); disp_2D_array(b); sum(a, b, c); disp_2D_array(c); return 0; } 12.3 配列を使って結果を返す void sum(int x[][NCOL], int y[][NCOL], int z[][NCOL]) { int i, j; for (i = 0; i < NROW; i++) { for (j = 0; j < NCOL; j++) { z[i][j] = x[i][j] + y[i][j]; } } } void disp_2D_array(int u[][NCOL]) { int i, j; for (i = 0; i < NROW; i++) { for (j = 0; j < NCOL; j++) { printf(" %10d", u[i][j]); } printf("\n"); } } 演習問題12.2 #include <stdio.h> #define NROW 3 #define NCOL 3 void sum_ave(double ?????????, double *s, double *av); int main(void) 配列要素の数値の総和と { 平均値を計算する関数 double s, av; double a[NROW][NCOL] = {{3.24, 1.76, 5.32}, {2.37, 4.33, 1.26}, {1.86, 1.86, 3.64}}; sum_ave(??????????); printf("総和 = %7.2f, 平均 = %7.2f¥n", s, av); return 0; } void sum_ave(double ?????????, double *s, double *av) { int i, j; *s = 0; for (i = 0; i < ????; i++) { for (j = 0; j < ????; j++) { *s += ???????; 総和の計算 } } *av = ??????????????; 平均値の計算 } 演習問題12.3 #include <stdio.h> #define N 3 void sum(int x[][N], int y[][N], int z[][N]); void diff(int x[][N], int y[][N], int z[][N]); void prod(int x[][N], int y[][N], int z[][N]); void disp_2D_array(int x[][N]); int main(void) { int a[N][N] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}; int b[N][N] = {{11, 12, 13}, {14, 15, 16}, {17, 18, 19}}; int c[N][N]; disp_2D_array(a); disp_2D_array(b); sum(???????); disp_2D_array(c); diff(???????); disp_2D_array(c); prod(???????); disp_2D_array(c); return 0; } 演習問題12.3 (つづき) void sum(int x[][N], int y[][N], int z[][N]) { zi, j xi, j 行列の和 ???...??? } void diff(int x[][N], int y[][N], int z[][N]) { zi, j xi, j ???...??? 行列の差 } void prod(int x[][N], int y[][N], int z[][N]) { int i, j, k; for (i = 0; i < ?; i++) { 行列の積 for (j = 0; j < ?; j++) { z[i][j] = 0; n for (k = 0; k < ?; k++) zi , j z[i][j] += ???????????????; } k 1 } } void disp_2D_array(int x[][N]) { ???...??? } yi, j yi, j x i,k yk , j 演習問題12.4 #include <stdio.h> #define N 3 void sweep_out(double ????????); void disp_2D_array(double ????????); int main(void) { double a[N][N+1] = {{2,3,1,-1}, {3,1,2,7}, {1,2,3,6}}; disp_2D_array(?); sweep_out(?); disp_2D_array(?); return 0; } 掃出法 2 3 1 1 1 0 0 x 3 1 2 7 0 1 0 y 1 2 3 6 0 0 1 z 演習問題12.4 (つづき) void sweep_out(double ????????) { int i, j, k; double w; k行目の成分をその対角成分で割る for (k = 0; k < N; k++) { w = a[k][k]; for (j = 0; j <= N; j++) a[k][j] /= w; for (i = 0; i < N; i++) { if (i != k) { w = a[i][k]; for (j = 0; j <= N; j++) a[i][j] -= w * a[k][j]; } } 掃き出し操作 } } void disp_2D_array(double ????????) { ???...??? } 第1回 レポート(必須) 課題 課題:教科書p.114の演習問題12.3 または 12.4 提出期限:2009年10月23日(金) 12:50 提出場所:ネットワーク実験室(1)の入口近くの箱 今回のレポートでは以下の項目をいれること。 1. 学籍番号、氏名 2. 問題番号 レポートのファイルは 3. ソースリスト 保存しておくこと 4. 実行結果 5. 感 想(5行以上) レポートサンプルを参照のこと
© Copyright 2024 ExpyDoc