ctime

char *ctime( time_t *time )

システムクロック時間を人間が理解可能な時間文字列に変換する。
ctimeとはconvert timeの略かと思われる。
意味合い的には「localtime+asctime」という働きをする。


#include <stdio.h>
#include <time.h>

void main()
{
 time_t nowtime;
 time( &nowtime );
 printf( "%s", ctime( &nowtime ) );
}


実行結果

Tue Oct 24 12:12:37 2006


'\n'と'\0'が文字列の最後に付加されます。
C > 標準関数 > 時間処理 | comments (0) | trackbacks (0)

feof

int feof( FILE *fp )

ファイルfpがファイルエンドなら非0を返す。


while ( !feof( fp ) ) {
 c = getc( fp );
 ・・・
}


ファイルfpがファイルエンドでない間、処理を続ける。
C > 標準関数 > ファイル入出力関数 | comments (0) | trackbacks (0)

ファイル入出力主要関数一覧

FILE *fi;
FILE *fo;
int a, c;
char str[256];
とした場合

putc1文字書き出しputc( c, fo )
fputc同上fputc( c, fo )
getc1文字読み込みc = getc( fi )
fgetc同上c = fgetc( fi )
fputs1行書き出しfputs( str, fo )
fgets1行読み込みfgets( str, 256, fi )
fprintf書式付き書き出しfprintf( fo, "%d\n", a );
fscanf書式付き読み込みfscanf( fi, "%d", &a );

fgetsの場合、文字列の最後に"\0"が付加されなければならないので
上記の例では読み込めるのは255文字までとなる。
C > 標準関数 > ファイル入出力関数 | comments (0) | trackbacks (0)

コマンドライン引数の取得

コマンドラインからの引数を確認するプログラム

#include <stdio.h>

void main( int argc, char *argv[] )
{
 printf( "argc:%d\n", argc );
 for ( int i = 0; i < argc; i++ )
  printf( "argv[ %d ]:%s\n", i, argv[ i ] );
}


以下のような内容の起動用バッチも作成しておきます。

適当.exe 第1引数 第2引数
pause


実行結果

argc:3
argv[ 0 ]:適当.exe
argv[ 1 ]:第1引数
argv[ 2 ]:第2引数


argcはコマンドラインからmain関数へ渡されたすべての引数の数です。
argv[0]はコマンド名そのものを示しています。
"適当.exe"から見た場合、第1引数はargv[1]、第2引数はargv[2]に入ります。

これを利用してファイル入出力処理をコマンドラインから行う事ができます。

ファイルから1文字ずつリードしてディスプレイに表示していくプログラム

#include <stdio.h>
#include <stdlib.h>

void main( int argc, char *argv[] )
{
 FILE *fp;
 int c;

 if ( argc != 2 ) {
  printf( "引数の数が違います\n" );
  exit( 1 );
 }
 if ( ( fp = fopen( argv[1], "r" ) ) == NULL ) {
  printf( "入力ファイルがオープンできません\n" );
  exit( 1 );
 }

 while ( ( c = getc( fp ) ) != EOF )
  putchar( c );

 fclose( fp );
}

C > 標準関数 > ファイル入出力関数 | comments (0) | trackbacks (0)

条件付きコンパイル


#include <stdio.h>

#define DEBUG

void main()
{
 printf( "処理開始\n" );

#ifdef DEBUG
 printf( "%s\n", __TIME__ );
 printf( "%s\n", __DATE__ );
 printf( "%s\n", __FILE__ );
 printf( "%d\n", __LINE__ );
#endif

 printf( "処理終了\n" );
}


出力結果

処理開始
11:56:29
Oct 19 2006
C:\xxx\xxx\xxx\tekito.cpp
13
処理終了




#include <stdio.h>

//#define DEBUG

void main()
{
 printf( "処理開始\n" );

#ifdef DEBUG
 printf( "%s\n", __TIME__ );
 printf( "%s\n", __DATE__ );
 printf( "%s\n", __FILE__ );
 printf( "%d\n", __LINE__ );
#endif

 printf( "処理終了\n" );
}

出力結果

処理開始
処理終了

C > プリプロセッサ | comments (0) | trackbacks (0)

処理系が定義しているマクロ

C言語の処理系は次の4種類のマクロを標準マクロとして定義しています。
__TIME__コンパイル時刻を「時:分:秒」の書式で表す文字列
__DATE__コンパイル日付を「月 日 年」の書式で表す文字列
__FILE__処理中のソースプログラムの名前を表す文字列
__LINE__処理中のソースプログラムの行番号を表す10進数(先頭行は1)
C > プリプロセッサ | comments (0) | trackbacks (0)

関数のポインタ配列

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


#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)

演算子の優先順位

優先順位123456789101112131415
関数、かっこ()              
配列[]              
構造体.、->              
 sizeof             
ポインタ *、&             
インクリメント・ディクリメント ++、--             
算術 -*、/、%+、-           
関係     <、<=、>、>===、!=        
ビット ~  <<、>>  &^|     
論理 !        &&||   
条件            ?:  
代入             =、+=、*=、etc 
カンマ              ,
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)