2011-02-07 3 views
0

私は初心者です。文字列と数値データ(例えば、douubles)をテキストファイルから取得し、それをベクトルに格納するテンプレート関数を作成しようとしました。ベクトルの各要素は異なる名前または番号です。C++ newbie:テンプレート関数の問題 - 文字列と数値データをテキストファイルから取り出してベクトルに入れよう

先週、私は過負荷またはテンプレートがこれに最も適しているかどうか尋ねました。私は、結果のベクトル(私が望むもの)がテンプレートパラメータTを提供する関数に渡されるテンプレートメソッドを使いたいと思います。しかし、私は問題があります。誰かが助けることができれば、私は感謝します!コードは以下の通りですが、それに続いてエラーが表示されます。

//私のコード:メインで

template<typename T> 
void readFile(const std::string& name, const std::string& find, std::vector<T>& results){ 
    std::ifstream file(name.c_str()); 
    std::string line; 

    while(std::getline(file, line)) 
    { 
     if(line == find) 
     { 
      std::getline(file, line); 
      line.erase(remove(line.begin(), line.end(), '\''), line.end()); 
      std::istringstream streamLine(line); 

      results = std::vector<T>(std::istream_iterator<T>(streamLine), std::istream_iterator<T>()); 
     } 
    } 
} 

コール():

readFile(name, "label", results); 

私は取得していますエラーは以下の通りです。関数呼び出しがどのように定義に一致しないのか分かりません。愚かな間違いのための事前の謝罪!

error: no matching function for call to 
'std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, 
std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > 
::resize(std::basic_string<char, std::char_traits<char>, std::allocator<char> >&)' 

私が関数にvoidの代わりに "result"を返すようにすると、物事はうまくいくようです。関数定義でreturn文で

std::vector<T> readFile(const std::string& name, const std::string& find, std::vector<T>& results) 

:ここで私が何を意味するかだ

return std::vector<T>(std::istream_iterator<T>(streamLine), std::istream_iterator<T>()); 

しかし、このようにそれを行うには不格好/悪いスタイルらしいです。私は参照を使う方が良いと思っていたでしょう。それがうまくいかない場合でも、最初の方法(voidを含む)がうまくいかない理由を知りたいのです。

ヒントをいただければ幸いです!

+0

「結果」と呼び出し前のコードは 'readFile'のように見えますか? – Nim

+0

こんにちはNim ... main():const std :: string name = "test.dat";その後、std :: vector 結果。ベクトルを返す – Ant

+1

は悪くないかもしれません。ローカル変数に直接代入すると、コンパイラはそのコピーを削除することができます。 http://en.wikipedia.org/wiki/Return_value_optimizationを参照してください。 – tenpn

答えて

1

これを完全にコンパイル可能なコードスニペットにするには、多大な労力をかけなければなりませんでした。ここに私が思いついたのがあります:

#include <string> 
#include <vector> 
#include <istream> 
#include <fstream> 
#include <iterator> 
#include <sstream> 
#include <algorithm> 

template<typename T> 
void readFile(const std::string& name, 
       const std::string& find, 
       std::vector<T>& results) 
{ 
    std::ifstream file(name.c_str()); 
    std::string line; 

    while(std::getline(file, line)) 
    { 
     if(line == find) 
     { 
     std::getline(file, line); 
     line.erase(remove(line.begin(), line.end(), '\''), line.end()); 
     std::istringstream streamLine(line); 

     results = std::vector<T>(std::istream_iterator<T>(streamLine), 
            std::istream_iterator<T>()); 
     } 
    } 
} 

void do_it_with_strings(std::vector<std::string> &results) 
{ 
    readFile("fred", "barney", results); 
} 

このコードスニペットはgcc 4.5.1でうまくコンパイルされます。 main機能の正確なタイプはnameresultsですか?また、問題は、ベクトルのresize関数を呼び出すように思われる。ベクタのコンストラクタや代入演算子が内部的に行う可能性はありますが、コード内で直接実行しているようには見えません。

しかし、これに関係なく、とにかくあなたのコードを書く方法はありません。私はあなたの代わりにこれを行うことをお勧め:このような機能では

#include <string> 
#include <vector> 
#include <istream> 
#include <fstream> 
#include <iterator> 
#include <sstream> 
#include <algorithm> 

template<typename T> 
std::vector<T> readFile(const std::string& name, const std::string& find) 
{ 
    std::ifstream file(name.c_str()); 
    std::string line; 

    while(std::getline(file, line)) 
    { 
     if(line == find) 
     { 
     std::getline(file, line); 
     line.erase(remove(line.begin(), line.end(), '\''), line.end()); 
     std::istringstream streamLine(line); 

     return std::vector<T>(std::istream_iterator<T>(streamLine), 
           std::istream_iterator<T>()); 
     } 
    } 
    return std::vector<T>(); 
} 

void do_it_with_strings(std::vector<std::string> &results) 
{ 
    results = readFile<std::string>("fred", "barney"); 
} 

を、私はそれが明示的にあなたが関数を呼び出す際に読み取るためにではなく、それは暗黙のうちから決定している期待しているタイプを記述するために、より良いことだと思います。vectorあなたが合格の種類

+0

ありがとう、オニファリウス。時間があれば、なぜあなたが「削除」を定義したのかを説明することができれば素晴らしいでしょう。私はそれがSTLによって提供されたものだと思った(私はそれを定義していない)。また、C++ 0xのSTLの "move assignment"がどういうものなのか分かりませんが、リターンを使う効率的なコストは私にとっては不便ではないと思いますので、リターンを使用します。助けに多くの時間を取ってくれてありがとう! – Ant

+0

@Ant - これはstd :: removeが存在しないことを忘れていて、 'remove'を残していたので' getline'を修飾していましたので、あなたが定義した関数だと思いました。 – Omnifarious

+0

@Ant - STLの「削除」を使用するように私の質問を修正しました。 – Omnifarious

1

ここでは、ファイルからあなたの文字列または数値のいずれかを取得するコードの一部です:

#include <fstream> 
#include <vector> 
#include <iterator> 
#include <algorithm> 

template<typename T> 
void read_values(const std::string& filename, std::vector<T>& coll) 
{ 
    std::fstream file(filename); 

    std::copy (std::istream_iterator<T>(file),  
       std::istream_iterator<T>(), 
       back_inserter(coll)); 

    std::sort(coll.begin(), coll.end()); 

    coll.erase(std::unique(coll.begin(), coll.end()), coll.end()); 
} 

int main(int argc, char* argv[]) 
{ 
    std::vector<int> values; 
    read_values("C:\\example.txt", values); 

    return 0; 
} 

あなたの代わりに文字列値を読みたい場合は、あなただけの必要はstd :: stringからpasへのstd :: vectorを提供するsをテンプレート関数に追加します。

関連する問題