C言語ワンポイント講座ポインタと派生型徹底入門 サンプルプログラム集

コンピュータを学習する人の学校:パソコンキャンパス、プログラミングキャンパス

ここでは、 The Office Uchida, School of Computerの e-Learningシステム 「C言語ワンポイント講座 ポインタと派生型入門」のためのサンプルプログラムを紹介しています。

この中に記載されているプログラムをブラウズあるいはカットアンドペーストしてください。

目次に戻る


第3章 関数を指すポインタ

内容
Sample list 3-1 関数を指すポインタ
Sample list 3-2 関数を指すポインタの付け替え
Sample list 3-3 関数を指すポインタの配列
Sample list 3-4 関数を指すポインタの配列(typedef版)
Sample list 3-5 コールバック関数の簡単な利用例
Sample list 3-6 コールバック関数の簡単な利用例(引数を2つとる関数の場合)
Sample list 3-7 実例:シグナル処理関数(signal)
Sample list 3-8 実例:プログラム終了時の実行関数登録(atexit)
Sample list 3-9 実例:バイナリサーチ(整数の場合:bsearch)
Sample list 3-10 実例:バイナリサーチ(文字列の場合:bsearch)
Sample list 3-11 実例:クイックソート(整数の場合:qsort)
Sample list 3-12 実例:クイックソート(文字列の場合:qsort)

関数を指すポインタ

Sample list 3-1 関数を指すポインタsample3_1.c
#include<stdio.h>

double f1( double x )
{
	return x+1.0;
}

int main( void )
{
	double (*p)(double) = f1; /* 関数を指すポインタpに関数のアドレスf1をセット */

	double ans = p( 5.0 ); /* 関数を指すポインタpに格納されているアドレスの関数を指定されたパラメータで呼び出す */

	printf( "p(5.0)=%g\n", ans );

	return 0;
}
Sample list 3-1の実行結果(cygwin)

% gcc sample3_1.c
% ./a
p(5.0)=6

目次に戻る, 先頭に戻る


関数を指すポインタの付け替え

Sample list 3-2 関数を指すポインタの付け替えsample3_2.c
#include<stdio.h>
#include<math.h>

double f1( double x )
{
	return x+1.0;
}

double f2( double x )
{
	return x+2.0;
}

int main( void )
{
	double (*p)(double) = f1;

	double ans1 = p( 5.0 );
	double ans2, ans3;

	p = f2; /* ポインタの付け替え */

	ans2 = p(5.0);

	p = sqrt; /* ポインタをsqrt関数にセット */

	ans3 = p( 2.0 );

	printf( "ans1=%g, ans2=%g, ans3=%g\n", ans1, ans2, ans3 );

	return 0;
}
Sample list 3-2の実行結果(cygwin)

% gcc sample3_2.c
% ./a
ans1=6, ans2=7, ans3=1.41421

目次に戻る, 先頭に戻る


関数を指すポインタの配列

Sample list 3-3 sample3_3.c
#include<stdio.h>

double f1( double x )
{
	return x+1.0;
}

double f2( double x )
{
	return x+2.0;
}

double f3( double x )
{
	return x+3.0;
}

int main( void )
{
	double (*p[3])(double) = { f1, f2, f3, }; /* 関数を指すポインタの配列 */
	int k;

	for( k=0; k<3; k++ )
	{
		double ans = p[k]( 5.0 ); /* p[k]の関数を呼び出す */

		printf( "p[%d](5.0)=%g\n", k, ans );
	}

	return 0;
}
Sample list 3-3の実行結果(cygwin)

% gcc sample3_3.c
% ./a
p[0](5.0)=6
p[1](5.0)=7
p[2](5.0)=8

目次に戻る, 先頭に戻る


関数を指すポインタの配列(typedef版)

Sample list 3-4 関数を指すポインタの配列(typedef版)sample3_4.c
#include<stdio.h>

double f1( double x )
{
	return x+1.0;
}

double f2( double x )
{
	return x+2.0;
}

double f3( double x )
{
	return x+3.0;
}

typedef double (*funcTable[3])(double); /* 「関数を指すポインタの配列」型 */

int main( void )
{
	funcTable p = { f1, f2, f3, }; /* 関数を指すポインタの配列 */
	int k;

	for( k=0; k<3; k++ )
	{
		double ans = p[k]( 5.0 ); /* p[k]の関数を呼び出す */

		printf( "p[%d](5.0)=%g\n", k, ans );
	}

	return 0;
}
Sample list 3-4の実行結果(cygwin)

% gcc sample3_4.c
% ./a
p[0](5.0)=6
p[1](5.0)=7
p[2](5.0)=8

目次に戻る, 先頭に戻る


コールバック関数の簡単な利用例

