17
ププププププププププ 12 プ ププププププププ(1) ププ プププププ ププ [email protected]

プログラミング演習 Ⅱ 第 12 回 文字列とポインタ(1)

Embed Size (px)

DESCRIPTION

プログラミング演習 Ⅱ 第 12 回 文字列とポインタ(1). 情報・知能工学系 山本一公 [email protected]. 前回の課題の解説・ポイント. 課題10-1 ポインタ変数の扱いに慣れるのが目的 普通に平均を求めるだけ 課題 10-2 こちらも、ポインタ変数の扱いに慣れるのが目的 簡単なソートアルゴリズム 選択ソート(一番小さい数を見つけて入れ替え) バブルソート(隣合う2数を比較して入れ替え). 課題9の採点結果 から. 課題 9-1 配列に対して、要素毎のアドレスではなく、 先頭アドレスのみを表示しているケースがあった 課題9 - 2 - PowerPoint PPT Presentation

Citation preview

Page 1: プログラミング演習 Ⅱ 第 12 回 文字列とポインタ(1)

プログラミング演習Ⅱ第 12 回

文字列とポインタ(1)

情報・知能工学系山本一公

[email protected]

Page 2: プログラミング演習 Ⅱ 第 12 回 文字列とポインタ(1)

前回の課題の解説・ポイント• 課題10-1

– ポインタ変数の扱いに慣れるのが目的– 普通に平均を求めるだけ

• 課題10-2– こちらも、ポインタ変数の扱いに慣れるのが

目的– 簡単なソートアルゴリズム

• 選択ソート(一番小さい数を見つけて入れ替え)• バブルソート(隣合う2数を比較して入れ替え)

Page 3: プログラミング演習 Ⅱ 第 12 回 文字列とポインタ(1)

課題9の採点結果から• 課題9-1

– 配列に対して、要素毎のアドレスではなく、先頭アドレスのみを表示しているケースがあった

• 課題9-2– OK になってない人は、テストが不十分です– 自分の書いたプログラムがどういう挙動にな

るか、客観的に読めるようになりましょう

Page 4: プログラミング演習 Ⅱ 第 12 回 文字列とポインタ(1)

今日の内容• 教科書 pp.248 ~ 253• 文字列とポインタ

• 「文字列とポインタ」となっていますが、半分は「配列とポインタ」です

Page 5: プログラミング演習 Ⅱ 第 12 回 文字列とポインタ(1)

文字列リテラルとポインタ• 文字列リテラルは、メモリ上のどこかに確保さ

れている• 文字列リテラルを評価すると、文字列の先頭文

字へのポインタが返される

– 配列 str の最初の要素が’ A’ 、 2 番目の要素が’ B’ 、 3番目の要素が’ C’ 、 4 番目の要素が 0 で初期化される

– ptr には、メモリ上のどこかに確保された文字列の先頭アドレスが代入される• ptr が確保される場所と文字列リテラルの場所は無関係

char str[] = “ABC”; /* &str[0] =‘A’ のアドレス となる */ char *ptr = “123”; /* ptr = ‘1’ のアドレス となる */

Page 6: プログラミング演習 Ⅱ 第 12 回 文字列とポインタ(1)

配列とポインタの共通点• 配列で使う添字演算子“ [” “]” をポインタ

に対しても使うことができる– 効果も同じ– ポインタを使って、配列と同じことができる

– この場合、 ptr[0] は‘ 1’ 、 ptr[1] は‘ 2’ 、 ptr[2] は‘ 3’ である• C 言語では、配列の先頭アドレスしか見ていない

(要素数は無視)ので全く同じになる

char str[] = “ABC”; /* &str[0] =‘A’ のアドレス となる */ char *ptr = “123”; /* ptr = ‘1’ のアドレス となる */

Page 7: プログラミング演習 Ⅱ 第 12 回 文字列とポインタ(1)

配列とポインタの違い(1)• 配列変数は const 扱いなので、代入できない• ポインタ変数は代入できる

– 配列変数への文字列リテラルの代入は、初期化の場合のみ可能

– ポインタ変数の場合は、メモリ上のどこかに確保される文字列リテラルの先頭文字へのポインタが代入されるだけなのでプログラム中でも可能( Fig.11-3 )

char str[] = “ABC”; char *ptr = “123”;

str = “DEF”; /* エラー! */ ptr = “456”; /* 正しい! */

Page 8: プログラミング演習 Ⅱ 第 12 回 文字列とポインタ(1)

配列とポインタの違い(2)• 配列は、初期化時に要素数を指定できる

ので、使用しない領域を確保しておくことが可能( Fig.11-4(a) )

• ポインタはあくまでもアドレスを保持するだけの単独の変数( Fig.11-4(b) )– 文字列リテラルは、文字列に必要な領域しか

確保されない

Page 9: プログラミング演習 Ⅱ 第 12 回 文字列とポインタ(1)

文字列の配列(1)• 文字列の配列は、配列の配列で実現する場合と、

ポインタの配列で実現する場合で(メモリ上の実体が)かなり異なる

• 配列による文字列の配列の場合– C 言語での配列の配列( 2 次元配列)は、

