情報処理II

情報処理Ⅱ
2005年11月11日(金)
授業の進め方
構造体
プリプロセッサ
指令
その他の型
ライブラリ関数
「配列」と「ポインタ」は違うの?
 「変数」と「オブジェクト」は違うの?
2年以降で
さらに学習・習熟
ファイル入出力

識別子
算術型
制御文
演算子
配列・文字列
ポインタ
関数
変数の
有効範囲
プログラムの作成・
コンパイル・実行
2
本日学ぶこと

配列(array),多次元配列,文字列


次に学ぶこと:ポインタ(pointer)
配列を使ってできること



平均や分散を求める
行列の積を求める
"Wakayama" → "akayamaW" → "kayamaWa" → … →
"Wakayama" のように1文字ずつずらして表示する
3
配列とは?
配列は,同一の型のオブジェクトを1個以上連続して
記憶域(メモリ)に配置し利用するための機構である.



同一の型のオブジェクト: a[0]はint,a[1]はchar,とい
うのはNG.
1個以上: 1個でもいい.0個はNG.
連続して: 隙間がない.a[10]の次はa[11],その次は
a[12],…となる.
4
配列の宣言(1)

int a[3]; と宣言すると,3個のint型オブジェクトを確保
する.



a[0], a[1], a[2]が左辺値として使用できる.
宣言の形にも関わらず,a[3]は使用できない.代入したとき
の動作は不定.
「配列は0から始まる」と覚える.
a
a[0] a[1] a[2]
変数名:
参照可能だが
代入は不可.
オブジェクト:
代入と参照が
可能.
5
配列の宣言(2)

配列のサイズは?




× 整数以外,負の数,0
× 変数や関数呼び出しを含む値
○ 正の整数値に評価される定数式(定数のみからなる式)
一括の宣言

int a[3], b[5]; のように,一つの宣言文で複数の配列
を宣言できる.
6
配列の初期化


int x = 0; と同様に,配列も初期化できる?
int a[3] = {100, 200, 300}; と書けばよい.


int a[3]; a[0] = 100; a[1] = 200; a[2] =
300; と同じ.
他の宣言例





○
○
○
?
×
int
int
int
int
int
a[3]
a[3]
a[3]
a[3]
a[3]
=
=
=
=
=
{100, 200, 300,};
初期値が明示されて
{100, 200};
いない要素には,0が
{0};
代入される.
{};
{100, 200, 300, 400};
7
要素数を明示しない宣言

int a[ ] = {100, 200, 300}; は
int a[3] = {100, 200, 300}; と同じ.



要素数はコンパイル時に決まる.(実行時ではない.)
要素数を決め打ちする必要がなく,将来変更する可能性のあ
るとき,この書法が積極的に用いられる.
× int a[ ];
8
配列の要素数の求め方

aを配列変数とすると,sizeof(a) / sizeof(a[0])
でその要素数が求められる.


算術型に限らず,どんな型でも成立する.
aがポインタ変数の場合や,mallocライブラリルーチンなどで
動的に確保した配列領域には,利用できない.
a[0] a[1] a[2]
…
a[9]
sizeof(a)
sizeof(a[0])
9
平均と分散を求めるプログラム

データ


平均は,総和を個数で割って求める.




int score[] = {
84, 88, 72, 62, 84, 80, 62, 68, 90, 84,
82, 72, 84, 84, 94, 59, 80, 98
};
和を格納する変数を別途用意しておく.
個数は?
… sizeof(score)/sizeof(score[0])
総和は整数型,平均は実数型
分散はΣ(値-平均)2を個数で割って求める.
10
多次元配列の宣言


多次元配列: 配列の配列
int a[2][2]; と宣言すると,
sizeof(int)が4のとき,
sizeof(a)は16
sizeof(a[0])は8
sizeof(a[0][0])は4
a
参照可能だが
代入は不可.
a[0]
a[1]
a[0][0] a[0][1] a[1][0] a[1][1]
オブジェクト:
代入と参照が
可能.
11
多次元配列の初期化(1)

int a[3][3] = {{1, 2, 3}, {4, 5, 6}, {7,
8, 9}};
a
a[0]
1
a[1]
2
3
4
a[2]
5
6
7
8
9
a[0][0] a[0][1] a[0][2] a[1][0] a[1][1] a[1][2] a[2][0] a[2][1] a[2][2]
12
多次元配列の初期化(2)

他の初期化例





int a[3][3] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
int a[3][3] = {1, 2, 3, 4};
int a[3][3] = {{1, 2}, {3, 4}};
int a[2][2][2] = {{1, 2}, {3, 4}};
int a[ ][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8,
9}};
最も左だけ
省略可能
初期値が明示されて
いない要素には,0が
代入される.
13
行列の積を求めるプログラム(1)

2×2の行列は int a[2][2]; で宣言.


float,double,unsigned intのほうがいい場合も
a と b の積を c に格納するとき:
b[0][0]
b[1][0]
b[0][1]
b[1][1]
a[0][0] a[0][1]
c[0][0] = a[0][0] * b[0][0] c[0][1] = a[0][0] * b[0][1]
+ a[0][1] * b[1][0]
+ a[0][1] * b[1][1]
a[1][0] a[1][1]
c[1][0] = a[1][0] * b[0][0] c[1][1] = a[1][0] * b[0][1]
+ a[1][1] * b[1][0]
+ a[1][1] * b[1][1]
14
行列の積を求めるプログラム(2)

一般に,


n×m と m×p の行列の積を求めることができ,
結果は n×p の行列になる.
c[i][j] = ∑0≦k≦m-1(a[i][k] * b[k][j])
これを 0≦i≦n-1,0≦j≦p-1 に対して計算すればよい.
p
m
n
n
p
15
文字列

文字列は,末尾に '\0' のつくchar配列である.



'\0' は 0 と同一.文字を意識するときに使用する.
'a' の書式を文字定数という.ただし,int型の値である.
"a" の書式を文字列リテラルという.

文字列リテラルを直接書き換えることはできないが,配列変数
の初期化で代入し,そこを書き換えることは可能.
文字:
'a'
文字列:
"a"
'a'
'\0'
16
文字列と配列変数

char a[ ] = "Wakayama"; は,
char a[9] = {'w', 'a', 'k', 'a', 'y', 'a',
'm', 'a', '\0'}; と同じ.



sizeof(a)/sizeof(a[0]) は8ではなく9.
char a[9] = "Wakayama"; も同じ.
char a[8] = "Wakayama"; は,
char a[8] = {'w', 'a', 'k', 'a', 'y', 'a',
'm', 'a'}; と同じ.

'\0' がないため,文字列ではない.
17
文字列をずらす
Wakayama
akayamaW
kayamaWa
ayamaWak
yamaWaka
amaWakay
maWakaya
aWakayam
Wakayama
18
文字列をずらすには
(旧) word
'W'
'a'
'k'
'a'
'y'
'a'
'm'
'a'
'\0'
'k'
'a'
'y'
'a'
'm'
'a'
'W'
'\0'
c = 'W'
(新) word
'a'
19
まとめ




「型 変数名[要素数];」と宣言すると,変数名[0] ~ 変
数名[要素数-1] が利用できる.
配列宣言と同時に,{ … } を用いて初期化も可能.
多次元配列を用いると,2次元,3次元,…に自然に情報を格
納できる.
文字列 "string" は,末尾に '\0' のつく文字配列で
ある.文字列を配列に格納すれば,書き換えられる.
20