可変引数を利用してVSのデバッグ出力ウィンドウやウィンドウボックス等でデバッグメッセージを出す方法
皆さんC/C++でデバッグメッセージを出したいときはどうしているでしょうか?
コンソールプログラムの場合はprintfやcoutで済ましている人もいるのではないでしょうか。
ではコンソールプログラムからWin32などのコンソールがないプログラムにした場合どうしますか。
printfを使っている箇所を以下のようにファイル出力に書き換えますか。
FILE* fp = fopen( "log.txt", "a" ); if ( fp != NULL ) { fprintf( fp, "ID:%d Message:%s\n", id, msg ); // printfから置き換え fclose( fp ); }
また可変引数ではなくconst char*しか受け付けないログ出力関数の場合などは
printfを使っている箇所で以下のように書き換えますか。
char tmp[512]; sprintf( tmp, "ID:%d Message%s\n", id, msg ); OutputLog( tmp ); // printfから置き換え
このような変更による影響を最小限にするため、
可変引数の自作ログ関数を作っておき、その中でメッセージ出力した方が良いでしょう。
普段は必ず自作ログ関数を使用します。
自作ログ関数の中でprintfするなりファイル出力するなり必要に応じて変更します。
こうすることで出力先を変更するときでも、ログ出力部分は何も変えずに済みますよね。
以下に可変引数の自作ログ関数を紹介します。
OutputDebugStringでVisualStudioのデバッグ出力ウィンドウにメッセージを出力し、
MessageBox APIでダイアログボックスに出力を行います。
ダイアログボックスを出すかどうかは第一引数で決まります。
VisualStudioのデバッグ出力ウィンドウにはデバッグコンパイル時だけ出力するようにしています。
// Debug時のDEBUGPRINTマクロとDEBUGPRINTLNマクロ #if _DEBUG inline void __cdecl DebugPrintf( bool bOutputMB, const char *fmt, ... ) { char tmp[1024]; va_list ap; va_start( ap, fmt ); vsprintf( tmp, fmt, ap ); // VisualStudioのデバッグウィンドウには必ず出力する OutputDebugString( tmp ); if( bOutputMB ) { // メッセージボックスはフラグがONにされたときだけ出力 ::MessageBox( NULL, tmp, "DEBUG MESSAGE", MB_OK ); } va_end( ap ); } #define DEBUGPRINT DebugPrintf inline void __cdecl DebugPrintfln( bool bOutputMB, const char *fmt, ... ) { char tmp[1024]; va_list ap; va_start( ap, fmt ); vsprintf( tmp, fmt, ap ); ::strcat( tmp, "\n" ); // VisualStudioのデバッグウィンドウには必ず出力する OutputDebugString( tmp ); if( bOutputMB ) { // メッセージボックスはフラグがONにされたときだけ出力 ::MessageBox( NULL, tmp, "DEBUG MESSAGE", MB_OK ); } va_end( ap ); } #define DEBUGPRINTLN DebugPrintfln #else inline void __cdecl DebugPrintfln( bool bOutputMB, const char *fmt, ... ) { char tmp[1024]; if( bOutputMB ) // リリース時はメッセージボックスのみ出力 { va_list ap; va_start( ap, fmt ); vsprintf( tmp, fmt, ap ); ::strcat( tmp, "\n" ); ::MessageBox(NULL, tmp, "DEBUG MESSAGE", MB_OK); va_end( ap ); } } // リリース時は何もしない #define DEBUGPRINT __noop #define DEBUGPRINTLN DebugPrintfln #endif
使用例です。
DEBUGPRINTLN( true, "ID:%dのオブジェクトが生成された(Msg:%s)", id, msg );
おまけで、可変引数を利用してstringを作成する関数も載せておきます。
// stringを作り出す便利関数 inline string MAKESTRING( const char *fmt, ... ) { va_list ap; va_start( ap, fmt ); char tmp[1024]; vsprintf( tmp, fmt, ap ); string tmp2 = tmp; va_end(ap); return tmp2; }
簡単ですが、あったら便利という感じです。