Sample list 3-5 コールバック関数の簡単な利用例sample3_5.c
#include<stdio.h>
#include<math.h>

double callback( double x ) /* コールバック関数 */
{
	return x+1.0;
}

double g( double x, double (*f)(double) )
{
	return f( x );
}

int main( void )
{
	double ans = g( 5.0, callback ); /* 自作のコールバック関数を呼ぶ */

	printf( "ans = %g\n", ans );

	ans = g( 5.0, sqrt ); /* sqrtをコールバック関数として呼ぶ */

	printf( "ans = %g\n", ans );

	return 0;
}
Sample list 3-5の実行結果(cygwin)

% gcc sample3_5.c
% ./a
ans = 6
ans = 2.23607

目次に戻る, 先頭に戻る


コールバック関数の簡単な利用例(引数を2つとる関数の場合)

Sample list 3-6 コールバック関数の簡単な利用例(引数を2つとる関数の場合)sample3_6.c
#include<stdio.h>
#include<math.h>

/* 引数を2つ取る関数の場合 */

double callback( double x, double y ) /* コールバック関数 */
{
	return x+y;
}

double g( double x, double (*f)(double,double) )
{
	return f( x, x );
}

int main( void )
{
	double ans = g( 5.0, callback ); /* 自作のコールバック関数を呼ぶ */

	printf( "ans = %g\n", ans );

	ans = g( 5.0, pow ); /* powをコールバック関数として呼ぶ */

	printf( "ans(5の5乗) = %g\n", ans );

	return 0;
}
Sample list 3-6の実行結果(cygwin)

% gcc sample3_6.c
% ./a
ans = 10
ans(5の5乗) = 3125

目次に戻る, 先頭に戻る


実例:シグナル処理関数(signal)

Sample list 3-7 実例:シグナル処理関数(signal)sample3_7.c
#include<stdio.h>
#include<signal.h>

void printMessage( int sigNo ) /* シグナルハンドラ */
{
	printf( "割り込み発生:シグナル=%d\n", sigNo );
}

int main( void )
{
	int x[1];
	int y;

	/* 「SIGSEGV:メモリアクセス違反」があったら、
		printMessage関数を呼ぶようにセットする */
	if( signal( SIGSEGV, printMessage ) != SIG_ERR )
		fprintf( stderr, "シグナル設定成功\n" );
	else
		fprintf( stderr, "シグナル設定失敗" );

	y = x[ 10000 ]; /* わざとSIGSEGVを発生させる */

	printf( "プログラム終了:これは実行されない\n" );

	return 0;
}
Sample list 3-7の実行結果(cygwin)

% gcc sample3_7.c
% ./a
シグナル設定成功
割り込み発生:シグナル=11

参考文献:内田智史、秋元勝、北川雅巳、大津崇共著:「C言語によるプログラミング スーパーリファレンス編」、オーム社、pp.447-448

目次に戻る, 先頭に戻る


実例:プログラム終了時の実行関数登録(atexit)

Sample list 3-8 実例:プログラム終了時の実行関数登録(atexit)sample3_8.c
#include<stdio.h>
#include<stdlib.h>

void pr1( void ){ printf( "pr1 called\n" ); }
void pr2( void ){ printf( "pr2 called\n" ); }
void pr3( void ){ printf( "pr3 called\n" ); }

int main( void )
{
	if( !atexit( pr1 ) ) printf( "pr1 OK\n" ); else printf( "pr1 NO\n" );
	if( !atexit( pr2 ) ) printf( "pr2 OK\n" ); else printf( "pr2 NO\n" );
	if( !atexit( pr3 ) ) printf( "pr3 OK\n" ); else printf( "pr3 NO\n" );

	return 0; /* プログラムの終了:登録した関数が実行される */
}
Sample list 3-8の実行結果(cygwin)

% gcc sample3_8.c
% ./a
pr1 OK
pr2 OK
pr3 OK
pr3 called
pr2 called
pr1 called

参考文献:内田智史、秋元勝、北川雅巳、大津崇共著:「C言語によるプログラミング スーパーリファレンス編」、オーム社、pp.494-495

目次に戻る, 先頭に戻る


実例:バイナリサーチ(整数の場合:bsearch)

Sample list 3-9 実例:バイナリサーチ(整数の場合:bsearch)sample3_9.c
#include<stdio.h>
#include<stdlib.h>

int compare( const int *n1, const int *n2 )
{
	printf( "%d, %d\n", *n1, *n2 ); /* テスト用表示:実際には不要 */

	return *n1 - *n2;
}

int main( void )
{
	int data[] = { -2, 0, 1, 3, 5, 6, 9, 10, 11, 12, 100, };
	int num = sizeof data / sizeof data[0];

	int target = 0;
	int *t;

	if( ( t = (int *)bsearch( &target, data, num, sizeof( data[0] ), (int (*)(const void *, const void * ))compare ) ) != NULL )
		printf( "%dがありました。\n", *t );
	else
		printf( "%dがありませんでした。\n", target );

	return 0;
}
Sample list 3-9の実行結果(cygwin)

