2016-10-31 7 views
0

私は、空白で区切られた単精度値をASCIIファイルの科学記法で読みました。 1行に複数の値があります。ストリームストリームを介してベクトルを生成します。できるだけ早くインプリメンテーション変換による文字列ストリームからの挿入

// Illustrates typical string from file 
std::string string_with_floats("-2.750000e+001 2.750000e+001 3.450000e+001"); 

// Template parameter is the desired return type 
vector<int> data = ReadValues<int>(string_with_floats); 

template <class T> 
vector<T>& ReadValues(std::string& string_with_data) 
{ 
    std::stringstream ss(string_with_data); 
    std::vector<T> values; 
    T val; 
    while(stream >> val) 
    { 
     values.push_back(val); 
    } 
    return values; 
} 

ベクターにおける結果上記の例では、-2に切り捨て、ちょうど最初の値が移入されたが、おそらくループが終了するので、:ベクトルのプリミティブ型は、データの種類と異なる場合があります数字以外の文字が遭遇する。テンプレートパラメータがfloatであっても、入ってくる文字列にint値が含まれていると、期待どおりに動作します。

暗黙の変換を実行して最も近い整数に丸めるためにstringstreamを設定する方法はありますか?元のプリミティブ型first(float)に挿入してTに明示的キャストを実行する必要はありますか?理想的には、ReadValuesにstring_with_dataのデータの型について伝える必要はありません。double、float、int、short、またはlongのいずれかであり、要求された型もこれらの型のいずれかになります。

ありがとうございました。

答えて

1

あなたはstring_with_data内のデータの種類を知っていれば、それは単純に次のようになります。ただ、そのタイプの1つの値を読み、そしてベクターにそれをプッシュする前に必要な型にキャスト:

template <class T> 
vector<T>& ReadValues(std::string& string_with_data) 
{ 
    std::stringstream ss(string_with_data); 
    std::vector<T> values; 
    float val; // use original type not required one 
    while(stream >> val) 
    { 
     values.push_back((T) val); 
    } 
    return values; 
} 

元の型がわからない場合は、C++や他のすべての型を受け入れるのに十分な大きさの標準ライブラリには単一の型がないので、少し難しくなります。だから、文字列として、各データを読み込み、その後の補助にstringstreamに必要なタイプにそれをデコードする必要があります。

template <class T> 
std::vector<T> ReadValues(std::string& string_with_data) 
{ 
    std::stringstream ss(string_with_data); 
    std::vector<T> values; 
    std::string str; 
    T val; 
    while(ss >> str)   // first store the value into a string whatever it is 
    { 
     std::stringstream(str) >> val; // then read it as the required type 
     values.push_back(val); 
    } 
    return values; 
} 

ことをあなたは確認することができますこの方法:あなたが残っていない

  • あなたは元の文字列

NOTEを読み込むときに必要な型で許可された最大の精度を使用し

  • int型を読み込むときに、ストリームにおけるフロートの一部を末尾:私は

  • +0

    ありがとうございます。最後に提案するアプローチをテンプレートパラメータとして指定しました。私はCスタイルのキャストをstatic_cast (val)に置き換えました。 – pdm2011

    0

    最初の行を取得する代わりに浮動小数点形式でファイルから直接データを抽出しない理由は何ですか?

    double f; 
    std::vector<int> out; 
    std::ifstream file("numbers.txt"); 
    
    file >> std::scientific; 
    
    while (file >> f) 
        out.push_back(out); 
    

    それともあなたはそれをより多くのイテレータフレンドリー行いたい場合:あなたは「オリジナル」を知らない一般的な機能を作りたい、@SergeBallestaが言うように、場合

    std::vector<int> out; 
    std::ifstream file("numbers.txt"); 
    
    file >> std::scientific; 
    
    std::copy(std::istream_iterator<double>(file), 
          std::istream_iterator<double>(), 
          std::back_inserter(out))); 
    

    をターゲットタイプのみをイテレータのように記述します。

    template <class T> 
    std::vector<T> ReadValues(std::string& string_with_data) 
    { 
        std::istringstream ss(string_with_data); 
        std::vector<T> values; 
    
        using iss_it = std::istream_iterator<std::string>; 
    
        std::transform(iss_it(string_with_data), iss_it(), std::back_inserter(values), 
           [](const std::string& x) { return boost::lexical_cast<T>(x) }); 
    
        return values; 
    } 
    
    +1

    ありがとうございます。私は効果的にあなたが提案する最初のオプションのために、テンプレートメソッドではなく行ってきました。ところで、大量のファイルを使用しているistream_iteratorを使用する場合、過去に「不良割り当て」エラーに遭遇しました。使用可能なRAMが豊富な64ビットビルドを使用していました。 – pdm2011

    関連する問題