第 12 章 関数と配列

22
第 12 第 第第第第第 1 次次次次 2 次次次次 次次次次次次次次次次次 次次次次 次次次次次次

Upload: gay-dudley

Post on 04-Jan-2016

25 views

Category:

Documents


2 download

DESCRIPTION

第 12 章 関数と配列. 1 次元配列 2 次元配列 配列を使って結果を返す 演習問題 レポート課題. 9.4 配列変数とポインタ ( 再掲 ). C では、 配列 変数は ポインタ 変数 を用いてアクセスすることが多い. 1000 1004 1008 ・ ・ ・. a[0]. &a[0] は 1000 、 &a[1] は 1004. a[1]. a[2]. a[3]. int *a_p; a_p = &a[0] ;. a[4]. 1000. a_p. a_p は、整数型変数のアドレスが入る - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: 第 12 章 関数と配列

第 12 章 関数と配列

1 次元配列2 次元配列

配列を使って結果を返す演習問題

レポート課題

Page 2: 第 12 章 関数と配列

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];

Page 3: 第 12 章 関数と配列

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] の番地を代入するよ、という意味。図示すると、

Page 4: 第 12 章 関数と配列

… 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], …となる

Page 5: 第 12 章 関数と配列

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]

・・・

・・・

・・・

Page 6: 第 12 章 関数と配列

value = sum(count, &a[0]);

10.9  関数と配列

上記の文は、下のように書いても同様(この方が一般的)

value = sum(count, a);

プログラム例 10.9.1 の main の4行目

Page 7: 第 12 章 関数と配列

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[]

Page 8: 第 12 章 関数と配列

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

初期値があればサイズは省略可

Page 9: 第 12 章 関数と配列

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"); }}

内側の波カッコは人が読みやすくするため

Page 10: 第 12 章 関数と配列

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 行目

Page 11: 第 12 章 関数と配列

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 という数字があちこちに散逸

Page 12: 第 12 章 関数と配列

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"); }}

行数、列数を集中管理

Page 13: 第 12 章 関数と配列

呼び出し側の配列へデータを返すプログラム例 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 に返すには?

Page 14: 第 12 章 関数と配列

呼び出し側の配列へデータを返す

… 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] が入る

Page 15: 第 12 章 関数と配列

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;}

Page 16: 第 12 章 関数と配列

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  配列を使って結果を返す

Page 17: 第 12 章 関数と配列

配列要素の数値の総和と平均値を計算する関数

平均値の計算

総和の計算

#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

Page 18: 第 12 章 関数と配列

#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

Page 19: 第 12 章 関数と配列

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  (つづき)

行列の和

行列の差

行列の積

Page 20: 第 12 章 関数と配列

#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

掃出法

Page 21: 第 12 章 関数と配列

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 行目の成分をその対角成分で割る

掃き出し操作

Page 22: 第 12 章 関数と配列

レポートのファイルは保存しておくこと

今回のレポートでは以下の項目をいれること。• 学籍番号、氏名• 問題番号• ソースリスト• 実行結果• 感 想(5行以上)

第 1 回 レポート ( 必須 ) 課題 課題:教科書 p.114 の演習問題 12.3 または 12.4 提出期限: 2008 年 10 月 24 日 ( 金 ) 12:50 提出場所:ネットワーク実験室 ( 1 ) の入口近くの箱

レポートサンプルを参照のこと