% gcc sample3_9.c
% ./a
0, 6
0, 1
0, 0
0がありました。

参考文献:内田智史、秋元勝、北川雅巳、大津崇共著:「C言語によるプログラミング スーパーリファレンス編」、オーム社、pp.496-497

目次に戻る, 先頭に戻る


実例:バイナリサーチ(文字列の場合:bsearch)

Sample list 3-10 実例:バイナリサーチ(文字列の場合:bsearch)sample3_10.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int compare( const char *name1, const char **name2 )
{
	printf( "%s, %s\n", name1, *name2 ); /* テスト用表示:実際には不要 */
	return strcmp( name1, *name2 );
}

int main( void )
{
	char *names[] = { "atexit", "atol", "bsearch", "calloc", "malloc", "qsort", "rand", "system", "wcstombs", };
	int  num = sizeof names / sizeof names[0];

	char *name = "atol"; /* 検索する文字列 */
	char **s; /* ポインタのポインタになっていることに注意 */

	if( ( s = bsearch( name, names, num, sizeof names[0], (int (*)(const void *, const void * ))compare ) ) != NULL )
		printf( "%sがありました。\n", *s );
	else
		printf( "%sがありませんでした。\n", name );

	return 0;
}
Sample list 3-10の実行結果(cygwin)

% gcc sample3_10.c
% ./a
atol, malloc
atol, bsearch
atol, atol
atolがありました。

参考文献:内田智史、秋元勝、北川雅巳、大津崇共著:「C言語によるプログラミング スーパーリファレンス編」、オーム社、pp.496-497

目次に戻る, 先頭に戻る


実例:クイックソート(整数の場合:qsort)

Sample list 3-11 実例:クイックソート(整数の場合:qsort)sample3_11.c
#include<stdio.h>
#include<stdlib.h>

int compare( const int *n1, const int *n2 ) /* 比較関数 */
{
	return *n1 - *n2;
}

int main( void )
{
	int data[] = { 4, 2, -2, 8, -9, 6, 4, 2, 1, 0, 17, -3, 23, };
	int num = sizeof data / sizeof data[0];

	int k;

	qsort( data, num, sizeof( data[0] ), (int (*)(const void *, const void * ))compare );

	for( k=0; k<num; k++ ) /* 結果の表示 */
		printf( "%d ", data[k] );
	printf( "\n" );

	return 0;
}
Sample list 3-11の実行結果(cygwin)

% gcc sample3_11.c
% ./a
-9 -3 -2 0 1 2 2 4 4 6 8 17 23

参考文献:内田智史、秋元勝、北川雅巳、大津崇共著:「C言語によるプログラミング スーパーリファレンス編」、オーム社、pp.503-504

目次に戻る, 先頭に戻る


実例:クイックソート(文字列の場合:qsort)

Sample list 3-12 実例:クイックソート(文字列の場合:qsort)sample3_12.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int compare( const char **name1, const char **name2 ) /* 比較関数 */
{
	printf( "%s, %s\n", *name1, *name2 ); /* テスト用表示:実際には不要 */
	return strcmp( *name1, *name2 );
}

int main( void )
{
	char *names[] = { "rand", "calloc", "malloc", "wcstombs", "atol", "qsort", "atexit", "system", "bsearch", };
	int  num = sizeof names / sizeof names[0];

	int k;

	qsort( names, num, sizeof( names[0] ), (int (*)(const void *, const void * ))compare );

	for( k=0; k<num; k++ ) /* 結果の表示 */
		printf( "%s ", names[k] );
	printf( "\n" );

	return 0;
}
Sample list 3-12の実行結果(cygwin)

% gcc sample3_12.c
% ./a
rand, atol
atol, bsearch
rand, bsearch
calloc, bsearch
rand, bsearch
system, bsearch
atexit, bsearch
malloc, bsearch
qsort, bsearch
atol, bsearch
wcstombs, bsearch
wcstombs, bsearch
atol, atexit
wcstombs, malloc
wcstombs, qsort
malloc, qsort
wcstombs, calloc
qsort, calloc
malloc, calloc
wcstombs, system
qsort, system
wcstombs, rand
system, rand
qsort, rand
atexit atol bsearch calloc malloc qsort rand system wcstombs

参考文献:内田智史、秋元勝、北川雅巳、大津崇共著:「C言語によるプログラミング スーパーリファレンス編」、オーム社、pp.503-504

目次に戻る, 先頭に戻る


Copyright (c) 2006 Satoshi Uchida, The Office Uchida, School of Computer