スライド11

プログラミング演習Ⅱ
第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へ直接質問しに来ても構いません