プログラミング論 関数ポインタ と 応用(qsort)

Slides:



Advertisements
Similar presentations
アルゴリズムとデータ構造 第2回 線形リスト(復習).
Advertisements

15.1 文字列処理の基本 15.2 文字列処理用ライブラリ関数
情報基礎演習B 後半第5回 担当 岩村 TA 谷本君.
数理情報工学演習第一C プログラミング演習 (第3回 ) 2014/04/21
プログラミング入門2 第10回 動的な領域確保 情報工学科 篠埜 功.
データ構造とアルゴリズム 第10回 mallocとfree
プログラミング入門2 第10回 構造体 情報工学科 篠埜 功.
プログラミング入門2 第10回 構造体 情報工学科 篠埜 功.
プログラミング言語Ⅰ(実習を含む。), 計算機言語Ⅰ・計算機言語演習Ⅰ, 情報処理言語Ⅰ(実習を含む。)
プログラミング演習(2組) 第12回
12: コマンドライン引数 C プログラミング入門 総機1 (月1) Linux にログインし、以下の講義ページ を開いておくこと
12: コマンドライン引数 C プログラミング入門 基幹7 (水5) Linux にログインし、以下の講義ページ を開いておくこと
第8回 プログラミングⅡ 第8回
構造体.
プログラミング演習Ⅰ 課題2 10進数と2進数 2回目.
演習問題の答え #include #include #define NUM 5 typedef struct { // 構造体の定義 float shincho; // 身長 float taiju; // 体重 } shintai; void hyouji(shintai.
ちょっとした練習問題① 配列iroを['R', 'W', 'R', 'R', 'W' , 'W' , 'W']を宣言して、「W」のときの配列の番号をprintfで表示するようなプログラムを記述しなさい。
プログラミング2 関数
プログラミング論 ファイル入出力
プログラミング応用 printfと変数.
プログラミング論 II 2008年10月30日 文字列
精密工学科プログラミング基礎 第10回資料 (12/18実施)
プログラミング 4 記憶の割り付け.
2005年度 データ構造とアルゴリズム 第3回 「C言語の復習:再帰的データ構造」
第10章 これはかなり大変な事項!! ~ポインタ~
プログラミング入門2 第8回 ポインタ 情報工学科 篠埜 功.
ネットワークプログラミング 第3回「C言語の基礎~コマンドライン引数・構造体・ポインタ」
メモリの準備 メモリには、その準備の方法で2種類ある。 静的変数: コンパイル時にすでにメモリのサイズがわかっているもの。 普通の変数宣言
プログラミング入門2 第11回 情報工学科 篠埜 功.
プログラミング入門2 第11回 情報工学科 篠埜 功.
第7回 プログラミングⅡ 第7回
アルゴリズムとデータ構造 補足資料5-1 「メモリとポインタ」
高度プログラミング演習 (08).
地域情報学 C言語プログラミング 第5回 ポインタ、関数、ファイル入出力 2017年11月17日
第11回 プログラミングⅡ 第11回
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 にログインし、以下の講義ページ を開いておくこと
演習0 func0, func1, func2を作成せよ. main()関数の中で,func0()を呼び出しを実行せよ.
オブジェクト指向言語論 第六回 知能情報学部 新田直也.
プログラミング言語論 第六回 理工学部 情報システム工学科 新田直也.
演習07-0 “Hello\n” “World!\n”と
精密工学科プログラミング基礎Ⅱ 第5回資料 今回の授業で習得してほしいこと: 構造体 (教科書 91 ページ)
15.1 文字列処理の基本 15.2 文字列処理用ライブラリ関数
データ構造とアルゴリズム 第11回 リスト構造(1)
プログラミング入門2 第9回 ポインタ 情報工学科 篠埜 功.
文字列へのポインタの配列 static char *lines[MAXLINES]; lines[0] NULL
IF文 START もしも宝くじが当たったら 就職活動する 就職活動しない YES END NO.
情報基礎演習B 後半第2回 担当 岩村 TA 谷本君.
第13回 ポインタ 1 1.
プログラミング論 ポインタ
09: ポインタ・文字列 C プログラミング入門 基幹7 (水5) Linux にログインし、以下の講義ページを開いておく こと
12: コマンドライン引数 C プログラミング入門 基幹7 (水5) Linux にログインし、以下の講義ページを開いておく こと
ネットワーク・プログラミング Cプログラミングの基礎.
第5回 プログラミングⅡ 第5回
プログラミング論 構造体
演習00-0 “Hello\n” “World!\n”と
11: 動的メモリ確保 C プログラミング入門 基幹2 (月4) Linux にログインし、以下の講義ページ を開いておくこと
プログラミング演習I 2003年6月11日(第9回) 木村巌.
プログラミング演習II 2004年11月 16日(第5回) 理学部数学科・木村巌.
プログラミング言語Ⅰ(実習を含む。), 計算機言語Ⅰ・計算機言語演習Ⅰ, 情報処理言語Ⅰ(実習を含む。)
15.1 文字列処理の基本 15.2 文字列処理用ライブラリ関数
プログラミング演習II 2004年11月 2日(第3回) 理学部数学科・木村巌.
値渡しと参照渡しについて.
プログラミング演習I 補講用課題
岩村雅一 知能情報工学演習I 第7回(後半第1回) 岩村雅一
第1章 文字の表示と計算 printfと演算子をやります 第1章 文字の表示と計算.
オブジェクト指向言語論 第六回 知能情報学部 新田直也.
プログラミング 3 ポインタ(1).
12: コマンドライン引数 C プログラミング入門 基幹2 (月4) Linux にログインし、以下の講義ページ を開いておくこと
岩村雅一 知能情報工学演習I 第9回(C言語第3回) 岩村雅一
Presentation transcript:

プログラミング論 関数ポインタ と 応用(qsort) http://www.ns.kogakuin.ac.jp/~ct13140/Prog/

概要 関数ポインタ qsort関数 関数(へのポインタ)を変数に入れてしまう. 分かりづらい? C言語に標準で搭載されているソート関数. 関数ポインタの理解が必須

関数ポインタの例 void hoge(){ printf("hello\n"); 実行結果 } hello void main(){ void (*p)(); /* ↑ 関数のアドレスを入れる変数pを宣言. */ p = &hoge; /* ↑ pに 関数hoge のアドレスを代入 */ (*p)(); /* pは関数hogeへのポインタ.(*p)は関数hogeそのもの */ 実行結果 hello

関数のアドレス 関数にはアドレスがある. 関数のアドレスは,「&関数名」あるいは「関数名」で取得で取得可能.(どちらでも良い) 関数はメモリ上に存在している. 関数のアドレスは,「&関数名」あるいは「関数名」で取得で取得可能.(どちらでも良い) void hoge(){ } void main(){ printf("&hoge = %p\n", &hoge); printf("hoge = %p\n", hoge); 実行結果 &hoge = 0x400498 hoge = 0x400498

関数のアドレス 標準関数にもアドレスがある. void main(){ printf("%p\n", &printf); } 実行結果 0x4003a0

関数ポインタ変数 関数のアドレスを入れる変数の宣言 void (*p)(); 「引数(),戻り値voidの関数」 へのポインタpを宣言. 解説? void hoge(){ printf("Hello\n"); } void main(){ void (*p)(); p = &hoge; (*p)(); int i; int *p; i と *p が同等の存在 void hoge(); void (*p)(); hoge と *p が同等の存在

関数ポインタ変数 関数のアドレスを入れる変数の宣言 int (*p)(int, int); 「引数(int,int), 解説? int hoge(int a, int b){ return a+b; } void main(){ int (*p)(int, int); p = &hoge; printf("%d\n", (*p)(3,4) ); int i; int *p; i と *p が同等の存在 int hoge(int a, int b); int (*p)(int a, int b); hoge と *p が同等の存在

関数ポインタ から 関数にアクセス pが関数ポインタなら,(*p)()あるいはp() にて,関数にアクセスできる.(どちらでも良い) void hoge(){ printf("Hello\n"); } void main(){ void (*p)(); p = &hoge; (*p)(); int hoge(int a, int b){ return a+b; } void main(){ int (*p)(int, int); p = &hoge; printf("%d\n", (*p)(3,4) ); 実行結果 Hello 実行結果 7

関数ポインタ から 関数にアクセス pが関数ポインタなら,(*p)()あるいはp() にて,関数にアクセスできる.(どちらでも良い) void hoge(){ printf("Hello\n"); } void main(){ void (*p)(); p = &hoge; p(); int hoge(int a, int b){ return a+b; } void main(){ int (*p)(int, int); p = &hoge; printf("%d\n", p(3,4) ); 実行結果 Hello 実行結果 7

関数ポインタの例 int hoge(int a, int b){ return a+b; } int fuga(int a, int b){ return a*b; void main(){ int x; int (*p)(int, int); p = &hoge; printf("%d\n", (*p)(3,4) ); p = &fuga; 実行結果 7 12 これは hoge これは fuga

関数ポインタの例 関数の引数に「関数ポインタ」を渡すことも可能。 int hoge(int a, int b){ return a+b; } int fuga(int a, int b){ return a*b; int func( int (*p)(int, int) ){ return (*p)(3,4); void main(){ printf("%d\n", func(&hoge) ); printf("%d\n", func(&fuga) ); 実行結果 7 12 この関数を実行 p=hogeなら加算 p=fugaなら乗算

qsort C言語の標準関数. クイックソートでデータをソートする. アドレスbaseに格納されているデータをソート. void qsort(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *)); クイックソートでデータをソートする. アドレスbaseに格納されているデータをソート. 各データのサイズはsizeで,データ個数はnmumb. データ同士の比較は,関数ポインタcomparが指す関数の結果(戻り値)に従う. ユーザが関数を指定し,動作を決める. size_t型は「整数型」と考えて良い.

qsort 関数ポインタcompar comparが指す関数は, int(*compar)(const void *a, const void *b) comparが指す関数は, もしa<bなら,負の数を返す. もしa==bなら,0を返す. もしa>bなら,正の数を返す. qsortは,要素間大小比較をするときに,この関数を呼び出して結果を決める. 「const付き」のポインタは,そのポインタの先の値は「読み出しはできる」が「書き込み」はできない.

qsortの例 (int型) int comp(const void *a, const void *b){ const int *p, *q; p=a; q=b; return *p - *q; } void main(){ int x[5]={3,0,2,9,5}; printf("%d %d %d %d %d\n", x[0], x[1], x[2], x[3], x[4]); qsort( x, 5, sizeof(int), &comp); 実行結果 3 0 2 9 5 0 2 3 5 9

qsortの例 (文字列) int comp(const void *a, const void *b){ const char *p, *q; p=a; q=b; return strcmp(p, q); } void main(){ char x[3][5]={"hoge","fuga","piyo"}; printf("%s %s %s\n", x[0], x[1], x[2]); qsort( x, 3, 5, &comp); 実行結果 hoge fuga piyo fuga hoge piyo

qsortの例 (構造体) struct seiseki{ int math; int engl; }; int comp(const void *a, const void *b){ const struct seiseki *p, *q; p=a; q=b; return (p->math + p->engl) - (q->math + q->engl); } void main(){ struct seiseki stu[3]={{90,80}, {10,80}, {23,20}}; printf("(%d,%d),(%d,%d),(%d,%d)\n", stu[0].math, stu[0].engl, stu[1].math, stu[1].engl, stu[2].math, stu[2].engl); qsort( stu, 3, sizeof(struct seiseki), &comp); qsortの例 (構造体) 実行結果 (90,80),(10,80),(23,20) (23,20),(10,80),(90,80)