std::stringを返すsprintfっぽい関数

2010/05/12 | By KUMA | Filed in: 技術メモ.

長めの定型文を出さなきゃならんコードを書く必要があるのだが、perlではパフォーマンス的に厳しいので、c++/stl環境でsprintfっぽい動きをしてくれるものを(自分で作るのはかったるいので)探していた。

すると、こちらで公開されているでないか。ありがとうございます。

バックアップがてらそのまま引用させていただく。

/**********************************************************************
 CのsprintfをC++/STLで実現する
 使い方
    std::string str = cformat( "%d:%s", intvalue, charpointer);
 試したコンパイル環境
    VC++ .NET 2003 / WINDOWS XP Professional 64 bit edition.
    GCC C++ 3.3.6 / glibc 2.3.4 / Vine Linux 4.2
**********************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <vector>
#include <string>
#include <stdexcept>

#ifdef _WIN32
#define vsnprintf   _vsnprintf
#endif

std::string cformat( char *format, ...)
{
    int bufsize = 1024; // 適当なサイズ
    std::vector<char>   buff(bufsize);
    va_list args;

    // 適当なバッファサイズで先ずは、vsnprintfを試す。
    // 出力がバッファサイズ以上の場合、VC++ .NET 2003の場合は -1、
    // glibc2.1以降は、書き込みに必要なサイズを返す。
    va_start(args, format);
    int vssize = vsnprintf( &buff[0], bufsize, format, args);
    va_end(args);

    // vsnprintfが成功した場合終了する。
    if ( vssize >= 0 && vssize < bufsize ) {
        buff.resize(vssize);
        return std::string( buff.begin(), buff.end() );
    }

#ifdef _WIN32
    // VC++ .NET 2003 書き込みに必要なサイズを取得する。
    va_start(args, format);
    vssize = _vscprintf( format, args);
    va_end(args);
#endif

    if ( vssize < 0 ) throw std::runtime_error(format);

    // サイズを再割り当てし、再度試す
    buff.resize(vssize + 1);
    va_start(args, format);
    vssize = vsnprintf( &buff[0], vssize + 1, format, args);
    va_end(args);
    if ( vssize < 0 ) throw std::runtime_error(format);
    buff.resize(vssize);
    return std::string( buff.begin(), buff.end() );
}

↑と、stringstreamを使って定型文を無事簡潔に出力することができた。


Tags: ,

Comments are closed here.