応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...授業日程・内容...

47
応用プログラミング 高瀬 裕(たかせ ゆたか) [email protected] http://iui.ci.seikei.ac.jp/~takase/ 応用プログラミング<6> 第九回 2014/11/19

Transcript of 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...授業日程・内容...

Page 1: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型, 制御構造

応用プログラミング

高瀬 裕(たかせ ゆたか)[email protected] http://iui.ci.seikei.ac.jp/~takase/

応用プログラミング<6> 第九回 2014/11/19

Page 2: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型, 制御構造

授業日程・内容回数 日程 内容 テキスト第1回 9/24 基本データ型, 制御構造 1章第2回 10/1 一次配列,string クラス 2章 3章第3回 10/8 関数定義とスコープ (Vector型) 4章(5章)第4回 10/15 ファイル操作 6章第5回 10/22 テキスト入力処理 7章第6回 10/29 ポインタの基本 8章第7回 11/5 配列とポインタ 9章第8回 11/12 中間試験第9回 11/19 多次元配列 10章第10回 11/26 構造体 11章第11回 12/3 関数宣言, 関数名の多重定義, デフォルト引数, 関数テンプレート 12章第12回 12/10 再帰呼び出し 13章第13回 12/17 アルゴリズム 14章第14回 1/14 配列を用いた間接参照 15章第15回 1/21 期末試験

Page 3: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型, 制御構造

教員紹介

高瀬 裕(たかせ ゆたか)

居室:12号館 1階 知的インタフェース研究室

連絡先 [email protected]資料置き場 http://iui.ci.seikei.ac.jp/~takase/

専門はVR(バーチャルリアリティ)とか ヒューマンインタフェース です。

Page 4: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型, 制御構造

前回の復習

Page 5: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型, 制御構造

配列とポインタ

Page 6: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型, 制御構造

配列のアドレス(p79)

アドレス・ポインタ・配列の関係

int a[4] = {1,2,3,4};  // 配列の宣言と初期化

// 配列の要素のアドレス for(int i = 0; i <4 i++) cout << &a[i] << endl;

配列の先頭のアドレス &a[0] を 配列変数 a で扱えることにします

&配列変数名[0] or 配列変数名配列の先頭のアドレス :

int a[4] = {1,2,3,4};

cout << &a[0] << endl; cout << a << endl;

Source

同じ値です。(というか同じものです)

Page 7: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型, 制御構造

ポインタで配列を扱う(p79)

配列とポインタの関係

int a[4] = {1,2,3,4}; int* x = &a[0]; int* y = &a[2];

cout << *x <<“ “ << *y << endl;

// ポインタを配列のように扱う

cout << x[0] << “ “ << x[1] <<endl; cout << y[0] << “ “ << y[1] <<endl;

a[0] のアドレス を格納

a[2] のアドレス を格納

ポインタが指し示す アドレスの中身を出力

int *x = a でも同じ

Result1 2 3 4

配列っぽく表記すると アドレスを ポインタの型分だけずらしてくれます

y[0] は a[2] なので y[1] は a[3] になる

Page 8: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型, 制御構造

ポインタで配列を扱う配列とポインタの関係

1 1 0 1 1 0 0 1

1 1 0 0 0 0 1 11 0 0 0 1 0 0 00 0 1 1 1 0 0 01 0 0 1 1 1 0 01 0 0 1 1 1 0 01 0 0 1 1 1 0 01 0 0 1 1 1 0 01 0 0 1 1 1 0 01 0 0 1 1 1 0 01 0 0 1 1 1 0 01 0 0 1 1 1 0 01 0 0 1 1 1 0 01 0 0 1 1 1 0 0

100101102103104105106107108109111112113114

int a[0] (32bit)

int a[1] (32bit)

int a[2](32bit)

int a[4] = {1,2,3,4}; int* x = &a[0];

x[0] // a[0] のアドレスの中身 x[1]  // a[0] の(アドレス+ 4byte)の中身

int a[3]

配列を代入しているのではない事に注意 x はポインタなので アドレスが代入されています。

(int 型 ポインタなので)

Page 9: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型, 制御構造

配列引数(p81)

配列のアドレスを関数に渡す

