C/C++のよく使う構文の覚え書きです.基本的にWindows環境です. |
任意の底の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; }