2017-05-22 8 views
-1

printf形式の文字列書式設定を使用するC(> 80k行)の古いMUDコードベースを使用しています。それは普及しています。ほとんどすべてのテキストは、sprintfまたはvsprintfのラッパーを呼び出して実行されます。しかし、私は最近、STLを利用するためにg ++でコンパイルするようになりました。std :: string(実際には大文字と小文字を区別しない比較のための派生クラス)を使いたいと思います。std :: string aware vsprintfのオプション

明らかに、std :: stringを任意のprintf関数の可変引数の1つとして渡すことはできません。すべての場合に.c_str()が必要です。 printf関数への2000回以上の呼び出しを変更したくありません。です。私の質問は:私はどのようにstd :: string aware vsprintfを作ることができます

2つのオプションがあります:std :: stringへのポインタをstd :: string.data(またはc_out())に変更する引数を反復処理する独自のprintf関数を作成してstdに渡します。 :vsprintf、または私はprintfの勇気を借りて自分のロールを張ることができます。最初のオプションは、明らかに仕事が少なくなるように聞こえます。

もちろん、誰かが以前にこの操作を行っていても、私のグーグルでは何も得られていない場合があります。最良の選択肢がどのようになるかについてのヒント

編集: この質問は、How to use C++ std::ostream with printf-like formatting?の複製ではありませんでしたが、これは私がその質問に答えるとは信じられません。私はstd :: ostreamと古いCのprintfを使って文字列を出力する方法を尋ねていません。私は、sprintf/vsprintfを大量に使用する古いCコードベースのパッチソリューションについて、出力ストリームを使用するためにこれらの関数への呼び出しを何千も書き換えずに助けを求めています。

+2

_ "> 80k lines" _これはちょうどピーナッツです。 –

+1

再開。質問:これは** ostream'ではなく、 'string'に関する** **です。はい、両方とも '名前空間std'から来ていますが、共通点はほとんどありません。 – MSalters

答えて

1

printfラッパーを作成できます。このラッパーは、std::stringからchar const*を抽出します。例えば:

#include <iostream> 
#include <string> 
#include <cstdio> 

template<class T> 
inline auto to_c(T&& arg) -> decltype(std::forward<T>(arg)) { 
    return std::forward<T>(arg); 
} 

inline char const* to_c(std::string const& s) { return s.c_str(); } 
inline char const* to_c(std::string& s) { return s.c_str(); } 

template<class... Args> 
int my_printf(char const* fmt, Args&&... args) { 
    return std::printf(fmt, to_c(args)...); 
} 

int main() { 
    std::string name = "World"; 
    my_printf("Hello, %s!\n", name); 
} 

または、より良い、などfmtなどの近代的なC++フォーマットするライブラリへのスイッチ。

+0

YUCK! C++に切り替えるときは、C++でフォーマットできる他のタイプを利用してください! –

+0

答えの唯一のものだったら私はfmtを+1します。周囲のすべてのオプションを使って何かを調理することについての言い訳はありません。 –

+0

fmtライブラリは非常に面白く見えますが、後でそのライブラリを使用することになります。私の特定の問題を解決するために、サンプルコードは非常にうまく機能しています。私はコードを近代化するための単純なビルディングブロックを作っていると思う。ありがとう。 – Rakurai

0

共通の助言は、彼らの例を取るとBoost.Format

です:

// printf directives's type-flag can be used to pass formatting options : 
std::cout << format("_%1$4d_ is : _%1$#4x_, _%1$#4o_, and _%1$s_ by default\n") % 18; 
//   prints "_ 18_ is : _0x12_, _ 022_, and _18_ by default\n" 

は今、これはstd::ostream&を前提とし、あなたはバックバッファとしてstd::stringを使用するstd::stringstreamが必要になります。

PS。大文字と小文字を区別しない比較のための派生クラスを使用すると、あなたを噛んで待っているという悪い考えのように聞こえます。カスタムオーダーが必要です。注文を引き受けるすべてのSTL関数は、カスタム注文をサポートするために過負荷になります。

関連する問題