|
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;
}