プログラミング演習II 2004年11月 16日(第5回) 理学部数学科・木村巌.

Slides:



Advertisements
Similar presentations
アルゴリズムと データ構造 第 3 回 基本的なデータ構造(2) : 配列 1. 前回の復習 アルゴリズムの計算量 最悪(最大)計算量 計算量の漸近的評価 (オーダ)  多項式時間アルゴリズム( polynomial time algorithm )  指数時間アルゴリズム( exponential.
Advertisements

プログラミング演習II 2004年11月 30日(第6回) 理学部数学科・木村巌.
15.1 文字列処理の基本 15.2 文字列処理用ライブラリ関数
情報基礎演習B 後半第5回 担当 岩村 TA 谷本君.
数理情報工学演習第一C プログラミング演習 (第3回 ) 2014/04/21
プログラミング入門2 第10回 動的な領域確保 情報工学科 篠埜 功.
ファーストイヤー・セミナーⅡ 第8回 データの入力.
データ構造とアルゴリズム 第10回 mallocとfree
プログラミング入門2 第10回 構造体 情報工学科 篠埜 功.
システムプログラミング 第5回 情報工学科 篠埜 功 ヒアドキュメント レポート課題 main関数の引数 usageメッセージ
プログラミング演習Ⅱ 第12回 文字列とポインタ(1)
岩村雅一 知能情報工学演習I 第9回(C言語第3回) 岩村雅一
プログラミング基礎I(再) 山元進.
プログラミング言語Ⅰ(実習を含む。), 計算機言語Ⅰ・計算機言語演習Ⅰ, 情報処理言語Ⅰ(実習を含む。)
12: コマンドライン引数 C プログラミング入門 総機1 (月1) Linux にログインし、以下の講義ページ を開いておくこと
プログラミング演習II 2004年10月19日(第1回) 理学部数学科・木村巌.
12: コマンドライン引数 C プログラミング入門 基幹7 (水5) Linux にログインし、以下の講義ページ を開いておくこと
第8回 プログラミングⅡ 第8回
理由:文字数より要素数の多い配列を用いた時に,文字列の最後を示すため
理由:文字数より要素数の多い配列を用いた時に,文字列の最後を示すため
プログラミング演習II 2004年12月 21日(第8回) 理学部数学科・木村巌.
ファイル操作と文字列の利用.
第3回 配列,構造体,ポインタ ~ データ構造について学ぶための基礎~
プログラミング論 関数ポインタ と 応用(qsort)
ちょっとした練習問題① 配列iroを['R', 'W', 'R', 'R', 'W' , 'W' , 'W']を宣言して、「W」のときの配列の番号をprintfで表示するようなプログラムを記述しなさい。
プログラミング論 II 2008年10月30日 文字列
精密工学科プログラミング基礎 第10回資料 (12/18実施)
プログラミング 4 記憶の割り付け.
プログラミング演習I 2003年6月25日(第10回) 木村巌.
2005年度 データ構造とアルゴリズム 第3回 「C言語の復習:再帰的データ構造」
プログラミング演習I 2003年5月7日(第4回) 木村巌.
第10章 これはかなり大変な事項!! ~ポインタ~
プログラミング入門2 第8回 ポインタ 情報工学科 篠埜 功.
岩村雅一 知能情報工学演習I 第9回(後半第3回) 岩村雅一
メモリの準備 メモリには、その準備の方法で2種類ある。 静的変数: コンパイル時にすでにメモリのサイズがわかっているもの。 普通の変数宣言
プログラミング入門2 第11回 情報工学科 篠埜 功.
前回の練習問題.
プログラミング入門2 第11回 情報工学科 篠埜 功.
第7回 プログラミングⅡ 第7回
P n ポインタの基礎 5 q m 5 7 int* p; int 型の変数を指すポインタ int* q; int 型の変数を指すポインタ int n=5, m=7; int 型の変数 int array[3]; int* pArray[3]; p = &n; ポインタにアドレスを代入しているのでOK.
09: ポインタ・文字列 C プログラミング入門 総機1 (月1) Linux にログインし、以下の講義ページ を開いておくこと
プログラミング基礎B 文字列の扱い.
岩村雅一 知能情報工学演習I 第9回(後半第3回) 岩村雅一
岩村雅一 知能情報工学演習I 第9回(C言語第3回) 岩村雅一
プログラミング演習I 2004年5月19日(第5回) 理学部数学科・木村巌.
オブジェクト指向言語論 第六回 知能情報学部 新田直也.
プログラミング言語論 第六回 理工学部 情報システム工学科 新田直也.
精密工学科プログラミング基礎Ⅱ 第5回資料 今回の授業で習得してほしいこと: 構造体 (教科書 91 ページ)
岩村雅一 知能情報工学演習I 第9回(後半第3回) 岩村雅一
15.1 文字列処理の基本 15.2 文字列処理用ライブラリ関数
プログラミング入門2 第9回 ポインタ 情報工学科 篠埜 功.
プログラミング演習I 2003年4月30日(第3回) 木村巌.
文字列へのポインタの配列 static char *lines[MAXLINES]; lines[0] NULL
プログラミング演習I 2003年7月2日(第11回) 木村巌.
09: ポインタ・文字列 C プログラミング入門 基幹7 (水5) Linux にログインし、以下の講義ページを開いておく こと
第5回 プログラミングⅡ 第5回
情報処理Ⅱ 第7回 2004年11月16日(火).
プログラミング 4 文字列.
11: 動的メモリ確保 C プログラミング入門 基幹2 (月4) Linux にログインし、以下の講義ページ を開いておくこと
プログラミング演習I 2003年6月11日(第9回) 木村巌.
情報処理Ⅱ 2005年11月25日(金).
15.1 文字列処理の基本 15.2 文字列処理用ライブラリ関数
プログラミング演習II 2003年11月19日(第6回) 木村巌.
プログラミング演習II 2003年12月10日(第7回) 木村巌.
プログラミング演習II 2004年11月 2日(第3回) 理学部数学科・木村巌.
プログラミング入門2 第5回 配列 変数宣言、初期化について
プログラミング演習II 2003年10月29日(第2,3回) 木村巌.
岩村雅一 知能情報工学演習I 第7回(後半第1回) 岩村雅一
12: コマンドライン引数 C プログラミング入門 基幹2 (月4) Linux にログインし、以下の講義ページ を開いておくこと
岩村雅一 知能情報工学演習I 第9回(C言語第3回) 岩村雅一
Presentation transcript:

プログラミング演習II 2004年11月 16日(第5回) 理学部数学科・木村巌

前回までの復習 配列とポインタの関係 引数と配列

今日学ぶこと 文字列とポインタ 文字列の操作 動的なメモリの確保 関数ポインタ 教科書10.3から(p. 317~)

文字列をポインタで扱う 7章で見たように、C言語には「文字列型」というものは存在せず、char型の配列(で、最後の要素が’\0’になっているもの)で代用しているのだった char str[] = “Hello”; これは、次と同じ char str[] = {‘H’, ‘e’, ‘l’, ‘l’, ‘o’, ‘\0’};

文字列をポインタで扱う(続) char型のポインタで扱うことも出来る: char *str = “Hello”; ポインタで扱う場合は、どこかに、”Hello”を保存するのに必要なだけのメモリが確保され、その先頭のアドレスがstrというchar型のポインタ変数strに保存される 教科書の図10-7(318頁参照) Sample8.cを打ち込んで、コンパイル・実行してみよう

配列とポインタとの違い 配列には、一度初期化した後で、再び代入することは出来ない char str[] = “Hello”; str = “Goodbye”; /* これは出来ない */ 実際に試してみて、どのようなエラーメッセージが表示されるか確認しよう! しかし、ポインタを使うばあいは、再代入することが出来る(図10-8、320頁)

文字列を入力する場合 配列を宣言して、文字列を格納する領域を確保しておく: char str[100]; /* 文字列を格納する配列 */ scanf (“%s”, str); /* 配列に文字列を格納 */ ポインタを使う場合は、文字列を格納する領域を、動的に確保する(malloc()を使う、後述)

文字列への再代入 標準ライブラリ関数に、文字列の再代入を行う関数がある 実際は、文字列をメモリ上のどこかにコピーしてくれる関数strcpy() 後述

文字列の配列 複数の文字列を、文字列の配列1つにまとめることが出来る Sample9.cを打ち込んで、コンパイル・実行してみよう char str[3][20] = {“Hello”, “Goodbye”, “Thankyou”}; 19文字までの文字列が3つからなる、文字列の配列 図10-9を参照

文字列ポインタの配列 文字列はポインタとしても扱える 文字列のポインタの配列として、複数の文字列をまとめて扱うことも出来る char *str[3] = {“Hello”, “Goodbye”, “Thankyou”}; ポインタの配列として実現されている.図10-10, 325頁を参照

文字列の操作 標準ライブラリ関数には、文字列を操作するための関数が多数用意されている string.h というヘッダーファイルをインクルードする #include <string.h>

文字列操作用の関数(例) size_t strlen (const char *str); 文字列strの長さ(最後のNULLを除く) char *strcpy (char *str1, const char *str2); 文字列str2をstr1にコピーし、str1を返す char *strcat (char *str1, const char *str2); 文字列str2をstr1の末尾に追加してstr1を返す int strcmp (const char *str1, const char *str2); 文字列str1, str2を辞書式順序で比較し、str1がstr2より小さい、等しい、大きいに応じて、負、0、正の値を返す

文字列の長さを調べる 入力された文字列の長さを返すプログラムSample11.c 入力して、コンパイル・実行してみよう 文字列の長さを知るには、strlen()を使う(string length) strlen()を自分で書いてみよ

文字列をコピーする 文字列を配列に代入した場合、再代入が出来ないのだった 配列の各要素に、一文字ずつ代入することはできる 簡単な関数で実現できる(書いてみよ)が、これも標準ライブラリ関数strcpy()として用意されている Sample12.cを打ち込んで、コンパイル・実行してみよう コピー先に、コピー元が収まるだけのメモリがあることを保証するのは、プログラマの責任

文字列を連結する char *strcat (char *str1, const char *str2); 一つの文字列strの末尾に、もう一つの文字列str2を連結するという処理を行うのが、strcat()関数(string conCATenate) str1が指しているメモリに、連結した後の文字列が収まるだけのメモリがあることを保証するのは、プログラマの責任 Sample12.cを入力し、コンパイル・実行してみよう

配列の大きさに注意 上でも述べたように、strcpy()のコピー先、またstrcat()の連結先に、十分なメモリがあることを保証するのは、プログラマの責任 そうでない場合、配列の最後の要素を超えて書き込まれる 何が起こるか分かりません また、strcpy()で、コピー元とコピー先が重なっている場合の挙動も未定義

文字列を比較する strcmp()関数(string compare)は、引数を比較し、一致していた場合は0を返す Sample14.cを入力し、コンパイル・実行してみよう 必ずしも同じ長さの配列でなくても良い

文字列の長さを実行時に決める これまでのプログラムでは、文字列の長さは(配列の長さとして)、コンパイル時に(つまり、プログラムの実行が始まる前に)決まっていた プログラムの実行中に、文字列の長さを決めることが出来ると便利である 文字列に限らず、任意の大きさのメモリを、実行中に確保・開放できる:malloc()とfree()

void *malloc(size_t n)関数 #include <stdlib.h> を忘れないこと プログラムの実行時に、必要なサイズ(n bytes)のメモリを確保して、そのメモリのアドレスを返す 任意の型にキャストできるように、返値の型はvoid * (void型へのポインタ) メモリの確保に失敗した場合は、NULLポインタが返る

void *free(void *p)関数 pが指すメモリ領域を開放し、後のmalloc()などに使えるようにする ほとんどのOS(たとえばMicrosoft Windows, FreeBSD, Linuxなど)では、プログラムが正常に終了すれば、そのプログラムが使ったメモリは自動的に開放される 長時間実行され続けるプログラムでは、malloc()して不要になったメモリを正しく開放するのは重要。そうでないと、使用可能なメモリが減少していく(memory leakという)

動的なメモリ確保の例 Sample15.cを入力し、コンパイル・実行してみよう 型Tの要素n個を保持するメモリは、sizeof (T) * n bytes たとえば、T = char なら、n文字からなる文字列を保持するのに必要なのは sizeof (char) * (n+1) bytes. 最後の’\0’用に1足している

関数ポインタ ポインタ変数とは、さまざまなオブジェクト(int, char, double型の値や、それらの配列など)のアドレスを格納する変数だった アドレスとは、メモリ上の場所(通し番号)だった 関数も、メモリ上に一定の場所を占める 関数のアドレスもある 関数ポインタ

関数ポインタの宣言 関数ポインタの宣言 たとえば pMは、int型を二つ取り、int型を返す関数へのポインタ 戻り値の型  (*関数ポインタ) (引数リスト); たとえば int (*pM) (int x, int y); pMは、int型を二つ取り、int型を返す関数へのポインタ

関数ポインタにアドレスを代入 関数ポインタに、関数のアドレスを代入する たとえば 関数ポインタに代入された関数の呼び出し 関数ポインタ = 関数名; &はいらない(関数名は関数のアドレスそのもの) たとえば pM = max; pMは関数max()を指す 関数ポインタに代入された関数の呼び出し (*pM)(5, 10) /* max(5, 10)と同じ */

関数ポインタの利用と応用 Sample16.cを入力して、コンパイル・実行してみよう 関数ポインタの応用 たとえば、関数ポインタを配列に格納し、必要に応じて異なる関数を呼び出すことができる Sample17.cを入力して、コンパイル・実行してみよう

今日学んだこと 文字列とポインタ 文字列の操作 動的なメモリの確保 関数ポインタ 教科書10.3から10.5まで(p. 317~348)

レポート課題 (1)13番目のスライドにあるように、strlen()と同じ動作をする関数、mystrlen()を書いてみよ。Sample11.cを、mystrlen()を使うものに書き換えよ。 (2・やや難)文字列str1とstr2とを連結した文字列を新たに作り、それを返す関数 char *strappend (const char *str1, const char *str2); を書け。

レポート課題(続) (2)のヒント: char * strappend (const char *str1, const char *str2) { char *str = (char *) malloc (/*str1とstr2が入るだけのメモリを確保する */); if (!str) perror ("malloc failed in mystrappend()"); exit (EXIT_FAILURE); } strcpy (/* strにstr1をコピーする */); strcat (/* strにstr2を連結する */); return str;

レポート課題(続) 締め切り:2004年11月22日一杯(日本時間で) 提出:メールで木村(iwao@sci.toyama-u.ac.jp)まで. 感想などあると木村が喜びます