関数のポインタ配列

構文
戻り値型 (*識別子)(パラメータ型リスト)


#include <stdio.h>

int func1( int, int );
int func2( int, int );

void main()
{
 int ( *funcp[] )( int, int ) = { func1, func2 };
 printf( "%d\n", funcp[0]( 1, 2 ) );
 printf( "%d\n", funcp[1]( 1, 2 ) );
}

int func1( int i, int j )
{
 return i + j;
}

int func2( int i, int j )
{
 return i - j;
}


実行結果

3
-1

C > 関数 | comments (0) | trackbacks (0)

関数の再帰呼び出し


#include <stdio.h>

int loopA( int );
void loopB( int );

void main()
{
 int i = 3;
 loopA( i );
 printf( "\n" );
 loopB( i );
}

int loopA( int n )
{
 printf( "loopA-out1:%d\n", n );
 if ( !n ) {
  printf( "出力終了\n" );
  return 0;
 }
 return loopA( --n );
 printf( "loopA-out2:%d\n", n );
}

void loopB( int n )
{
 printf( "loopB-out1:%d\n", n );
 if ( !n ) {
  printf( "出力終了\n" );
  return;
 }
 loopB( --n );
 printf( "loopB-out2:%d\n", n );
}


出力結果

loopA-out1:3
loopA-out1:2
loopA-out1:1
loopA-out1:0
出力終了

loopB-out1:3
loopB-out1:2
loopB-out1:1
loopB-out1:0
出力終了
loopB-out2:0
loopB-out2:1
loopB-out2:2

C > 関数 | comments (0) | trackbacks (0)

配列の初期化

配列のすべての要素を0で初期化するには

int a[10] = { 0 };
int a[3][10] = { 0 };


のように書きます。

では次のようにするとすべて1で初期化されるでしょうか?

実験1
int a[3][10] = { 1 };

実行結果
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

どうやら違うみたいです。では続けて以下はどうなるでしょうか?

実験2
int a[3][10] = { 0, 1, 2, 3, 4, 5 };

実行結果
0 1 2 3 4 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0


実験3
int a[3][10] = { { 0, 1 }, { 2, 3, 4, 5 } };

実行結果
0 1 0 0 0 0 0 0 0 0 2 3 4 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

つまり、指定されない要素は0が設定されます。

文字列の初期化も同様です。

実験4
char *str[5] = { "apple", "orange" };

実行結果

apple
orange
(null)
(null)
(null)

C > 配列 | comments (0) | trackbacks (0)

代表的なプリプロセッサ制御文

#defineマクロの定義
#undef定義の無効化
#includeファイルの取り込み
#if条件コンパイル
#elif条件コンパイル
#else条件コンパイル
#ifdef条件コンパイル
#ifndef条件コンパイル
#line行制御
#errorエラー生成
#pragma厳密にはコンパイラ制御文
C > プリプロセッサ | comments (0) | trackbacks (0)

素数だ・・・素数を数えるんだ・・・・

「エラトステネスのふるい」のサンプル

#include <stdio.h>
#define NUM 1000

void main()
{
 int prime[ NUM ], i, j;

 for ( i = 2; i < NUM; i++ )
  prime[ i ] = 1; // 1を立てておく

 for ( i = 2; i < NUM; i++ ) {
  if ( prime[ i ] == 1 ) { // 1ならそれは最初にみつかった素数
   for ( j = 2; i * j < NUM; j++ )
    prime[ i * j ] = 0; // i以外のiの倍数を全て倒す
  }
 }

 printf( "素数:1 " );
 for ( i = 2; i < NUM; i++ ) {
  if ( prime[ i ] == 1 )
   printf( "%d ", i );
 }
}


結果は出力してのお楽しみだ。
C > アルゴリズム | comments (0) | trackbacks (0)

ビット演算

ビットパターンを表示するサンプル

#include <stdio.h>
void bitpat( int x )
{
 int i;
 for ( i = 31; i>=0; i-- )
  printf( "%d", ( x >> i ) & 0x00000001 );
 printf( "\n" );
}

void main()
{
 int a;
 while ( scanf( "%d", &a ) != EOF )
  bitpat( a );
}

C > 演算 | comments (0) | trackbacks (0)

ポインタ配列を関数に渡す


#include <stdio.h>

void dispA( char** s )
{
 int i = 0;
 printf( "sのアドレス%p:格納アドレス%p\n", &s, s );
 while ( s[ i ] != NULL ) {
  printf( "s[%d]のアドレス%p:格納アドレス%p:%s\n", i, &s[ i ], s[ i ], s[ i ] );
  i++;
 }
 printf( "sのアドレス%p:格納アドレス%p\n\n", &s, s );
}

void dispB( char** s )
{
 printf( "sのアドレス%p:格納アドレス%p\n", &s, s );
 while ( *s != NULL ) {
  printf( "sのアドレス%p:格納アドレス%p:%s\n", &s, *s, *s );
  s++;
 }
 printf( "sのアドレス%p:格納アドレス%p\n", &s, s );
}

void main()
{
 char *name[] = { "Candy", "Rolla", "Nancy", "Ann", "Eluza", NULL };
 dispA( name );
 dispB( name );
}


実行結果