1 次元配列を 2 次元的に扱っているだけ• char st[3][6] と定義されたものは実質 st[18] と同じ• st[2][5] は st[2 * 6 + 5] としてアクセスされる

– すなわち、メモリ上には連続的に配置される

Page 10: プログラミング演習 Ⅱ 第 12 回 文字列とポインタ(1)

文字列の配列(2)• ポインタによる文字列の配列の場合

– ポインタ配列の要素は、それぞれの文字列リテラルの先頭アドレスを指すだけ

– 文字列はそれぞれがメモリ上のどこかに存在する• 実際にどこに配置されるかは処理系依存

• Fig. 11-5– 配列で実現する場合は、 2 次元配列の初期化と同様

に、間に 0 が埋め込まれている– ポインタの場合は 0 は入らないし、連続した領域に

確保されてもいない• ポインタの配列も、他の配列と同じように扱われるので、

連続した領域に確保される

Page 11: プログラミング演習 Ⅱ 第 12 回 文字列とポインタ(1)

共通点・相違点まとめ• 共通点

– 配列にもポインタにも添字演算子が使える• 書き方も使い方も結果も同じ• 区別なく使って特に問題ない

• 相違点– 配列の配列( 2 次元配列)による文字列の配列

• その実体が連続した領域に確保される( 2 次元配列なので、文字のないところには 0 が入る)

• 配列なので、文字列の代入は初期化時しかできない。文字単位の置き換えはできる。

– ポインタの配列による文字列の配列• ポインタは連続した領域に確保されるが、実体は必ずしも連続した領域に

確保されるわけではない• 要素を別の文字列リテラルで置き換えることができる。

Page 12: プログラミング演習 Ⅱ 第 12 回 文字列とポインタ(1)

今週の課題1. 教科書 p.253, List 11-5 のプログラムを改造して、 st[0][0] ~ st[2]

[5] 、 pt[0][0] ~ pt[2][5] の各要素の内容とアドレスを表示するようにし、「配列による文字列」と「ポインタによる文字列」のそれぞれの文字列リテラルがメモリ上でどのように配置されているか調べよ。文字列の内容は List 11-5 から変更しないこと。

2. 1 次元配列の先頭アドレスをポインタ配列に代入すれば、 2 次元配列を実現できる。このようにして実現した 2 次元配列による行列の掛け算を行う関数(行列 a× 行列 b の結果を行列 ans に入れる関数。 a は n×m 行列、 b は m×l 行列、 ans は n×l 行列とする) void mat_mul(int *ans[], int *a[], int *b[], int n, int m, int l) を作成せよ。 main 関数なども作成して完成したプログラムを作ることとし、 main 関数の中で教科書 p.103, 演習 5-7 の配列を与えて関数を呼び出し掛け算を計算せよ。

Page 13: プログラミング演習 Ⅱ 第 12 回 文字列とポインタ(1)

課題2のヒント(1)• ポインタ配列を関数に渡す int main(void){ … char *ptr[3] = {“123”, “4567”, “78910”};

… function(ptr); …

void function(char *ptr[]){ …

Page 14: プログラミング演習 Ⅱ 第 12 回 文字列とポインタ(1)

課題2のヒント(2)• ポインタをポインタ配列に代入する int main(void){ … int a0[3], a1[3]; // 3 要素の 1 次元配列 int *ptr[2]; // 2 要素のポインタ配列

… ptr[0] = a0; ptr[1] = a1; // これで 2×3 の行列ができる // 行列要素の代入 ptr[0][0] = 1; ptr[0][1] = 2; ptr[0][2] = 3; ptr[1][0] = 4; ptr[1][1] = 5; ptr[1][2] = 6; …

Page 15: プログラミング演習 Ⅱ 第 12 回 文字列とポインタ(1)

課題2のヒント(3)• これ何の役に立つの?

– 1 次元配列は、 malloc() 関数によりプログラム中で可変長の領域を確保できるので、これを応用することによって任意の多次元可変長配列をプログラム中で作ることができる

int n, m, i; int **ptr; … // n × m の 2 次元配列を作る ptr = (int**)malloc(sizeof(int*) * n); // n 次元のポインタ配列 for (i = 0; i < n; i++) { ptr[i] = (int*)malloc(sizeof(int) * m); // m 次元の実配列 }

Page 16: プログラミング演習 Ⅱ 第 12 回 文字列とポインタ(1)

レポートについて• 電子メールで提出

– 提出先は [email protected]– Subject を「プログラミング演習2 課題 11提出 学籍番号・氏名 」とすること

– C 言語ソースファイルを添付する• メールの本文には何も書かなくて良いです

– ソースファイルの頭にコメントで以下の情報を入れる• 学籍番号・氏名• プログラムの説明(どのように動くのか、工夫した点等)• 実行結果(長い場合は一部)を貼る

– 提出締切は、 1月 30 日(水) 12:00 (1週間後)

Page 17: プログラミング演習 Ⅱ 第 12 回 文字列とポインタ(1)

授業用 Webサイト• URL:

http://www.slp.cs.tut.ac.jp/~kyama/programming2/– 課題の pdfファイルが置いてあります。– 授業で使った pptファイルを置いていきます。

• 質問メールは、以下のどちらかのアドレスまで– [email protected][email protected]

• C-515 へ直接質問しに来ても構いません