180 likes | 305 Views
プログラミング演習 Ⅱ 第 11 回 ポインタ(2). 情報・知能工学系 山本一公 kyama@tut.jp. 前回の課題の解説・ポイント(1). 課題9-1 p.228 、 List 10-2 を参考に作成 printf () のアドレスを表示するための変換指定子は “%p” 全ての変数が連続した領域に確保されるわけでは ない ことが分かる 隙間があいている コンピュータがアクセスし易いように割りつけられる 配列 は 必ず 連続 した領域に確保 される. 前回の課題の解説・ポイント(2). 課題9-2 月日数が 31 日でない月の処理に注意
E N D
プログラミング演習Ⅱ第11回ポインタ(2) 情報・知能工学系 山本一公 kyama@tut.jp
前回の課題の解説・ポイント(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 10-10 • 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]; } intarray[100], num, value; value = function(array, num);
配列の受渡し(2) • 呼出し側 • 配列名だけ書いているので、“array” は “&array[0]” と同じ意味になり、配列の先頭アドレスを指す ⇒ それを関数に渡している intarray[100], num, value; value = function(array, num);
配列の受渡し(3) • 受け取り側 • 通常、“x[]” と “*x” は別物である • 配列変数は const である • 関数の仮引数では、同じもの(単なるアドレスの受渡し)になる int function(int x[], int no)/* 仮引数の場合のみ、 int*x でも同じ意味に */ { return x[no]; }
今週の課題(1) • 要素数nのdouble型配列arrayに入っている数値の平均を求めて返す関数 double ave(double *array, int n) を作成せよ。ただし、これはポインタを上手く扱えるようになるための演習課題なので、ave関数中で“[” “]”を使用してはならない。 main関数等も作成して、完成したプログラムを作成すること。 • 要素数nのint型配列arrayに入っている数値を昇順(小→大の順)に並べ替えて array に上書き格納する関数 void sort(int *array, int n) を作成せよ。ただし、こちらも、sort関数中で“[” “]”を使用してはならない。 main関数等も作成して、完成したプログラムを作成すること。
今週の課題(2) • 課題10-2のためのソートアルゴリズム • 何でも良い。適当に調べたものを使え。ネットで見つけたソースコードを参考にしても良い。 • 分からない人は以下のアルゴリズム(選択ソート)を使え • n個の要素の中で一番小さい値を探し、1番目の要素と交換する • 以下、k=2~n-1まで「k番目からn番目までの要素の中から一番小さい値を探し、k番目の要素と交換する」ことを繰り返す
レポートについて • 電子メールで提出 • 提出先は prog2@slp.cs.tut.ac.jp • Subjectを「プログラミング演習2 課題10提出 学籍番号・氏名 」とすること • C言語ソースファイルを添付する • メールの本文には何も書かなくて良いです • ソースファイルの頭にコメントで以下の情報を入れる • 学籍番号・氏名 • プログラムの説明(どのように動くのか、工夫した点等) • 実行結果(長い場合は一部)を貼る • 提出締切は、1月23日(水) 12:00 (1週間後)
授業用Webサイト • URL: http://www.slp.cs.tut.ac.jp/~kyama/programming2/ • 課題のpdfファイルが置いてあります。 • 授業で使ったpptファイルを置いていきます。 • 質問メールは、以下のどちらかのアドレスまで • kyama@tut.jp • prog2@slp.cs.tut.ac.jp • C-515へ直接質問しに来ても構いません