C/C++のよく使う構文の覚え書きです.基本的にWindows環境です.


(公開:2007年02月06日)

任意の底のlog

標準関数としてないのが謎.

double logn(int base, double antilog) {
    return log(antilog) / log((double)base);
}

ミリ秒単位で処理時間を計測する

リアルタイム処理の研究とかだと処理時間計測はつきものですね.

#include <stdio.h>
#include <windows.h>

int main(void)
{
    LARGE_INTEGER freq,time_start,time_end; // 周波数,開始時間,終了時間

    QueryPerformanceFrequency(&freq);
    QueryPerformanceCounter(&time_start);

    //////////// ここに処理を書く ///////////////////////////
    Sleep(500);                   // 処理例(500ms間スリープ)
    /////////////////////////////////////////////////////////

    QueryPerformanceCounter(&time_end);
    printf("処理時間:%d[ms]\n",(time_end.QuadPart - time_start.QuadPart)*1000 / freq.QuadPart);

    return 0;
}

0〜nの乱数を発生させる

乱数を発生させるにはrand()関数を使います.また,乱数系列の初期化を行うためにsrand()関数を使います. 初期化のためのseed値には時刻を用いるのが一般的です.

#include <stdio.h>
#include <stdlib.h> // rand()関数用
#include <time.h>   // time()関数用

int main(void)
{
    int r,n;
    srand((unsigned)time(NULL)); // 乱数の初期化

    n = 10;
    r = rand()%(n+1); // 0〜nの乱数を発生

    return 0;
}

任意の確率で処理を行う

乱数を応用すれば,「○%の確率で○○する」が作れます. 定数RAND_MAXはrand()関数が出力する乱数の最大値です.

#include <stdio.h>
#include <stdlib.h> // rand()関数用
#include <time.h>   // time()関数用

int main(void)
{
    double probability = 0.01; // 確率(1%)
    srand((unsigned)time(NULL)); // 乱数の初期化

    if ( (double)rand()/RAND_MAX < probability ) {
        // ここに処理を書く			
    }

    return 0;
}

限りなくゼロに近いdouble値をゼロと判定する

doubleの最小の正の値はfloat.hでDBL_MINという定数で定義されています. これを利用して以下のような関数を作ると良いでしょう.

#include <float.h>
/*---------------------------------------
戻り値は
 1 : ゼロまたはゼロに限りなく近い
 0 : それ以外
---------------------------------------*/
int IsNearlyZero(double x)
{
    return (x>=0 && x<DBL_MIN*100); // この100は適当に範囲を持たせるためのスケール値
}

メモリを動的に確保する

メモリを動的に確保するための関数は,Cではcalloc(またはmalloc),C++ではnewです. また,確保したメモリを開放するための関数は,Cではfree,C++ではdeleteを使います.


C言語版
#include <stdio.h>
#include <malloc.h>

int main(void)
{
    double *data;  // 確保した領域の先頭を示すポインタ
    int n;         // 領域の大きさ

    n = 10;

    // メモリの確保
    data = calloc(n,sizeof(double))
    if (data==NULL) {
        printf("memory error");
        return -1;
    }

    // 扱い方は配列と同じ
    data[0] = 1;
    data[n-1] = 200;

    printf("%d\n",data[0]);
    printf("%d\n",data[n-1]);

    // メモリの解放(必須)
    free(data);

    return 0;
}

C++版
#include <iostream>
using namespace std;

int main(void)
{
    double *data; // 確保した領域の先頭を示すポインタ
    int n;        // 領域の大きさ

    n = 10;

    // メモリの確保
    data = new double [n];

    if (data==NULL) {
        printf("memory error");
        return -1;
    }

    // 扱い方は配列と同じ
    data[0] = 1;
    data[n-1] = 200;

    // メモリの解放(必須)
    delete[] data;

    return 0;
}

同じことをやるのでも,C++のSTLのvectorを使うほうがより強力で便利です.

コンソールでアニメーション表示を行う

エスケープ文字 \r (行頭に戻る)を使えばこんな悪戯も.進行状況表示などにも応用できます.

#include <stdio.h>
#include <windows.h>

int main(void)
{
    while (1) {
        printf("          ( ゚∀)    キタ━ッ!!\r");
        Sleep(100);
        printf("          (   ゚)キタ━━━ッ!!\r");
        Sleep(100);
        printf("    キタ(    )━━━━ッ!!\r");
        Sleep(100);
        printf("   キタ━(゚   )━━━━ッ!!\r");
        Sleep(100);
        printf("  キタ━━(∀゚ )━━━━ッ!!\r");
        Sleep(100);
        printf("キタ━━━━(゚∀゚)━━━━ッ!!\r");
        Sleep(100);
    }
}

printf()のような書式指定ができる関数を作る

連番のファイルを開いたりするとき,「sprintfでファイル名を作ってからfopenに渡す」のが常套手段ですが, その関数自体にprintfのような書式指定ができるインターフェースがあればもっと便利です. 書式指定のインターフェースを作るには,「可変個引数」と「vprint()」を使います. 例として,書式指定のできるfopen関数を以下に示します.


const char *format, ...の部分が書式指定になります. 書式指定以外にパラメータを渡す引数がいる場合は,const char *formatより前に置いてください.

#include <stdio.h>
#include <stdarg.h>  // vprintfを使うため

// 書式指定ができるfopen
FILE* FileOpen(const char *mode, const char *format, ...)
{
    char buffer[255]; // 文字列バッファ

    va_list ap;
    va_start(ap, format);
    vsprintf(buffer, format, ap);
    va_end(ap);

    /* この時点でbufferに書式処理後の文字列が入ってる */

    return fopen(buffer,mode);
}

int main(void)
{
    int i;
    FILE *fp;
								
    for (i=0; i<10; i++) {
        fp = FileOpen("r","data%04.bmp",i); // 書式指定で書ける!(for文を回すときに便利)
        if (fp!=NULL) {
            /* なにか処理 */
            fclose(fp);
        }
    }

    return 0;
}