情報処理II

情報処理Ⅱ
2007年11月5日(月)
授業の進め方
構造体
プリプロセッサ
指令
その他の型
ライブラリ関数
「配列」と「ポインタ」は違うの?
 「変数」と「オブジェクト」は違うの?
2年以降で
さらに学習・習熟
ファイル入出力

識別子
算術型
制御文
演算子
配列・文字列
ポインタ
関数
変数の
有効範囲
再帰呼び出し
プログラムの作成・
コンパイル・実行
2
本日学ぶこと

配列(array),多次元配列,文字列


次に学ぶこと:ポインタ(pointer)
配列を使ってできること



平均や分散を求める
行列の積を求める
"Wakayama" という文字列を1文字ずつ分解する
3
配列とは?
配列は,同一の型のオブジェクトを1個以上連続して
記憶域(メモリ)に配置し利用するための機構である.



同一の型のオブジェクト: a[0]はint,a[1]はchar,とい
うのはNG.
1個以上: 1個でもいい.0個はNG.
連続して: 隙間がない.a[10]の次はa[11],その次は
a[12],…となる.
入p.237
リp.276
4
配列の宣言(1)

int a[3]; と宣言すると,3個のint型オブジェクトを確保
する.



a[0], a[1], a[2]が左辺値として使用できる.
宣言の形にも関わらず,a[3]は使用できない.代入したとき
の動作は不定.
「配列は0から始まる」と覚える.
a
a[0] a[1] a[2]
配列変数名:
参照可能だが
代入は不可.
オブジェクト:
代入と参照が
可能.
入p.237
リp.277
5
オブジェクトとは


実体,object
Cでは,「メモリに格納されている実体」のこと


「オブジェクト」という言葉が出てきたら,
値がメモリの中にどのような形で格納されるかを
イメージすること!
「オブジェクト指向」とは完全に無関係
a
a[0] a[1] a[2]
配列変数はオブジェクトではない…
メモリに割り付けられない
配列領域はオブジェクト…
メモリに割り付けられる
入p.238-239
リp.61
6
配列の宣言(2)

配列の個数(要素数,サイズ)は?




× 整数以外,負の数,0
× 変数や関数呼び出しを含む値
○ 正の整数値に評価される定数式(定数のみからなる式)
一括の宣言

int a[3], b[5]; のように,一つの宣言文で複数の配列
を宣言できる.
リpp.276-278
7
配列の初期化


int x = 0; と同様に,配列も初期化できる?
int a[3] = {100, 200, 300}; と書けばよい.


int a[3]; a[0] = 100; a[1] = 200; a[2] =
300; と同じ.
他の宣言例





○
○
○
?
×
リpp.194-195
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};
8
個数を明示しない宣言

int a[ ] = {100, 200, 300}; は
int a[3] = {100, 200, 300}; と同じ.



リp.194
要素数はコンパイル時に決まる.(実行時ではない.)
要素数を決め打ちする必要がなく,将来変更する可能性のあ
るとき,この書法が積極的に用いられる.
× int a[ ];
9
配列のサイズの求め方

aが配列変数のとき,sizeof(a) / sizeof(a[0]) で
そのサイズ(要素数)が求められる.


算術型に限らず,どんな配列変数でも成立する.
aがポインタ変数の場合や,mallocなどにより動的に確保し
た配列領域には,利用できない.
a[0] a[1] a[2]
…
a[9]
sizeof(a)
sizeof(a[0])
リp.282
10
合計・平均・最大・最小

問題

キーボードから10個の整数を読み取り,その合計・平均・最大
値・最小値を表示するプログラムを作りなさい.整数を読み取
るには,ライブラリ関数の scanf を使いなさい.
11
scanf

フォーマットに従って入力を読み込むライブラリ関数


使用例


参考:printfは,フォーマットに従って出力するライブラリ関
数
if (scanf("%d", &a) == 1) {
処理
}
不適切な使用例

while (scanf("%d", &a) != EOF) …
リpp.476-477
12
scanfの留意点

格納したい変数の型は,パターンに合わせる


格納したい変数の直前に「&」をつける


