2016-03-28 17 views
2

私は非ヌル終了文字列を返すレガシー関数をいくつか持っています。非ヌル終了C文字列を終了C文字列に変換する最もきれいな方法

struct legacy { 
    char a[4]; //not null terminated 
    char b[20]; //not null terminated 
}; 

私はこれらの文字配列を周りにたくさん渡しています。それらをヌルに変換するにはクリーンな方法が必要です。

これは私がやっていたもので、今の時点で:

legacy foo; 
std::string a(foo.a, sizeof(foo.a)); 
std::string b(foo.b, sizeof(foo.b)); 
bar(foo.a.c_str(), foo.b.c_str()); 

私は何かのようにこのコードを減らすためのクラスとテンプレートを使用することができますきれいな方法はあります...

legacy foo; 
bar(make_null_terminated(foo.a), make_null_terminated(foo.b)); 
+0

'バー()' 'だけのconstのchar *'を取るのか?それはそれらを保持しているのか、ntbsの寿命は 'bar()'の呼び出しを最後にする必要はありませんか? – Barry

+0

@バリーバーは 'const char *'を取るだけです – andre

+0

他のものを取るように変更することはできますか? – Barry

答えて

7

何かが行う必要があります。

struct make_null_terminated { 
    template <size_t sz> 
    make_null_terminated(char (&lit)[sz]) : str(lit, sz) {} 
    operator const char*() const { return str.c_str(); } 
private: 
    std::string str; 
} 

これは、あなたが望むように使用することができます。

EDITタグを編集した後、std::beginstd::endlを削除しました。

0

あなたは、単に次のことができます。このような

std::string a(std::begin(foo.a), std::end(foo.a)); 
+0

std :: endはすでに終了文字がNULLであると仮定していますか? – andre

+0

私はあなたが質問のポイントを見逃していると思います - これを関数(テンプレート)にカプセル化できますか? –

+0

@andre:そうではありません。 –

0

私が考えることができる最もクリーンな方法は、イテレータの一種であるポインタstd :: stringのイテレータコンストラクタを使用することです。

bar(std::string(std::begin(foo.a), std::end(foo.a)).c_str(), 
    std::string(std::begin(foo.b), std::end(foo.b)).c_str()); 

ここには何が起こっているのですか?

  1. foo.aにバイトをコピーして追加することにより、文字列を作成末尾ゼロ

  2. 同上foo.b

  3. コールに対して(これはスタンダード::文字列の中にカプセル化されます)テンポラリ文字列のメソッドc_str()は、内部でヌルで終了するC文字列へのポインタを取得します。

  4. コールバー

  5. 一時的な文字列を破壊

+0

Toooooたくさんのタイピング: – SergeyA

+0

@SergeyA対策2回、一度カット。それで、どのくらい入力しても問題ありません。もう一度触れる必要はありません。 –

+0

'legacy'からのデータを必要とする関数のすべての呼び出しに対して。私はOPには1つ以上のものがあると信じています。 – SergeyA

関連する問題