配列の要素を全て関数に渡すことはできない (書き下せば別ですが) 配列のアドレスを渡せばよい

実引数 : 関数を呼び出す時の引数

仮引数:関数で受け取る時の引数

アドレス:関数に渡したいアドレス

ポインタ:受け取るためにはポインタが必要型名* 仮の変数名 int* a

型名 変数名[] int a[] 仮引数に限ってこれでもOKいつものポインタ

Page 10: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型, 制御構造

void incr(int x[], int sz){ for(int i = 0; i< sz; i++) x[i]++;

}

int main(){ const int size = 5; int a[size] = {1,2,3,4,5};

incr(a,size);

return 0; }

実引き数は渡したいアドレス (配列の先頭)

仮引数はポインタ

配列を全て渡す場合は 配列の先頭アドレスを関数に渡す

各要素へのアクセス

この場合の各要素へのアクセスは x[i] で行える。 (正確には i 番目のアドレスの中身へアクセスしている)

配列ではなく,アドレスを渡している点に注意

Page 11: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型, 制御構造

void incr(int* x, int sz){ for(int i = 0; i< sz; i++) x[i]++;

}

int main(){ const int size = 5; int a[size] = {1,2,3,4,5};

incr(&a[0],size);

return 0; }配列のアドレスを受け取ったことが分かりにくいので 仮引数は int x[] の方を推奨します。 実引数は&a[0] と書くのが面倒なので a と 書けるようになってます。

前のページと全く同じ挙動になる点 に注意して下さい。

一般に,配列はサイズが無いと扱いにくいので渡してます。

配列のアドレスを 受け取ったことが分かりにくい

Page 12: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型, 制御構造

内容を変更できない配列引数(p82)

アドレスを渡すと簡単に書き換えられてしまいます配列(のアドレス)を関数に渡しても 配列の要素を変更しない場合も多いです

void print(int x[], int sz){ for(int i=0; i < sz; i++) cout << x[i]<< “ “; cout << endl; }

int main(){ int n[3] = {0,1,2}; print(n,3);

return 0; }

print 関数は出力のみで要素を変更しない

void print( const int x[], int sz){

仮引数の前に const を付けると 変更不可能になる

変更しようとするとコンパルエラーに

Page 13: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型, 制御構造

要素数を渡さない方法文字列ならわかりやすい

文字列は最後尾が ヌル文字 ‘\0’ でした。void print(const char x[]){ for(int i=0; x[i] != ‘\0’; i++) cout << x[i]<< “ “; cout << endl; }

int main(){ const char s[] = “abcd”; print(s);

return 0; }

ヌル文字が出てくるまで出力する。

例えば,文字数のカウントも可能になります。

Page 14: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型, 制御構造

配列の先頭要素以外を渡すアドレスなので途中からでも渡せます。

今までは, 関数に配列をまるごと渡していました。

配列の先頭アドレスを渡していました。渡すアドレスを変えれば,配列の途中から関数で扱えます。

int a[]={1,2,3,4};

cout << a << endl; // 先頭のアドレスと等しい cout << &a[0] << endl; // ↑と等しい cout << &a[1] << endl; // 配列 1番目のアドレス

配列の途中から関数で扱うための実引数は想像できましたか?

Page 15: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型, 制御構造

#include <iostream>using namespace std;

// 配列の各要素を+1 する (要素を変更する)

void incr(int x[], int sz){

for (int i = 0; i < sz; i++)  x[i]++; }

// 配列のすべての要素を出力する (要素を変更しない)

void print(const int x[], int sz) {

for (int i = 0; i < sz; i++) cout << x[i] << " "; cout << endl; } int main() {const int asize = 5; // サイズ5の配列int a[asize] = { 1,2,3,4,5 };

print(a, asize); incr(&a[2], asize-2); print(a, asize); return 0;

}

3番目の要素のアドレスを渡す, サイズも減る。

受け取り方は変化ない

3番目の要素が x[0] になることに注意

あくまで渡したい位置のアドレスと,そこから最後までの要素数を渡している。

(c9_7_1)

Page 16: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型, 制御構造

#include <iostream>using namespace std;

// 要素数 sz の配列 x[] から n を探し、要素の添字を返す。 // 見つからない場合には sz を返す。 int find(const int x[], int sz, int n){

for (int idx = 0; idx < sz; idx++) if (x[idx] == n) return idx; return sz;

}

