2016-07-06 7 views
3

std::basic_istreamから特定の文字数を抽出してstd::stringに保存すると、安全で安全な方法はありますか?特定の文字数をstd :: basic_istreamからstd :: stringにコピーする

私は最終的に resultを取得するために char[]を使用しますが、私はPODの種類を回避し、より安全でより保守何か確保したいと考え、以下のプログラムで

#include <sstream> 
#include <string> 
#include <iostream> 
#include <exception> 

int main() 
{ 
    std::stringstream inss{std::string{R"(some/path/to/a/file/is/stored/in/50/chars   Other data starts here.)"}}; 
    char arr[50]{}; 
    if (!inss.read(arr,50)) 
     throw std::runtime_error("Could not read enough characters.\n"); 

    //std::string result{arr}; // Will probably copy past the end of arr 
    std::string result{arr,arr+50}; 

    std::cout << "Path is: " << result << '\n'; 
    std::cout << "stringstream still has: " << inss.str() << '\n'; 

    return 0; 
} 

代替:

  • 変換を上の文字列全体にストリーム:std::string{inss.c_str()}
    • これは悲しいldはストリーム全体のコピーを作成します。
  • は、これはまだ中間PODの配列を使用することになりchar[]
    • を受け入れるようにテンプレート関数を記述します。ループ内
  • 使用std::basic_istream::get一緒std::basic_string::push_back
    • でループを文字の必要数を読み取るために少し扱いに​​くいようだが、それは、配列を避けるん。
+0

可能な複製(C++ 11以降):[?コピーせずにstringstreamのうち、文字を取得する方法](http://stackoverflow.com/questions/28663075/how-to-get-characters-out -of-stringstream-without-copy) – NathanOliver

+0

ファイル名を50文字以下にすることは保証されていますか? –

+0

@QPaysTaxesファイル形式には、ファイル名に割り当てられた最初の50文字が含まれています。したがって、ファイル形式が同じである限り保証されます。ファイル形式が変更され、コードが変更される危険性があります。 – wally

答えて

2

だけresult文字列に直接それを読んで。

#include <sstream> 
#include <string> 
#include <iostream> 
#include <exception> 

int main() 
{ 
    std::stringstream inss{std::string{R"(some/path/to/a/file/is/stored/in/50/chars   Other data starts here.)"}}; 
    std::string result(50, '\0'); 

    if (!inss.read(&result[0], result.size())) 
     throw std::runtime_error("Could not read enough characters.\n"); 

    std::cout << "Path is: " << result << '\n'; 
    std::cout << "stringstream still has: " << inss.str() << '\n'; 

    return 0; 
} 

C++ 11、std::stringfrom cppreference)のメモリレイアウトに関する以下の保証以来。 basic_string

要素は、basic_string sために、すなわち、連続[0, s.size())の任意nため&*(s.begin() + n) == &*s.begin() + nに格納されている、または、等価的に、s[0]へのポインタが最初の要素へのポインタを期待する関数に渡すことができCharT[]配列の配列。

+2

@jaggedSpire 'pos'が' size'関数から返された値と等しいときにアクセスします。この例では、 'pos'には' 0'が使われ、 'size'には' 50'が返され、未定義の振る舞いはありません。 –

+0

これはまさに私が探していた答えです。今それはとても明白だと思う... :) – wally

+0

@JamesAdkisonうん、私は投稿した後にそれをキャッチしました。ごめんなさい。 – jaggedSpire

関連する問題