プログラミング演習Ⅱ 第11回 ポインタ(2) 情報・知能工学系 山本一公 [email protected] 前回の課題の解説・ポイント(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]; } • 要素数を書いても間違いではない – 呼び出し側では”[]”を付けない int array[100], num, value; value = function(array, num); 配列の受渡し(2) • 呼出し側 int array[100], num, value; value = function(array, num); – 配列名だけ書いているので、“array” は “&array[0]” と同じ意味になり、配列の先頭ア ドレスを指す ⇒ それを関数に渡している 配列の受渡し(3) • 受け取り側 int function(int x[], int no) /* 仮引数の場合のみ、 int *x でも同じ意味に */ { return x[no]; } – 通常、“x[]” と “*x” は別物である • 配列変数は const である – 関数の仮引数では、同じもの(単なるアドレ スの受渡し)になる 今週の課題(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. 2. n個の要素の中で一番小さい値を探し、1番目の要素と交換 する 以下、k=2~n-1まで「k番目からn番目までの要素の中から 一番小さい値を探し、k番目の要素と交換する」ことを繰 り返す レポートについて • 電子メールで提出 – 提出先は [email protected] – Subjectを「プログラミング演習2 課題10提出 番号・氏名 」とすること – C言語ソースファイルを添付する 学籍 • メールの本文には何も書かなくて良いです – ソースファイルの頭にコメントで以下の情報を入れる • 学籍番号・氏名 • プログラムの説明(どのように動くのか、工夫した点等) • 実行結果(長い場合は一部)を貼る – 提出締切は、1月23日(水) 12:00 (1週間後) 授業用Webサイト • URL: http://www.slp.cs.tut.ac.jp/~kyama/programming2/ – 課題のpdfファイルが置いてあります。 – 授業で使ったpptファイルを置いていきます。 • 質問メールは、以下のどちらかのアドレスまで – [email protected] – [email protected] • C-515へ直接質問しに来ても構いません
© Copyright 2024 ExpyDoc