int main() {

const int size = 12; int a[size] = { 1,2,3,2,5,8,9,2,4,1,2,9 }; const int n = 2; // この値の要素を探す

int i = find(a, size, n); // 先頭から要素を探す

while (i < size) {

cout << "(" << i << ", " << a[i] << ")" << endl;++i; // 隣の要素を先頭と考える

i += find(&a[i], size-i, n); // 次の要素を探す

}

return 0;

常に,現在の先頭から何番目にあるかを返す

配列内の検索を行うプログラム (c9_7_2)

1 2 3 2 5 8 9 2 4 1 2 9a[]

1 回目 find(a,12,2) : 戻り値 11 2 3 2 5 8 9 2 4 1 2 9x[]

2 回目 find(&a[2], 10,2): 戻り値 1

3 5 8 9 2 4 1 2 9x[] 2

3 回目 find(&a[4], 8,2): 戻り値 35 8 9 4 1 2 9x[] 2

4 回目 find(&a[8], 4,2): 戻り値 24 1 9x[]

5 回目 find(&a[11], 1,2): 戻り値 19x[]

2

Page 17: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型, 制御構造

練習問題配列の受け渡しの復習

ある配列の要素を 2乗する関数 Square と 出力する関数 Print を作成してください。

ここでは,アドレスの渡し方と ポインタによる受け取り方をすべて変えてください。

Page 18: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型, 制御構造

多次元配列

Page 19: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型, 制御構造

多次元配列の基礎(p89)

配列を要素に持つ配列です。

1次元配列A B C D Echar c[5]c[0] c[1] c[2] c[3] c[4]

2次元配列

A B C D E

char c[3][5]

F G H I J

K L M N O

c[0]

c[1]

c[2]

[0] [1] [2] [3] [4]要素は c[0][0] から c[2][4] までの15個

c[0], c[1], c[2] が,要素数 5 の配列を持っている

c[0][0] : A c[1][3] : I c[2][2] : M

今までの配列

Page 20: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型, 制御構造

多次元配列の宣言と代入宣言:メモリ内に領域を確保する

型名 配列変数名[要素数][要素数]・・・

char c[3][5] (2次元配列)char c[3][5][9] (3次元配列)

多次元配列の宣言

要素の代入

c[0]

c[1]

c[2]

[0] [1] [2] [3] [4]

char c[3][5];

c[1][4] = ‘L’;L

c[0]

c[1]

c[2]

[0] [1] [2] [3] [4]

使って 3次元配列程度でしょうか

Page 21: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型, 制御構造

メモリの確保メモリの中の様子

1 1 0 1 1 0 0 10 1 1 1 0 0 0 0

1 1 0 0 0 0 1 11 0 0 0 1 0 0 00 0 1 1 1 0 0 01 0 0 1 1 1 0 01 0 0 1 1 1 0 01 0 0 1 1 1 0 01 0 0 1 1 1 0 01 0 0 1 1 1 0 01 0 0 1 1 1 0 01 0 0 1 1 1 0 01 0 0 1 1 1 0 0

100101102103104105106107108109111112113114

char a[0][0]char a[0][1]char a[0][2]char a[0][3]char a[0][4]char a[1][0]char a[1][1]char a[1][2]char a[1][3]char a[1][4]char a[2][0]char a[2][1]

char a[3][5] を宣言した場合の例アドレス  メモリ空間

多次元配列も 全ての要素が連続して確保される。

a[0][] の後に a[1][] がくる

a[0] a[1] a[2] が 5つの要素をそれぞれ持っている というイメージがあれば 繋がり方も納得いきます。

Page 22: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型, 制御構造

多次元配列の初期化初期化:宣言と同時に初期値を与える

その1:要素数も要素も全部書くchar c[3][5] = {{‘a’, ‘b’, ‘c’, ‘d’, ‘e’}, {‘f’, ‘g’, ‘h’, ‘i’, ‘j’}, {‘k’, ‘l’, ‘m’, ‘n’, ‘o’}};

要素5つの配列 が 3 つあることに注意

その2:要素数も要素も全部書く ver.2char c[3][5] = {‘a’, ‘b’, ‘c’, ‘d’, ‘e’, ‘f’, ‘g’, ‘h’, ‘i’, ‘j’, ‘k’, ‘l’, ‘m’, ‘n’, ‘o’};

1次元配列のように初期化する

どちらも同じですが,上を推奨します。

Page 23: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型, 制御構造

多次元配列の初期化2初期化:宣言と同時に初期値を与える

その3:すべてを 0 (ヌル文字)へchar c[3][5] = {};char c[3][5] = {0}; どちらも同じです。

メモリとの関係を思い出すと, 初期化をどこまで省略できるか理解できます。

その4:省略

int n []= {0,1,2,3,4}; という表記が可能でした。多次元配列だとどこまで省略できるでしょうか

1次元配列では

Page 24: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型, 制御構造

初期化の省略とメモリの配置1メモリの確保の際に必須の情報があります

1 1 0 1 1 0 0 10 1 1 1 0 0 0 0

1 1 0 0 0 0 1 11 0 0 0 1 0 0 00 0 1 1 1 0 0 01 0 0 1 1 1 0 01 0 0 1 1 1 0 01 0 0 1 1 1 0 01 0 0 1 1 1 0 01 0 0 1 1 1 0 01 0 0 1 1 1 0 01 0 0 1 1 1 0 01 0 0 1 1 1 0 0

100101102103104105106107108109111112113114

char a[0][0]char a[0][1]char a[0][2]char a[1][0]char a[1][1]char a[1][2]

アドレス  メモリ空間 char a[2][3] = { {‘a’, ‘b’, ‘c’}, {‘d’, ‘e’, ‘f’} }     の初期化の省略を考える省略 その1(コンパイルエラー)char a[][] = { {‘a’, ‘b’, ‘c’}, {‘d’, ‘e’, ‘f’} }

abcdef

空きスペースc,f の後の要素が省略される(かも)d のメモリ上の位置が決まらず 確保できない。

Page 25: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型, 制御構造

初期化の省略とメモリの配置2メモリの確保の際に必須の情報があります

1 1 0 1 1 0 0 10 1 1 1 0 0 0 0

1 1 0 0 0 0 1 11 0 0 0 1 0 0 00 0 1 1 1 0 0 01 0 0 1 1 1 0 01 0 0 1 1 1 0 01 0 0 1 1 1 0 01 0 0 1 1 1 0 01 0 0 1 1 1 0 01 0 0 1 1 1 0 01 0 0 1 1 1 0 01 0 0 1 1 1 0 0

100101102103104105106107108109111112113114

char a[0][0]char a[0][1]char a[0][2]char a[1][0]char a[1][1]char a[1][2]

アドレス  メモリ空間 省略 その2(コンパイルエラー)

char a[2][] = { {‘a’, ‘b’, ‘c’}, {‘d’, ‘e’, ‘f’} }

abcdef

空きスペース

c の後ろに要素が何個あるかわからない d の前に不定個数の要素が入るかも

メモリの確保ができない

Page 26: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型, 制御構造

初期化の省略とメモリの配置3メモリの確保のさいに必須の情報があります

1 1 0 1 1 0 0 10 1 1 1 0 0 0 0

1 1 0 0 0 0 1 11 0 0 0 1 0 0 00 0 1 1 1 0 0 01 0 0 1 1 1 0 01 0 0 1 1 1 0 01 0 0 1 1 1 0 01 0 0 1 1 1 0 01 0 0 1 1 1 0 01 0 0 1 1 1 0 01 0 0 1 1 1 0 01 0 0 1 1 1 0 0

100101102103104105106107108109111112113114

char a[0][0]char a[0][1]char a[0][2]char a[1][0]char a[1][1]char a[1][2]

アドレス  メモリ空間 省略 その3(コンパイル可能)char a[][3] = { {‘a’, ‘b’, ‘c’}, {‘d’, ‘e’, ‘f’} }a

bcdef

空きスペース

c の後ろは要素が絶対ない。 f の後ろに 3つの固まりが何個 入るかわからない

空きスペースの前に確保される

どれだけ空いてるかは場合に依る。

Page 27: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型, 制御構造

3次元以上の配列基本的には同じです

配列の要素の配列の要素が配列になっている場合になります。3次元配列int xx[4][5][2] =  // 要素を 4 つ持つ配列のそれぞれの要素は // 要素を 5 つ持つ配列である。 その 5 つの要素は // 要素を 2 つ持つ配列になっている。

{ { {1,2}, {2,3}, {3,4}, {4,5}, {5,6} }, { {6,7}, {7,8}, {8,9}, {9,8}, {8,7} }, { {1,2}, {2,3}, {3,4}, {4,5}, {5,6} }, { {6,7}, {7,8}, {8,9}, {9,8}, {8,7} }

};

0で初期化するなら xx[4][5][2] = {0};

この要素は xx[2][2][0]

Page 28: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型, 制御構造

多次元配列とループの関係(p91)

n 次元配列を出力するなら n 回ループ

int main(){ const int xsz =3, ysz =4; double a[xsz][ysz] = { { 2.3, 8.4, 4.3, 1.2},

{ 8.2, 1.3, 8.1, 7.5}, { 3.3, 3.1, 9.8, 5.3} };

for( int i=0; i < xsz; i++){ for(int j =0; j < ysz; j++){ cout << a[i][j] << “ ”;

} cout << endl;

}

return 0; }

単純にループするしかない

Page 29: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型, 制御構造

多次元配列とループの関係n 次元配列を入力するのも n 回ループ

int main(){ const int xsz =3, ysz =4; double a[xsz][ysz]; // 2次元配列を宣言

for( int i=0; i < xsz; i++){ for(int j =0; j < ysz; j++){ cin << a[i][j];

} }

-出力は省略- return 0; }

単純にループして受け取る

3 次元だろうが 4 次元だろうが同じです。

Page 30: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型, 制御構造

練習問題多次元配列の基礎

アルファベットが格納された配列 alpha を用意 しました。

$@KEYAKISAI$ って出力して下さい。

Page 31: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型, 制御構造

行列を扱う(p93)

行列計算ができそうです。

まず行列を思い出す

�a bc d

�2 x 2 行列

2行

�a bc d

�1行

1列 2列 行列行が横・列が縦

2行2列行列とも言います。 n 行,m 列の要素を (n,m) と書きます。

転置行列 行と列がひっくり返った行列です

A =

�a bc d

�AT =

�a cb d

�転置記号

要素(n,m) が (m,n)になる。 でもう通じますね!

Page 32: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型, 制御構造

転置行列を出力プログラム上では 0 スタートに注意

前略 int main(){ const int sz = 2;

int data[sz][sz] = {{1,2},{3,4}};

// 転置行列を出力 for(int i =0; i < size; i++){ for(int j =0; j < size; j++){ cout << data[j][i] << “ “;

} end << endl; }