単項演算子の一つ.次回の授業で説明する.
関数の戻り値(関数を呼び出すことによって得られる値)で成
否を判断する


%d ⇒ int, %f ⇒ double, %ld ⇒ longなど
読み込めた個数を返す.失敗すれば,0または負
読み込みに失敗したら,入力が進まない.


「入力が進む」 ⇒ ストリーム
「while (scanf("%d", &a) != EOF)」と書いていて,
数字・空白以外の入力があると,無限ループに陥る
リpp.489-492
13
合計・平均・最大・最小 求め方(1)

概略




「キーボードから整数を読み取り」⇒scanf
「表示する」⇒printf
配列を使用する
個々の整数と,合計・最大値・最小値はint型,
平均はdouble型とする
入pp.106-107, pp.183-184
int10.c
14
合計・平均・最大・最小 求め方(2)

求め方の詳細





forを用いて,10個の整数を配列に格納する.途中で読み込
みに失敗したら,「input error」と出力して終了する.
forを用いて合計を求め,変数sumに格納する.
「(double)sum / 個数」により平均を求め,変数avgに格
納する.
最小値,最大値を格納する変数をそれぞれmin,maxとし,初
期値(暫定的な最小値,最大値)をいずれもa[0]とする.
a[1]~a[9]のそれぞれについて,現時点でのminと比較し,
配列中の値のほうが小さければ,それを最小値とする.最大値
についても同様に処理する.
人間の目なら10個の中の最大・最小を一瞬で見つけられるが,
コンピュータは2つの値の比較を繰り返して,求めなければならない.
15
多次元配列の宣言


多次元配列: 配列の配列
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]
リpp.278-281
オブジェクト:
代入と参照が
可能.
16
多次元配列の初期化(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]
リp.279
17
多次元配列の初期化(2)

他の初期化例






int a[3][3] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
int b[3][3] = {1, 2, 3, 4};
int c[3][3] = {{1, 2}, {3, 4}};
int d[2][2][2] = {{1, 2}, {3, 4}};
int e[2][2][2] = {{{1, 2}, {3, 4}}};
int f[ ][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8,
9}};
最も左だけ
省略可能
初期値が明示されて
いない要素には,0が
代入される.
リpp.197-204
multiarray.c
18
多次元配列の使い道

行列


n行m列の実行列なら,
double a[n][m];
•ただしnとmは定数と
すること.
•j行i列の値は,
a[j][i]
a[0][0]
a[1][0]
a[0][1]
…
a[0][m-1]
…
a[n-1][0]
a[n-1][m-1]
ゲームなどで用いられ
る,2次元の盤やフィー
ルド
19
文字列

文字列は,末尾に '\0' のつくchar配列である.



「ナル文字」または
「ヌル文字」という
'\0' は 0 と同一.文字を意識するときに使用する.
'a' の書式を文字定数という.ただし,int型の値である.
"a" の書式を文字列リテラルという.

文字列リテラルを直接書き換えることはできないが,配列変数
の初期化で代入し,そこを書き換えることは可能.
文字:
'a'
文字列:
"a"
'a'
'\0'
入pp.240-241
リp.51, pp.56-58, p.283
20
配列変数に文字列を格納するには

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'}; と同じ.

リpp.56-58
'\0' がないため,文字列ではない.
21
文字列をずらす


入力:
出力:
rotateword.c
"Wakayama"
Wakayama
akayamaW
kayamaWa
ayamaWak
yamaWaka
amaWakay
maWakaya
aWakayam
Wakayama
22
文字列をずらすには
(旧) word
'W'
'a'
'k'
'a'
'y'
'a'
'm'
'a'
'\0'
'k'
'a'
'y'
'a'
'm'
'a'
'W'
'\0'
c = 'W'
(新) word
'a'
23
まとめ




「型 変数名[要素数];」と宣言すると,変数名[0] ~ 変
数名[要素数-1] が利用できる.
配列とfor文を組み合わせて,配列の各要素に対して一律
の処理をすることができる.
多次元配列を用いると,2次元,3次元,…に自然に情報を格
納できる.
文字列は,末尾に '\0' のつく文字配列である.文字列を
配列に格納すれば,書き換えられる.
24