180 likes | 302 Views
プログラミング演習 Ⅱ 第 13 回 文字列とポインタ(2). 情報・知能工学系 山本一公 kyama@tut.jp. 前回の課題の解説・ポイント(1). 課題11-1 配列は連続領域に確保される st [0][0] ~ st [2][5] でアドレスが 1 ずつ 増える 文字列リテラルは 必ずしも 連続した領域に確保されるわけでは ない が、ここの環境では連続した領域に確保される 配列と違って、必要な領域しか確保されない pt[1][3] と pt[2][0] のアドレスが同じに! 文字列の長さが変わると影響の出方も変わる. 前回の課題の解説・ポイント(2).
E N D
プログラミング演習Ⅱ第13回文字列とポインタ(2)プログラミング演習Ⅱ第13回文字列とポインタ(2) 情報・知能工学系 山本一公 kyama@tut.jp
前回の課題の解説・ポイント(1) • 課題11-1 • 配列は連続領域に確保される • st[0][0]~st[2][5]でアドレスが1ずつ増える • 文字列リテラルは必ずしも連続した領域に確保されるわけではない • が、ここの環境では連続した領域に確保される • 配列と違って、必要な領域しか確保されない • pt[1][3]とpt[2][0]のアドレスが同じに! • 文字列の長さが変わると影響の出方も変わる
前回の課題の解説・ポイント(2) • 配列の場合 • ポインタの場合 st[0][0] ↓ st[1][0] ↓ st[2][0] ↓ T u r b o \0 N A \0 \0 \0 \0 D O H C \0 \0 何が入っているか 分からない pt[0][0] ↓ pt[1][0] ↓ pt[2][0] ↓ 1 2 3 4 5 \0 1 2 \0 1 2 3 4 \0 ↑ pt[2][5] ↑ pt[1][3]
前回の課題の解説・ポイント(3) • 課題11-2 ポインタを入れる配列 実際に数値を入れる配列 1次元配列の 先頭アドレスが 入っている
課題10の採点結果から • 課題10-1 • 累和を入れる変数の初期化を忘れている人が何人かいた • 勝手に0に初期化してくれるので、ここ(計算機室)の環境で動かしていると気づきにくいが、コンパイラによっては正しく動かないので注意すること • 共通 • 課題が何か分かってない人が!
今日の内容 • 教科書 pp.254~265 • 文字列とポインタ • ポインタによる文字列の操作 • 文字列を扱うライブラリ関数
ポインタによる文字列の操作(1) • 文字列の長さを求める関数 • p.254, List 11-6 • 「ポインタをポインタらしく使って」 • ↓ここ • ↓今までなら、こんな感じ while (*s++) /* ポインタの指すところが移動して行く! */ len++; /* p.255, Fig.11-6 を見よ! */ while (s[len]) /* これで十分だけどね */ len++;
const なポインタ • ポインタを const で定義すると、「ポインタを介した値を書きかえること ができなくなる」 • 「ポインタ変数の値を書きかえることが できなくなる」んじゃないよ
ポインタによる文字列の操作(2) • 文字列をコピーする関数 • p.256, List 11-7 • 「ポインタをポインタらしく使って」 • ↓ここ • ↓今までなら、こんな感じ while (*d++ = *s++) /* ポインタの指すところが移動して行く! */ ; /* p.257, Fig.11-7 を見よ! */ while (d[i] = s[i]) /* これで十分だけど、上と比べると */ i++; /* iという変数が余分にいる */
文字列の不正なコピー • p. 258, List 11-8 • 文字列リテラルとして確保された領域へ上書きするのは良くないこと • そもそも処理系によってはできない • 文字列リテラルは const だと思っておけ! • 確保されていない領域への書き込み • p.259, Fig. 11-8 • 確保されている領域の外が使えるかどうか分からない……というか、普通は使っちゃダメ! • 行列も同じ!確保した領域より多く使っちゃダメ!
ポインタを返す関数 • p.259の下半分 • プログラムがちょっと短くなるだけで何が嬉しいのか……という感じ? • 例えば「文字列の途中のポインタを返す関数」「行列の中の、ある行ベクトルへのポインタを返す関数」というような使い方ができる • 前回の演習課題の解説のところで説明した malloc()は確保したメモリの先頭アドレスを返す
文字列を扱うライブラリ関数(1) • 文字列の長さを求める関数 • size_tstrlen(const char *s) • s が指す文字列の長さを返す • 文字列をコピーする関数 • char *strcpy(char *s1, const char *s2) • char *strncpy(char *s1, const char *s2, size_t n) • s2 が指す文字列を s1 が指す領域にコピーする • strncpy() の場合は n 文字コピー(足りない分は 0) • 返り値は s1 の値(普通、使わない)
文字列を扱うライブラリ関数(2) • 文字列を連結する関数 • char *strcat(char *s1, const char *s2) • char *strncat(char *s1, const char *s2, size_t n) • s1 が指す文字列の末尾に s2 が指す文字列を連結する • strncat() の場合は最大で n 文字連結 • 返り値は s1 の値(普通、使わない)
文字列を扱うライブラリ関数(3) • 文字列を比較する関数 • char *strcmp(const char *s1, const char *s2) • char *strncmp(const char *s1, const char *s2, size_t n) • s1 が指す文字列と s2 が指す文字列の文字コード(p.200)における大小関係の比較を行う • 等しければ 0を、s1 の方が大きければ正の整数値、s2 の方が大きければ負の整数値を返す • 「等しいときに 0 を返す」というのが感覚と逆なので、「文字列が等しければ」のつもりで 「if (strcmp(str1, str2)){…}」とやってしまいがち。注意。
文字列を扱うライブラリ関数(4) • 文字列を数値に変換する関数 • intatoi(const char *nptr) • 文字列を int 型の整数値に変換 • long atol(const char *nptr) • 文字列を long 型の整数値に変換 • double atof(const char *nptr) • 文字列を double 型の実数値に変換 • 結果の値がそれぞれの型で表現できないときの動作は未定義
今週の課題 • 教科書p. 260、演習11-2のプログラムを作成せよ。main関数等も作成して、完成したプログラムを作成すること。 • 教科書p. 262、演習11-5のプログラムを作成せよ。main関数等も作成して、完成したプログラムを作成すること。
レポートについて • 電子メールで提出 • 提出先は prog2@slp.cs.tut.ac.jp • Subjectを「プログラミング演習2 課題12提出 学籍番号・氏名 」とすること • C言語ソースファイルを添付する • メールの本文には何も書かなくて良いです • ソースファイルの頭にコメントで以下の情報を入れる • 学籍番号・氏名 • プログラムの説明(どのように動くのか、工夫した点等) • 実行結果(長い場合は一部)を貼る • 提出締切は、2月6日(水) 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へ直接質問しに来ても構いません