後略

2 x 2 行列の転置行列を出力

DATA =

�1 23 4

要素(i,j) を 要素(j,i)で出力する。

Source

Result1 3 2 4

では n x m 行列に拡張してみましょう。

DATAT =

�1 32 4

Page 33: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型, 制御構造

n x m 行列の転置(p.93)

(n,m) と(m,n)を入れ替えるのは同じ前略 int main(){ const int n = 3; // 行の要素数 const int m = 4; // 列の要素数

int data[n][m] = {0}; // 0 で初期化

// 入力部は省略

// 転置行列を出力 for(int i =0; i < m; i++){ // 行方向 for(int j =0; j < n; j++){ // 列方向 cout << data[j][i] << “ “;

} end << endl; } 後略

任意の行列は 2次元配列で表現できる

n x m 行列は m x n 行列として出力される。

3 x 4 4 x 3

Page 34: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型, 制御構造

逆行列の計算(p94)

の前に逆行列って何だっけ?正方行列

2x2行列の逆行列

A =

�a bc d

� 逆行列記号

2x2 行列・3x3 行列の用に行と列の数が同じ行列を正方行列といいます。

逆行列 正方行列に掛けると単位行列になる行列

正方行列 A に対して左を満たす B が A の逆行列 (E は単位行列)AB = E = BA

