第 12 章 関数と配列
1 次元配列2 次元配列
配列を使って結果を返す演習問題
レポート課題
a_p は、整数型変数のアドレスが入るポインタ型変数で(1行目)、配列 a の先頭の要素の番地を代入する(2行目)
9.4 配列変数とポインタ ( 再掲 )
100010041008・・・
a[0]
C では、配列変数はポインタ変数を用いてアクセスすることが多い&a[0] は 1000 、 &a[1] は 1004 a[1]
a[2]a[3]a[4]
a_p 1000
int *a_p;a_p = &a[0];
100010041008・・・
a[0]a[1]a[2]a[3]a[4]
a_p 1000
ポインタと配列変数との間の関係
1000
a[0]a_p
a_p = &a[0]; は、a_p = a; と書いても良い上記の文で、 a_p には、配列 a の先頭の要素a[0] の番地を代入するよ、という意味。図示すると、
… value = sum(count, &a[0]); …
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; }
main で関数 sum を呼び出す時、a の先頭アドレスを引数としている
10.9 関数と配列プログラム例 10.9.1
関数 sum の引数は、配列の要素数 n とポインタ
a[0], a[1] の値が加算される。ポインタは、 &a[0], &a[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; }
10.9 関数と配列プログラム例 10.9.1
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]
・・・
・・・
・・・
value = sum(count, &a[0]);
10.9 関数と配列
上記の文は、下のように書いても同様(この方が一般的)
value = sum(count, a);
プログラム例 10.9.1 の main の4行目
12.1 1 次元配列#include <stdio.h>double sum(int n, double 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;}
double sum(int n, double x[]){ int i; double s; s = 0.; for (i = 0; i < n; i++) s += x[i]; return s;}
プログラム例 10.9.1 改
*x_p のかわりに x[]
*x_p; x_p++ のかわりに x[i]
*x_p のかわりに x[]
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]);}
プログラム例 12.1.1
初期値があればサイズは省略可
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]
a11 a12・・・ a1n
a21 a22・・・ a2n
・・・
・・・
・・・
am1 am2・・・ amn
a11
a12
・・・
a1n
a21
・・・
折り返し場所の情報は省略できない
a[m][n] の行列表現
1行目
記憶領域→ 1 次元的
1 行目
2 行目
m 行目
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 3void 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.
2c11 c12 c13
c21 c22 c23
c31 c32 c33
a11 a12 a13
a21 a22 a23
a31 a32 a33
b11 b12 b13
b21 b22 b23
b31 b32 b33
= +
=a11+b11 a12+b12 a13+b13
a21+b21 a22+b22 a23+b23 a31+b31 a32+b32 a33+b33
関数 sum : 配列 a と b から、上記のように新しい配列 c を計算。
配列 c (新しいデータ)を main に返すには?
呼び出し側の配列へデータを返す
… sum(nr, nc, &a[0][0], &b[0][0], &c[0][0]); …
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++; }}
プログラム例 10.10.2
sum の呼び出し前: 配列 c[i][j] は 未定sum の呼び出し後: 配列 c[i][j] には a[i][j] + b[i][j] が入る
12.3 配列を使って結果を返すプログラム例 12.3.1
#include <stdio.h>#define NROW 3#define NCOL 3void 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;}
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.3 配列を使って結果を返す
配列要素の数値の総和と平均値を計算する関数
平均値の計算
総和の計算
#include <stdio.h>#define NROW 3#define NCOL 3void 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.2
#include <stdio.h>#define NROW 3#define NCOL 3void sum(int x[][NCOL], int y[][NCOL], int z[][NCOL]);void diff(int x[][NCOL], int y[][NCOL], int z[][NCOL]);void prod(int x[][NCOL], int y[][NCOL], int z[][NCOL]);void disp_2D_array(int x[][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(???????); disp_2D_array(c); diff(???????); disp_2D_array(c); prod(???????); disp_2D_array(c); return 0;}
演習問題 12.3
void sum(int x[][NCOL], int y[][NCOL], int z[][NCOL]){}void diff(int x[][NCOL], int y[][NCOL], int z[][NCOL]){}void prod(int x[][NCOL], int y[][NCOL], int z[][NCOL]){ int i, j, k; for (i = 0; i < ????; i++) { for (j = 0; j < ????; j++) { z[i][j] = 0; for (k = 0; k < ????; k++) z[i][j] += ???????????????; } }}void disp_2D_array(int x[][NCOL]){}
jijiji yxz ,,,
jijiji yxz ,,,
n
k
jkkiji yxz1
,,,
演習問題 12.3 (つづき)
行列の和
行列の差
行列の積
#include <stdio.h>#define NROW 3#define NCOL 4void sweep_out(double ?????????);void disp_2D_array(double ?????????);
int main(void){ double a[NROW][NCOL] = {{2, 3, 1, -1}, {3, 1, 2, 7}, {1, 2, 3, 6}}; disp_2D_array(?); sweep_out(?); disp_2D_array(?); return 0;}
演習問題 12.4
z
y
x
100
010
001
6321
7213
1132
掃出法
void sweep_out(double ?????????){ int i, j, k; double w; for (k = 0; k < NROW; k++) { w = a[k][k]; for (j = 0; j < NCOL; j++) a[k][j] /= w; for (i = 0; i < NROW; i++) { if (i != k) { w = a[i][k]; for (j = 0; j < NCOL; j++) a[i][j] -= w * a[k][j]; } } }}
void disp_2D_array(double ?????????){ ?????????}
演習問題 12.4 (つづき)
k 行目の成分をその対角成分で割る
掃き出し操作
レポートのファイルは保存しておくこと
今回のレポートでは以下の項目をいれること。表紙は不要。• 学籍番号、氏名• 問題番号• ソースリスト• 実行結果• 感 想(5行以上)
第 1 回 レポート ( 必須 ) 課題 課題:教科書 p.114 の演習問題 12.3 または 12.4 提出期限: 2007 年 10 月 26 日 ( 金 ) 17:00 提出場所:ネットワーク実験室 ( 1 ) の入口近くの箱