sのアドレス0012FF18:sの格納アドレス0012FF68
s[0]のアドレス0012FF68:s[0]の格納アドレス0042201C:Candy
s[1]のアドレス0012FF6C:s[1]の格納アドレス00423030:Rolla
s[2]のアドレス0012FF70:s[2]の格納アドレス00422FBC:Nancy
s[3]のアドレス0012FF74:s[3]の格納アドレス00422FB4:Ann
s[4]のアドレス0012FF78:s[4]の格納アドレス00422FAC:Eluza
sのアドレス0012FF18:sの格納アドレス0012FF68

sのアドレス0012FF18:sの格納アドレス0012FF68
sのアドレス0012FF18:sの格納アドレス0042201C:Candy
sのアドレス0012FF18:sの格納アドレス00423030:Rolla
sのアドレス0012FF18:sの格納アドレス00422FBC:Nancy
sのアドレス0012FF18:sの格納アドレス00422FB4:Ann
sのアドレス0012FF18:sの格納アドレス00422FAC:Eluza
sのアドレス0012FF18:sの格納アドレス0012FF7C

C > 関数 | comments (0) | trackbacks (0)

2次元配列を関数に渡す


#include <stdio.h>

int sum( int* a )
{
 int i = 0, sum = 0;
 while ( *a != -999 ) {
  sum += *a;
  a++;
 }
 return sum;
}

void main()
{
 int a[][4] = { { 1, 2, 3, 0 }
        , { 4, 5, 6, 0 }
        , { 7, 8, 9, -999 } };

 printf( "%d\n", sum( a[0] ) );
}

C > 関数 | comments (0) | trackbacks (0)

1次元配列を関数に渡す


#include <stdio.h>

int sumA( int* a )
{
 int sum = 0;
 while ( *a != -999 ) {
  sum += *a;
  a++;
 }
 return sum;
}

int sumB( int* a )
{
 int i = 0, sum = 0;
 while ( a[ i ] != -999 ) {
  sum += a[ i ];
  i++;
 }
 return sum;
}

void main()
{
 int a[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, -999 };

 printf( "%d\n", sumA( a ) );
 printf( "%d\n", sumB( a ) );
}

C > 関数 | comments (0) | trackbacks (0)

ポインタ配列


#include <stdio.h>
void main()
{
 char *str[] = { "Candy", "Nancy", "Eluza", "Ann" };
 int i, j;

 // 1行ずつ出力
 for ( i=0; i<4; i++ )
  printf( "%s\n", str[ i ] );

 // 1文字ずつ出力
 for ( i=0; i<4; i++ ) {
  j = 0;
  while ( str[ i ][ j ] != '\0' ) {
   putchar( str[ i ][ j ] );
   j++;
  }
  putchar( '\n' );
 }
}

C > ポインタ | comments (0) | trackbacks (0)

ポインタと2次元配列


#include <stdio.h>
void main()
{
 int a[][4] = { { 1, 2, 3, 0 }
        , { 4, 5, 6, 0 }
        , { 7, 8, 9, -999 } };

 int *pa = a[0];

 while ( *pa != -999 ) {
  printf( "%d ", *pa );
  pa++;
 }
}


a[0]は2次元配列の先頭アドレスを示すポインタ定数と考えらる。
C > ポインタ | comments (0) | trackbacks (0)

アドレス計算


#include <stdio.h>
void main()
{
 char* str = "hello";
 int i;

 for ( i=0; i<5; i++ ) {
  putchar( *( str + i ) );
  putchar( str[ i ] ); // 配列としての実体はない
 }
}

C > ポインタ | comments (0) | trackbacks (0)

配列のデータ数に依存しないプログラム

一般にデータ数は場合によって異なります。
そこで配列のデータの終わりに-999という値を置き
これをデータの終わりの印として扱えば
配列のデータに依存しないプログラムを作れます。


#include <stdio.h>
void main()
{
 int a[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, -999 };
 int sum = 0;
 int i = 0;

 while ( a[i] != -999 ) {
  sum += a[i];
  i++;
 }
 printf( "合計:%d\n", sum );
}

C > 配列 | comments (0) | trackbacks (0)

fopen

FILE* fopen( char* filename, char* openmode )

ファイルが正しくオープンされると、ファイルポインタが返される。
エラーの時はNULLが返される。


FILE *fp;
fp = fopen( "sample.txt", "r" );
・・・
fclose( fp );


fopenのオープンモード
"r"既存ファイルを読み込み。ファイルがないとエラーになる。
"w"既存ファイルに新規書き込み。元の記録内容は消去される。ファイルがない場合は新規作成される。
"a"既存ファイルに追加書き込み。ファイルがない場合は新規作成される。
"r+"既存ファイルに読み込みと書き込み。ファイルがないとエラーになる。
"w+"既存ファイルに新規書き込み。読み込みも可能。ファイルがない場合は新規作成される。
"a+"既存ファイルに追加書き込み。読み込みは先頭から。ファイルがない場合は新規作成される。
"rb"バイナリファイルの読み込み。
"wb"バイナリファイルの新規書き込み。
"ab"バイナリファイルの追加書き込み。
C > 標準関数 > ファイル入出力関数 | comments (0) | trackbacks (0)

エスケープ文字列

\a警報音
\n復改
\tタブコード
\0778進数
\xff16進数
\0文字コード0
C > 基礎 | comments (0) | trackbacks (0)