プログラミング演習Ⅱ 第 11 回 ポインタ(2) 情報・知能工学系 山本一公
前回の課題の解説・ポイント(1) 課題9-1 –p.228 、 List 10-2 を参考に作成 –printf() のアドレスを表示するための変換指定 子は “%p” – 全ての変数が連続した領域に確保されるわけ ではないことが分かる 隙間があいている – コンピュータがアクセスし易いように割りつけられる 配列は必ず連続した領域に確保される
前回の課題の解説・ポイント(2) 課題9-2 – 月日数が 31 日でない月の処理に注意 特に閏日がある 2 月 – 閏年の判定方法 現在の暦(グレゴリオ暦)では – 西暦年が 4 で割り切れる年は閏年 – ただし、西暦年が 100 で割り切れる年は平年 – ただし、西暦年が 400 で割り切れる年は閏年 if ((*y % 4 == 0) && (*y % 100 != 0) || (*y % 400 == 0)) {…
課題8の採点結果から(1) 課題8-1 – 関数の中で変換用の文字配列を用意している と、処理できる文字列の長さがその配列の大 きさで制限されることになる 汎用性が下がる 元の文字配列上で 1 文字ずつ直接入れ替えれば、文 字列の長さに依存しない
課題8の採点結果から(2) 課題8-2 –toupper() / tolower() は関数の中で行わないと意味がな い 問題で指定された関数を作成しましょう – 一致・不一致の判定が最後の行の結果だけに依存し ているプログラムがあった – 長さの違うファイルをきちんと扱えていない File1 の後ろに何かを付け足して File2 を作って比較すると、 一致判定を出すプログラムが多かった – パターンをいろいろ考えてテストすべき
今日の内容 教科書 pp.238 ~ 245 ポインタと配列 ポインタの型 ポインタと配列 配列の受渡し
ポインタの型 p.239, List 10-9 のプログラム – warning は出るものの、コンパイルできるし、 動かすこともできる – しかし、 sizeof(int) と sizeof(double) が異なっ ているので、上手く動いていない –int と double なのだから、ある意味当然か ポインタの型が問題になりやすいのは、 ポインタ演算を行う場合 – 配列をやると分かりやすい …… かな?
ポインタと配列(1) p.240, List ptr = &vc[0] と初期化 “ptr + i” は、 ptr が指すオブジェクト(ここ では配列 vc[] の先頭)の i 個後ろの要素を 指すポインタとなる – すなわち、 *(ptr + i) ⇒ vc[i] と同じ
ポインタと配列(2) ここで「ポインタの型」の話に戻る “ptr + i” は、 “ メモリ上のアドレス ptr の i 番地後ろ ” ではなくて、 “ptr が指すオブジェクトの i 個後ろの要素 ” である – アドレスを決定するためには、1個のオブ ジェクトの大きさが分からないといけない – それを決めているのが「ポインタの型」
ポインタと配列(3) “float *ptr” だったら、 sizeof(float) は 4 [Byte] なので、 “ptr + 1” の実際のアドレ スは、 ptr に “4” を加えたものになる “double *ptr” だったら、 sizeof(double) は 8 [Byte] なので、 “ptr + 1” の実際のアドレ スは、 ptr に “8” を加えたものになる ポインタの型を正しく与えておけば、こ のような計算は自動で正しく行われる
ポインタと配列(4) いちいち “&vc[0]” って書くの面倒だよね “vc” とだけ書くと “&vc[0]” と同じ意味になる! – 例外1: “sizeof(vc)” の場合 – 例外2: “&vc” の場合 p.243, Column 10-2 – ポインタは単なるアドレスなので、配列の大きさ (領域)に対する配慮はプログラマが自分でしなけ ればならない それが “ 参照 ” との違い
配列の受渡し(1) 関数のところでやった、配列の受渡し – 関数定義側では、 ”[]” だけを付ける 要素数を書いても間違いではない – 呼び出し側では ”[]” を付けない int function(int x[], int no) /* int *x でも良いが、 厳密には意味が異なる */ { return x[no]; } int array[100], num, value; value = function(array, num);
配列の受渡し(2) 呼出し側 – 配列名だけ書いているので、 “array” は “&array[0]” と同じ意味になり、配列の先頭ア ドレスを指す ⇒ それを関数に渡している int array[100], num, value; value = function(array, num);
配列の受渡し(3) 受け取り側 – 通常、 “x[]” と “*x” は別物である 配列変数は const である – 関数の仮引数では、同じもの(単なるアドレ スの受渡し)になる int function(int x[], int no) /* 仮引数の場合のみ、 int *x でも同じ意味に */ { return x[no]; }
今週の課題(1) 1. 要素数 n の double 型配列 array に入っている数値の平均を 求めて返す関数 double ave(double *array, int n) を作成せ よ。ただし、これはポインタを上手く扱えるようにな るための演習課題なので、 ave 関数中で “[” “]” を使用し てはならない。 main 関数等も作成して、完成したプロ グラムを作成すること。 2. 要素数 n の int 型配列 array に入っている数値を昇順(小 → 大の順)に並べ替えて array に上書き格納する関数 void sort(int *array, int n) を作成せよ。ただし、こちらも、 sort 関数中で “[” “]” を使用してはならない。 main 関数等 も作成して、完成したプログラムを作成すること。
今週の課題(2) 課題10-2のためのソートアルゴリズム – 何でも良い。適当に調べたものを使え。ネットで見 つけたソースコードを参考にしても良い。 – 分からない人は以下のアルゴリズム(選択ソート) を使え 1.n 個の要素の中で一番小さい値を探し、 1 番目の要素と交換 する 2. 以下、 k=2 ~ n-1 まで「 k 番目から n 番目までの要素の中から 一番小さい値を探し、 k 番目の要素と交換する」ことを繰 り返す
レポートについて 電子メールで提出 – 提出先は –Subject を「プログラミング演習2 課題 10 提出 学籍 番号・氏名 」とすること –C 言語ソースファイルを添付する メールの本文には何も書かなくて良いです – ソースファイルの頭にコメントで以下の情報を入れる 学籍番号・氏名 プログラムの説明(どのように動くのか、工夫した点等) 実行結果(長い場合は一部)を貼る – 提出締切は、 1 月 23 日(水) 12:00 (1週間後)
授業用 Web サイト URL: – 課題の pdf ファイルが置いてあります。 – 授業で使った ppt ファイルを置いていきます。 質問メールは、以下のどちらかのアドレスまで C-515 へ直接質問しに来ても構いません