A�1 =1

ad � bc

�d �b

�c a

行列式 ( det : determinant)

行列式が 0 だと逆行列は存在しない。

逆行列が存在する 正方行列のことを 正則行列と言います

Page 35: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型, 制御構造

逆行列を求める1(p.94)

行列の宣言と初期化まで

前略 int main(){ const int n = 2; // 行と列の大きさが同じ(正方行列)

double a[n][n] = {{1.0,3.0},{5.0,7.0}}; // 初期化

// 行列 a を出力          for(int i =0; i < n; i++){ for(int j =0; j < n; j++){     // 行列の出力 cout << data[i][j] << “ “;

} end << endl; }

つづく

Page 36: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型, 制御構造

逆行列を求める2(p.94)

逆行列存在の判定つづき

// 行列式を求めて 大きさを判定         const double epsilon = 1.0e-8 const double det = a[0][0]*a[1][1] - a[0][1]*a[1][0]; // ad -bc の計算

if(abs(det) < epsilon){ // det の絶対値がとても小さいと駄目 cout << “no inverse” << endl; return 1;

} つづくなぜ det == 0 ではないのかdouble 型は有効桁数が決まっています。有効桁の限界と数値0の間には無限個の数が ありますが,これらを全部0と見なさないと破綻します。

Page 37: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型, 制御構造

