情報処理Ⅱ 2006年11月8日(金)
授業の進め方 構造体 その他の型 2年以降で さらに学習・習熟 プリプロセッサ 指令 ライブラリ関数 ファイル入出力 「配列」と「ポインタ」は違うの? 「変数」と「オブジェクト」は違うの? 配列・文字列 ポインタ 関数 変数の 有効範囲 識別子 算術型 再帰呼び出し 制御文 演算子 プログラムの作成・ コンパイル・実行
本日学ぶこと 配列(array),多次元配列,文字列 配列を使ってできること 次に学ぶこと:ポインタ(pointer) 平均や分散を求める 行列の積を求める "Wakayama" という文字列を1文字ずつ分解する
配列とは? 配列は,同一の型のオブジェクトを1個以上連続して 記憶域(メモリ)に配置し利用するための機構である. 同一の型のオブジェクト: a[0]はint,a[1]はchar,というのはNG. 1個以上: 1個でもいい.0個はNG. 連続して: 隙間がない.a[10]の次はa[11],その次はa[12],…となる.
配列の宣言(1) int a[3]; と宣言すると,3個のint型オブジェクトを確保する. a a[0] a[1] a[2] 「配列は0から始まる」と覚える. 変数名: 参照可能だが 代入は不可. a オブジェクト: 代入と参照が 可能. a[0] a[1] a[2]
余談:オブジェクトとは 実体,object Cでは,「メモリに格納されている実体」のこと 「オブジェクト指向」とは完全に無関係 a a[0] 「オブジェクト」という言葉が出てきたら, 値がメモリの中にどのような形で格納されるかを イメージすること! 「オブジェクト指向」とは完全に無関係 a 変数はオブジェクトではない… メモリに割り付けられない a[0] a[1] a[2] 配列領域はオブジェクト… メモリに割り付けられる
配列の宣言(2) 配列のサイズは? 一括の宣言 × 整数以外,負の数,0 × 変数や関数呼び出しを含む値 ○ 正の整数値に評価される定数式(定数のみからなる式) 一括の宣言 int a[3], b[5]; のように,一つの宣言文で複数の配列を宣言できる.
配列の初期化 int x = 0; と同様に,配列も初期化できる? int a[3] = {100, 200, 300}; と書けばよい. int a[3]; a[0] = 100; a[1] = 200; a[2] = 300; と同じ. 他の宣言例 ○ int a[3] = {100, 200, 300,}; ○ int a[3] = {100, 200}; ○ int a[3] = {0}; ? int a[3] = {}; × int a[3] = {100, 200, 300, 400}; 初期値が明示されていない要素には,0が代入される.
要素数を明示しない宣言 int a[ ] = {100, 200, 300}; は int a[3] = {100, 200, 300}; と同じ. 要素数はコンパイル時に決まる.(実行時ではない.) 要素数を決め打ちする必要がなく,将来変更する可能性のあるとき,この書法が積極的に用いられる. × int a[ ];
配列の要素数の求め方 aが配列変数のとき,sizeof(a) / sizeof(a[0]) でその要素数が求められる. a[0] a[1] 算術型に限らず,どんな型に対する配列型でも成立する. aがポインタ変数の場合や,mallocなどにより動的に確保した配列領域には,利用できない. a[0] a[1] a[2] … a[9] sizeof(a) sizeof(a[0])
合計・平均・最大・最小 問題 キーボードから10個の整数を読み取り,その合計・平均・最大値・最小値を表示するプログラムを作りなさい.整数を読み取るには,ライブラリ関数の scanf を使いなさい. 個人的には「キーボード」も「表示する」も使いたくないのですが, 他科目や他の書籍との兼ね合いもあり,これらの用語も理解しておくべきで あろうと考え,今回,取り入れました. なぜ使いたくないかについては,「キーボードから読み取る」のも「表示する」のも, このプログラムそのものではなく,より外の,実行環境がすることだからです. 関連:http://d.hatena.ne.jp/takehikom/20061025/1161726651
scanf フォーマットに従って入力を読み込むライブラリ関数 使用例 不適切な使用例 参考:printfは,フォーマットに従って出力するライブラリ関数 使用例 if (scanf("%d", &a) == 1) { 処理 } 不適切な使用例 while (scanf("%d", &a) != EOF) …
scanfの留意点 格納したい変数の型は,パターンに合わせる 格納したい変数の直前に「&」をつける %d ⇒ int,%f ⇒ double,%ld ⇒ longなど 格納したい変数の直前に「&」をつける 単項演算子の一つ.次回の授業で説明する. 関数の戻り値(関数を呼び出すことによって得られる値)で成否を判断する 読み込めた個数を返す.失敗すれば,0または負 読み込みに失敗したら,入力が進まない. 「入力が進む」⇒ストリーム 「while (scanf("%d", &a) != EOF)」と書いていて,入力が人手でかつミスタイプをすると,無限ループに陥る
合計・平均・最大・最小 求め方(1) 概略 「キーボードから整数を読み取り」⇒scanf 「表示する」⇒printf 合計・平均・最大・最小 求め方(1) 概略 「キーボードから整数を読み取り」⇒scanf 「表示する」⇒printf 配列を使用する(使用しなくても書ける) 個々の整数と,合計・最大値・最小値はint型, 平均はdouble型とする
合計・平均・最大・最小 求め方(2) 求め方の詳細 合計・平均・最大・最小 求め方(2) 求め方の詳細 forループを用いて,10個の整数を配列に格納する.途中で読み込みに失敗したら,「input error」と出力して終了する. forループを用いて合計を求め,変数sumに格納する. 「(double)sum / 個数」により平均を求め,変数avgに格納する. 最小値,最大値を格納する変数をそれぞれmin,maxとし,初期値(暫定的な最小値,最大値)をいずれもa[0]とする. a[1]~a[9]のそれぞれについて,現時点でのminと比較し,配列中の値のほうが小さければ,それを最小値とする.最大値についても同様に処理する. 人間の目なら10個の中の最大・最小を一瞬で見つけられるが, コンピュータは2つの値の比較を繰り返して,求めなければならない.
多次元配列の宣言 多次元配列: 配列の配列 int a[2][2]; と宣言すると, a a[0] a[1] a[0][0] a[0][1] sizeof(int)が4のとき, sizeof(a)は16 sizeof(a[0])は8 sizeof(a[0][0])は4 多次元配列: 配列の配列 int a[2][2]; と宣言すると, a 参照可能だが 代入は不可. a[0] a[1] オブジェクト: 代入と参照が 可能. a[0][0] a[0][1] a[1][0] a[1][1]
多次元配列の初期化(1) int a[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}; a a[0]
多次元配列の初期化(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が 代入される.
多次元配列の使い道 行列 ゲームなどで用いられる,2次元の盤やフィールド n行m列の実行列なら,double a[n][m]; j行i列の値は,a[j][i] ゲームなどで用いられる,2次元の盤やフィールド
文字列 文字列は,末尾に '\0' のつくchar配列である. 'a' の書式を文字定数という.ただし,int型の値である. 「ヌル文字」または「ナル文字」という 文字列は,末尾に '\0' のつくchar配列である. '\0' は 0 と同一.文字を意識するときに使用する. 'a' の書式を文字定数という.ただし,int型の値である. "a" の書式を文字列リテラルという. 文字列リテラルを直接書き換えることはできないが,配列変数の初期化で代入し,そこを書き換えることは可能. 'a' "a" 文字: 文字列: 'a' '\0'
配列変数に文字列を格納するには 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' がないため,文字列ではない.
文字列をずらす 入力: "Wakayama" 出力: Wakayama akayamaW kayamaWa ayamaWak
文字列をずらすには word 'W' 'a' 'k' 'a' 'y' 'a' 'm' 'a' '\0' 'W' c = word 'a' (旧) 'W' c = word 'a' 'k' 'a' 'y' 'a' 'm' 'a' 'W' '\0' (新)
まとめ 「型 変数名[要素数];」と宣言すると,変数名[0] ~ 変数名[要素数-1] が利用できる. 配列宣言と同時に,{ … } を用いて初期化も可能. 配列とforループを組み合わせて,配列の各要素に対して一律の処理をすることができる. 多次元配列を用いると,2次元,3次元,…に自然に情報を格納できる. 文字列は,末尾に '\0' のつく文字配列である.文字列を配列に格納すれば,書き換えられる.
第1回レポート課題のヒント まずは打ち込んでコンパイル・実行する. 問2,問5,問4,問3の順に検討するとよい.ただしレポートでは,設問順に解答を書く. 問3の「どんな事実」は,「数学的な性質」を明示できていればよい. プログラムを読むときには,「何を対象として」「何を使って」「何をするか」を常に確認すること. 問5は,出力そのものをレポートにつけてはならない. 「簡潔な日本語で表現する」能力は,プログラムの読解や,自分の作ったプログラムを他人に説明するときに,大いに役立つ. 見たことのない英単語は,辞書で引くか,インターネットで検索してみる.