情報処理II

情報処理Ⅱ
2006年11月8日(金)
授業の進め方
構造体
プリプロセッサ
指令
その他の型
ライブラリ関数
「配列」と「ポインタ」は違うの?
 「変数」と「オブジェクト」は違うの?
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],…となる.
4
配列の宣言(1)

int a[3]; と宣言すると,3個のint型オブジェクトを確保
する.



a[0], a[1], a[2]が左辺値として使用できる.
宣言の形にも関わらず,a[3]は使用できない.代入したとき
の動作は不定.
「配列は0から始まる」と覚える.
a
a[0] a[1] a[2]
変数名:
参照可能だが
代入は不可.
オブジェクト:
代入と参照が
可能.
5
余談:オブジェクトとは


実体,object
Cでは,「メモリに格納されている実体」のこと


「オブジェクト」という言葉が出てきたら,
値がメモリの中にどのような形で格納されるかを
イメージすること!
「オブジェクト指向」とは完全に無関係
a
a[0] a[1] a[2]
変数はオブジェクトではない…
メモリに割り付けられない
配列領域はオブジェクト…
メモリに割り付けられる
6
配列の宣言(2)

配列のサイズは?




× 整数以外,負の数,0
× 変数や関数呼び出しを含む値
○ 正の整数値に評価される定数式(定数のみからなる式)
一括の宣言

int a[3], b[5]; のように,一つの宣言文で複数の配列
を宣言できる.
7
配列の初期化


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};
8
要素数を明示しない宣言

int a[ ] = {100, 200, 300}; は
int a[3] = {100, 200, 300}; と同じ.



要素数はコンパイル時に決まる.(実行時ではない.)
要素数を決め打ちする必要がなく,将来変更する可能性のあ
るとき,この書法が積極的に用いられる.
× int a[ ];
9
配列の要素数の求め方

aが配列変数のとき,sizeof(a) / sizeof(a[0]) で
その要素数が求められる.


算術型に限らず,どんな型に対する配列型でも成立する.
aがポインタ変数の場合や,mallocなどにより動的に確保し
た配列領域には,利用できない.
a[0] a[1] a[2]
…
a[9]
sizeof(a)
sizeof(a[0])
10
合計・平均・最大・最小

問題

キーボードから10個の整数を読み取り,その合計・平均・最大
値・最小値を表示するプログラムを作りなさい.整数を読み取
るには,ライブラリ関数の scanf を使いなさい.
11
scanf

フォーマットに従って入力を読み込むライブラリ関数


使用例


参考:printfは,フォーマットに従って出力するライブラリ関
数
if (scanf("%d", &a) == 1) {
処理
}
不適切な使用例

while (scanf("%d", &a) != EOF) …
12
scanfの留意点

格納したい変数の型は,パターンに合わせる


格納したい変数の直前に「&」をつける


単項演算子の一つ.次回の授業で説明する.
関数の戻り値(関数を呼び出すことによって得られる値)で成
否を判断する


%d ⇒ int,%f ⇒ double,%ld ⇒ longなど
読み込めた個数を返す.失敗すれば,0または負
読み込みに失敗したら,入力が進まない.


「入力が進む」⇒ストリーム
「while (scanf("%d", &a) != EOF)」と書いていて,
入力が人手でかつミスタイプをすると,無限ループに陥る
13
合計・平均・最大・最小 求め方(1)

概略




「キーボードから整数を読み取り」⇒scanf
「表示する」⇒printf
配列を使用する(使用しなくても書ける)
個々の整数と,合計・最大値・最小値はint型,
平均はdouble型とする
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]
オブジェクト:
代入と参照が
可能.
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]
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が
代入される.
18
多次元配列の使い道

行列


n行m列の実行列なら,double a[n][m];
•ただしnとmは定数とすること.
•j行i列の値は,a[j][i]
ゲームなどで用いられる,2次元の盤やフィールド
19
文字列

文字列は,末尾に '\0' のつくchar配列である.



「ヌル文字」または
「ナル文字」という
'\0' は 0 と同一.文字を意識するときに使用する.
'a' の書式を文字定数という.ただし,int型の値である.
"a" の書式を文字列リテラルという.

文字列リテラルを直接書き換えることはできないが,配列変数
の初期化で代入し,そこを書き換えることは可能.
文字:
'a'
文字列:
"a"
'a'
'\0'
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'}; と同じ.

'\0' がないため,文字列ではない.
21
文字列をずらす


入力:
出力:
"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
第1回レポート課題のヒント



まずは打ち込んでコンパイル・実行する.
問2,問5,問4,問3の順に検討するとよい.ただしレポート
では,設問順に解答を書く.
問3の「どんな事実」は,「数学的な性質」を明示できていれ
ばよい.


問5は,出力そのものをレポートにつけてはならない.


プログラムを読むときには,「何を対象として」「何を使って」「何
をするか」を常に確認すること.
「簡潔な日本語で表現する」能力は,プログラムの読解や,自
分の作ったプログラムを他人に説明するときに,大いに役立つ.
見たことのない英単語は,辞書で引くか,インターネットで検
索してみる.
25