逆行列を求める3(p.94)

逆行列の計算と出力つづき

// 逆行列を求める         double ia[n][n]; // 逆行列の大きさは元と同じ正方行列

ia[0][0] = a[1][1] / det; ia[0][1] = -a[0][1] / det; ia[1][0] = -a[1][0] / det; ia[1][1] = a[0][0] / det;

// 逆行列 ia を出力 cout << ia[0][0] << “ “ << ia[0][1] << ‘\n’ << ia[1][0] << “ “ << ia[1][1] << endl;

終了処理略

A�1 =1

ad � bc

�d �b

�c a

かなり泥臭い上に 2x2 しか使えません。(がしょうがない)

Page 38: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型, 制御構造

逆行列を求める4(p.94)

単位行列であることをチェックおまけ

// 逆行列 ia を出力 cout << ia[0][0]*ia[0][0] + a[0][1]*ia[1][0] << “ “ << ia[0][0]*ia[0][1] + a[0][1]*ia[1][1] << ‘\n’ << ia[1][0]*ia[0][0] + a[1][1]*ia[1][0] << “ “ << ia[1][0]*ia[0][1] + a[1][1]*ia[1][1] << endl;

�a1 a2

a3 a4

��b1 b2

b3 b4

�=

�a1b1 + a2b3 a1b2 + a2b4

a3b1 + a4b3 a3b2 + a4b4

AA�1 = E =

�1 00 1

2x2の単位行列

めでたく逆行列を計算できました。

Page 39: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型, 制御構造

2次元配列の引数(p.95)

関数に引数を渡す

配列を関数に渡す: アドレスを渡してポインタで受け取る前略 const int col =3; // 大域変数としてサイズを宣言 void incr(int x[][col], int sz){ // ポインタで受け取る for(int i =0; i <sz; i++){ for(int j =0; j < sz; j++){

x[i][j]++; // 要素を+1 するだけ } } int main(){ const int row = 3; int a[row][col] = {{1,2,3},{4,5,6},{7,8,9}} incr(a,row); // 先頭アドレスとサイズを渡す

後略

列の数を固定する!!

Page 40: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型, 制御構造

列の数を固定する理由メモリとの関係に戻ります。

1 1 0 1 1 0 0 10 1 1 1 0 0 0 0

1 1 0 0 0 0 1 11 0 0 0 1 0 0 00 0 1 1 1 0 0 01 0 0 1 1 1 0 01 0 0 1 1 1 0 01 0 0 1 1 1 0 01 0 0 1 1 1 0 01 0 0 1 1 1 0 01 0 0 1 1 1 0 01 0 0 1 1 1 0 01 0 0 1 1 1 0 0

100101102103104105106107108109111112113114

