C++:どfprintf結果として、std::string w/o sprintf
質問
私はオープンソースのUNIXツール内部実装はすべてC++で行われ、いの一部変更コードを取得することができるようになりますか。ようになったのは、最小限の変更を希望の私のパッチの受け入れを発表する予定ですソリューション導入可能な標準C++いを外部の依存関係をされていることが好ましい。
ここでは私の問題です。いのC++クラス--ましょう"と呼んでいる"と現在の使用fprintf()印刷、大きく形式のデータ構造をファイルポインタです。その印刷機能でも再帰的には同じ定義の印刷機能の複数の会員の授業("B"の一例)です。別のクラスCる会員std::文字列"foo"とすることができるソフトのprint()の結果のインスタンスA.もto_str()会員機能A.
に擬似コード:
class A {
public:
...
void print(FILE* f);
B b;
...
};
...
void A::print(FILE *f)
{
std::string s = "stuff";
fprintf(f, "some %s", s);
b.print(f);
}
class C {
...
std::string foo;
bool set_foo(std::str);
...
}
...
A a = new A();
C c = new C();
...
// wish i knew how to write A's to_str()
c.set_foo(a.to_str());
このCはおおむね安定的に推移し、BはAの被扶養者)の状態での磁束ので、以下のコードを変更しております。現在の印刷ファイル*F)インターフェースについて通知がありましたので保存されている。していると考えられていくつかの方法を実施::to_str()、それぞれ利点と欠点:
変更の通話fprintf()をsprintf()
- れないような書き換えを任意のフォーマット文字列
- print()がメソッドを実装し直してfprint(fです。to_str());
- がっていなければいけないと考えて手動で配置char[]sが合併しくc文字列で、最後の変換文字の配列は、std::string
くの成果a.print()文字列ストリーム
- この変換を形式の文字列 << 出力形式です。にも数多くありますfprintf(s変換:-{
- print()に書き換えられないの標準的な方法にしたんを出力ストリームからUNIXファイルを扱うもの 内容はこちらからご確認くださっき).
利用力の文字列 形式図書館
- より外部の依存関係.言え.
- フォーマットの書式が異なるほからprintf()さん:
printf(format_str,args)->cout << ブー::フォーマット(format_str)%arg1%arg2%など
利用Qtの QString::asprintf()
- 異なる外部依存性がある。
なので、い浮かべるのは可能です。その場合、だと思うんのページの先頭へ反対の場合、どのようなも見逃?
感謝。
解決
を使用してい#3:の向上の文字列形式の図書館がいることがなかった問題の違いはフォーマット仕様です。
作品のような魅力を私にとっては外部の依存関係が悪化すると(も安定した図書館)
編集:加え用ブー::フォーマットの代わりにprintf:
sprintf(buffer, "This is a string with some %s and %d numbers", "strings", 42);
のようなものになっていくかもこのブー::フォーマットは、図書館の
string = boost::str(boost::format("This is a string with some %s and %d numbers") %"strings" %42);
武器agiは、dexで下がらないboxerぐの解明をご利用のブー::フォーマット
に使用しましたブー::フォーマットとしてsprintf/printf交換4または5アプリケーション(書形式の文字列をファイル、またはカスタム出力に戻)といった問題形式に違いがある。あり(無名)形式の指示子ではなかった問題です。
異なった形式仕様とはほとんどなストリーム(しん)
他のヒント
こちらは熟うための機能と同じ'sprintfが返std::string,免疫をバッファオーバーフロー。このコードの一部である、オープンソースプロジェクトを書い(BSDライセンス)なので、誰でも気軽に利用することが出来ます。
#include <string>
#include <cstdarg>
#include <vector>
#include <string>
std::string
format (const char *fmt, ...)
{
va_list ap;
va_start (ap, fmt);
std::string buf = vformat (fmt, ap);
va_end (ap);
return buf;
}
std::string
vformat (const char *fmt, va_list ap)
{
// Allocate a buffer on the stack that's big enough for us almost
// all the time.
size_t size = 1024;
char buf[size];
// Try to vsnprintf into our buffer.
va_list apcopy;
va_copy (apcopy, ap);
int needed = vsnprintf (&buf[0], size, fmt, ap);
// NB. On Windows, vsnprintf returns -1 if the string didn't fit the
// buffer. On Linux & OSX, it returns the length it would have needed.
if (needed <= size && needed >= 0) {
// It fit fine the first time, we're done.
return std::string (&buf[0]);
} else {
// vsnprintf reported that it wanted to write more characters
// than we allotted. So do a malloc of the right size and try again.
// This doesn't happen very often if we chose our initial size
// well.
std::vector <char> buf;
size = needed;
buf.resize (size);
needed = vsnprintf (&buf[0], size, fmt, apcopy);
return std::string (&buf[0]);
}
}
編集:私がこのコードを知らなかった(笑することが重要であるこC99適合性およびWindowsと高齢glibcが異なりvsnprintf行動は、-1を返します失敗は決定的な措置がどのスペースが必要です。ここでは私の修正コード、誰でも見できるのではないかと考えてたくさんで、編集をいただきたいと考えており、料金は表示されて
std::string
Strutil::vformat (const char *fmt, va_list ap)
{
// Allocate a buffer on the stack that's big enough for us almost
// all the time. Be prepared to allocate dynamically if it doesn't fit.
size_t size = 1024;
char stackbuf[1024];
std::vector<char> dynamicbuf;
char *buf = &stackbuf[0];
va_list ap_copy;
while (1) {
// Try to vsnprintf into our buffer.
va_copy(ap_copy, ap);
int needed = vsnprintf (buf, size, fmt, ap);
va_end(ap_copy);
// NB. C99 (which modern Linux and OS X follow) says vsnprintf
// failure returns the length it would have needed. But older
// glibc and current Windows return -1 for failure, i.e., not
// telling us how much was needed.
if (needed <= (int)size && needed >= 0) {
// It fit fine so we're done.
return std::string (buf, (size_t) needed);
}
// vsnprintf reported that it wanted to write more characters
// than we allotted. So try again using a dynamic buffer. This
// doesn't happen very often if we chose our initial size well.
size = (needed > 0) ? (needed+1) : (size*2);
dynamicbuf.resize (size);
buf = &dynamicbuf[0];
}
}
利用できstd::stringとiostreamsとフォーマットなどのsetw()を呼び出その他iomanip
次のことュニケーション:
void A::printto(ostream outputstream) {
char buffer[100];
string s = "stuff";
sprintf(buffer, "some %s", s);
outputstream << buffer << endl;
b.printto(outputstream);
}
(B::printto
同様)の定義
void A::print(FILE *f) {
printto(ofstream(f));
}
string A::to_str() {
ostringstream os;
printto(os);
return os.str();
}
もちろん、本当に使用snprintfの代わりにsprintfを避けるバッファがあります。きものを選択的に変更によりリスクsprintfsる << 形式は、より安全ての変更などが可能です。
実際に試したほうがよいでしょう、ロキ図書館のSafeFormatヘッダファイルhttp://loki-lib.sourceforge.net/index.php?n=Idioms.Printf).すめの文字列形式の図書館での書式のprintf(...)。
私はこういう事が決められません!
この約直列化?印刷適正ですか。る方の場合は、ブ::直列化します。で"再帰的な"直列化オブジェクトのサブオブジェクトです。