スライド13

プログラミング演習Ⅱ
第13回
文字列とポインタ(2)
情報・知能工学系
山本一公
[email protected]
前回の課題の解説・ポイント(1)
• 課題11-1
– 配列は連続領域に確保される
• st[0][0]~st[2][5]でアドレスが1ずつ増える
– 文字列リテラルは必ずしも連続した領域に確
保されるわけではない
• が、ここの環境では連続した領域に確保される
• 配列と違って、必要な領域しか確保されない
• pt[1][3]とpt[2][0]のアドレスが同じに!
– 文字列の長さが変わると影響の出方も変わる
前回の課題の解説・ポイント(2)
• 配列の場合
st[0][0]
↓
T
u
st[1][0]
↓
r
b
o
\0
N
A
st[2][0]
↓
\0
• ポインタの場合
pt[0][0]
↓
1
2
pt[1][0]
↓
3
4
5
\0
1
2
\0
\0
\0
D
O
1
↑
pt[1][3]
2
C
\0
\0
何が入っているか
分からない
pt[2][0]
↓
\0
H
3
4
\0
↑
pt[2][5]
前回の課題の解説・ポイント(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_t strlen(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)
• 文字列を数値に変換する関数
– int atoi(const char *nptr)
• 文字列を int 型の整数値に変換
– long atol(const char *nptr)
• 文字列を long 型の整数値に変換
– double atof(const char *nptr)
• 文字列を double 型の実数値に変換
– 結果の値がそれぞれの型で表現できないとき
の動作は未定義
今週の課題
1. 教科書 p. 260、演習11-2のプログラムを作成せ
よ。main関数等も作成して、完成したプログラ
ムを作成すること。
2. 教科書 p. 262、演習11-5のプログラムを作成せ
よ。main関数等も作成して、完成したプログラ
ムを作成すること。
レポートについて
• 電子メールで提出
– 提出先は [email protected]
– Subjectを「プログラミング演習2 課題12提出
番号・氏名 」とすること
– C言語ソースファイルを添付する
学籍
• メールの本文には何も書かなくて良いです
– ソースファイルの頭にコメントで以下の情報を入れる
• 学籍番号・氏名
• プログラムの説明(どのように動くのか、工夫した点等)
• 実行結果(長い場合は一部)を貼る
– 提出締切は、2月6日(水) 12:00 (1週間後)
授業用Webサイト
• URL:
http://www.slp.cs.tut.ac.jp/~kyama/programming2/
– 課題のpdfファイルが置いてあります。
– 授業で使ったpptファイルを置いていきます。
• 質問メールは、以下のどちらかのアドレスまで
– [email protected][email protected]
• C-515へ直接質問しに来ても構いません