char a[0][0]char a[0][1]char a[0][2]char a[0][3]char a[0][4]char a[1][0]char a[1][1]char a[1][2]char a[1][3]char a[1][4]char a[2][0]char a[2][1]

アドレス  メモリ空間 char a[3][5] で考えます。「a」 はa[0][0]のアドレス(102) のことです。

&a[0] とも書けます

列の数が固定されていないと 配列 a[0] の終わりがどこか理解できません

a[1][0] を呼び出されても反応できない。

反対に,列の数が固定されれば,a[1][0] も a[100][0] もいくつ先のアドレスを 見ればいいのかわかります。 (char 型であれば a[1][0] は5つ先, a[100][0]は500個先)

多次元配列の初期化で見たのと似てます

Page 41: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型, 制御構造

練習問題多次元配列を引数にする

10000個の配列が,それぞれ 0 - 9 の10個の要素 を持つような2次元配列を作成し,出力します。

戻り値のない setArray() 関数 戻り値のない printArray() 関数

を作成して出力結果に見合うようにソースコードを 補って下さい。

Page 42: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型, 制御構造

2次元配列の一部を渡す(p96)

ある行だけ関数に渡すことができます。void print_capital(const char s[]){ // char 型配列を受け取る for(int i=0; s[i] !=‘\0’; i++){      // ヌル文字が出てくるまで char c = s[i]; if(c >=‘a’ && c <= ‘z’) c = c - ‘a’+’A’ // 小文字を大文字に変換して出力 cout << c; } cout << endl;

}

int main(){ const int row = 3; const int col = 5; // 残りはヌル文字で埋まる const chat str[row][col] ={“a1cd”, “2eg”, “hi”}; for(int i=0; i<row; i++){ print_capital(str[i]);    // str[0], str[1], str[2] の先頭アドレスを渡す } retunr 0;

}

str[0] str[1] str[2]

Page 43: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型, 制御構造

string配列(p98)

string型の配列は2次元配列ぽくなりますstring 型変数は 1文字づつ要素にアクセスするときに配列っぽく 表記しました。string型の配列は2次元配列のようになります。

int main(){ const int size = 10; string a[size] = {"Sapporo", "Aomori", "Sendai", "Utsunomiya","Tokyo", "Nagoya", "Oosaka", “Fukuoka"}; // 残りはヌル文字で埋まる

const char x = ‘o’; // 探す文字 int n = 0;  // カウンタ for(int i=0; i<size; i++){ for(int j =0; s[j] != ‘\n’; j++){ if(s[i][j] == x) n++;  // 配列 i 番目の文字列の j 番目の文字 が x なら

} } cout << n << endl; retunr 0;

}

Page 44: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型, 制御構造

実験の諸注意注目!

口頭試問を受けたら僕宛にメールで Source Codeを送って下さい。(実行結果は必要ないです) [email protected]

座席は前から 3, 4列目 で変わらず。

ソースにコメント入れてから口頭試問に呼んで下さい。 コメントないと受け付けません。

Page 45: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型, 制御構造

実験問題の軽い説明

Page 46: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型, 制御構造

行列の足し算 これは単純

行列の掛け算 3x3 は思い出して下さい。�

a1 a2

a3 a4

��b1 b2

b3 b4

�=

�a1b1 + a2b3 a1b2 + a2b4

a3b1 + a4b3 a3b2 + a4b4

�a1 a2

a3 a4

�+

�b1 b2

b3 b4

�=

�a1 + b1 a2 + b2

a3 + b3 a4 + b4

2番の出力は,要素を書き下すのは禁止とします。 for文回して下さい。(とはいえ一回書き下すと分かりやすい)

問1 と 問2

Page 47: 応用プログラミングiui.ci.seikei.ac.jp/~takase/wp/wp-content/uploads/2014/...授業日程・内容 回数 日程 内容 テキスト 第1回 9/24 基本データ型, 制御構造

3番はがんばれ。とりあえず数字を1個出力してみましょうstring を使うと桁数を簡単に把握できます。 文字と数字の対応関係を考えればあとは簡単なんですが・・

#include<iostream> // 他必要あれば追加する #include “font.h”

using namespace std;これがスタートラインでしょうか

各自で font.h の中身を確認しておきましょう。

問3