200 likes | 409 Views
プログラミング演習 Ⅱ 第 10 回 ポインタ(1). 情報・知能工学系 山本一公 kyama@tut.jp. 前回の課題の解説・ポイント(1). 課題8-1 例えば、文字列の長さは こんな感じで分かるので、 後は str [ i ] と str [count – i – 1] をひっくり返せば良い。 文字列の長さは strlen () でも得られる. void rev_string (char str []) { … int count = 0; while ( str [count]) count++; /* 文字列の長さを得る */
E N D
プログラミング演習Ⅱ第10回ポインタ(1) 情報・知能工学系 山本一公 kyama@tut.jp
前回の課題の解説・ポイント(1) • 課題8-1 • 例えば、文字列の長さはこんな感じで分かるので、後はstr[i]とstr[count – i – 1]をひっくり返せば良い。 • 文字列の長さはstrlen()でも得られる void rev_string(char str[]) { … int count = 0; while (str[count]) count++; /* 文字列の長さを得る */ …
前回の課題の解説・ポイント(2) • 課題8-2 • 例えば、toupper()かtolower()を使って、大文字か小文字に統一してから比較する intstricomp(const char str1[], const char str2[]) { inti = 0; while (str1[i] != 0 || str2[i] != 0) { if (toupper(str1[i]) != toupper(str2[i])) { return 0; } i++; } return 1; }
課題7の採点結果から(1) • 課題7-1 • 「関数型」なのだから、関数と同じように使えないとダメ • 繰り返し使えないとダメ • ブロック化してないとダメ • 問題を変えない • もちろん変えたらダメに決まっています
課題7の採点結果から(2) • 課題7-2 • 行数をカウントする変数の初期化を忘れている人が多かった
課題7の採点結果から(3) • 行の途中でEOFが来ることを考慮すると intch, count = 0, cnum = 0; /* count:行数, cnum:処理している行の文字数 */ do { ch = getchar(); if (cnum == 0)/* 行頭だったら */ if (ch == EOF) break; else count++; if (ch == ‘\n’)cnum = 0; /* 改行で文字数を0に */ else cnum++; } while (ch != EOF); printf(“\nNumber of rows = %d\n”, count);
今日の内容 • 教科書 pp.225~237 • ポインタ • 計算機のメモリモデル • アドレス演算子 • ポインタ • 間接演算子 • ポインタと関数
計算機のメモリモデル • 変数の考え方 • 箱モデル ⇒ 独立の箱に変数の名前 • 実際の計算機のメモリ • 番地(アドレス)と変数名を対応させて記憶 (int) a (float) x floatなので、 4Byte分 a x …… 0 4 8 ☜ 番地
アドレス演算子 • 変数のアドレスを知りたい! • アドレス演算子 “&” • scanf()で使っていたアレ • 変数の”先頭番地”が値となる • “&a”は “4”、“&x”は“8”になる a x …… 0 4 8 ☜ 番地
ポインタ(1) • アドレスを知ると何の役に立つのか? • 変数を介さずにアドレスから直接変数を操作できる! • 配列や文字列の操作にとても便利 • 関数に副作用を起こさせるためにも便利 • 副作用:呼出し元の変数の値を書きかえる効果 • アドレスを格納する変数 ⇒ ポインタ型 • “*”を付けて宣言する int *ptr;
ポインタ(2) • int型のオブジェクト • 整数(int型)の値を格納する • intへのポインタ型のオブジェクト • ≪整数を格納する箱≫の“アドレス”を格納する int a, *ptra; ptra = &a; /* 変数 a のアドレスをポインタ変数 ptraに代入 */
間接演算子(1) • ポインタ変数に格納されているアドレスにはどんな値が入っているか? • 間接演算子 “*” で値を取り出せる • 変数宣言と同じ “*” int a, b, *ptra; ptra = &a; /* 変数 a のアドレスをポインタ変数 ptraに代入 */ a = 100; b = *ptra; /* “*ptra”は“a”と同じなので b には100 が入る!*/ a = 200; b = *ptra; /* b には200 が入る!*/
間接演算子(2) • 下の図のような場合 int *x, a, b; x = &a; /* 変数 a のアドレス(4)をポインタ変数 x に代入 */ a = 10; b = *x; /* “*x”は“a”と同じなので b には10 が入る!*/ *x x 4 a 10 b 10 …… 0 4 8 ☜ 番地
ポインタと関数(1) • C言語での関数の引数は“値渡し” • 関数の引数・変数は呼出し側の変数とは独立⇒ 呼出し側の変数の値は変更されない • “関数の独立性”という観点からは良いが、値を変更したいときもある • ポインタを関数に渡して間接的に変更する! • 1つの関数から複数の値を返したい場合にも使える
ポインタと関数(2) • ポインタでアドレスを渡す void function(int*b) /* 引数に“*”を付ける */ { if (*b < 10) *b = 10; /* bが示すアドレスに 10 を格納 */ } int main(void) { int a; … function(&a); /* 関数に a のアドレスを渡す */ /* 関数から戻ってくると、aの値が変わっている */ … }
ポインタと関数(3) • 下の図のような場合 • “&a”の値は“4” • 関数function()の引数“b” には“4”が渡される • アドレスが“値渡し”される • “*b”に代入すると、呼び出し元の“a”に値が入る *b a 10 b 4 …… 0 4 8 ☜ 番地
参照渡し • 変数の値ではなく変数の参照(変数の場所等、諸々の属性)を渡すやり方 • C言語にはない。C++言語にはある。 • ポインタ渡しは、“ポインタの値渡し” • ただし • C言語におけるポインタ渡しを、俗に“参照渡し”と呼んでいる • 本当の意味での“参照渡し”を指しているの か、俗な言い方での“参照渡し”を指しているのか、本を読んだりするときに気を付けること
今週の課題 • main関数の中で、char 型変数 a, b[3]、short型変数 c, d[3]、float型変数 e, f[3]、double型変数 g, h[3]を定義し、それぞれのアドレス(配列は各要素毎)を表示するプログラムを作成せよ。それぞれの変数がメモリ上でどのように配置されているか、確認することがこの課題の目的である。 • p.239、演習10-1のプログラムを作成せよ。main関数等も作成して、完成したプログラムを作成すること。
レポートについて • 電子メールで提出 • 提出先は prog2@slp.cs.tut.ac.jp • Subjectを「プログラミング演習2 課題9提出 学籍番号・氏名 」とすること • C言語ソースファイルを添付する • メールの本文には何も書かなくて良いです • ソースファイルの頭にコメントで以下の情報を入れる • 学籍番号・氏名 • プログラムの説明(どのように動くのか、工夫した点等) • 実行結果(長い場合は一部)を貼る • 提出締切は、1月16日(水) 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へ直接質問しに来ても構いません