2016-04-08 22 views
1

答えがhereであることを理解しようとしていますが、うまくいかないようです。ここでイテレータで正しくstd :: vectorを読み込んでファイルに書き込む

は、私が試したものです:

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

int main() 
{ 
    std::string path("numbersfile"); 

    std::vector<int> myVector{1,16,32,64}; 
    std::vector<int> newVector{}; 

    std::ofstream FILE(path,std::ios::out | std::ofstream::binary); 
    std::copy(myVector.begin(),myVector.end(),std::ostreambuf_iterator<char>(FILE)); 

    std::ifstream INFILE(path,std::ios::in | std::ifstream::binary); 
    std::istreambuf_iterator<char> iter(INFILE); 
    //std::copy(iter.begin(),iter.end(),std::back_inserter(newVector)); //this doesn't compile 
    std::copy(iter,std::istreambuf_iterator<char>{},std::back_inserter(newVector)); // this leaves newVector empty 
} 

newVectorは最後copy後も空です。最後のステートメントを更新してnewVectorを埋め込む方法

+3

'FILE.flush();最初の'のstd :: copy'後 '右? –

+0

はい、それは動作します! – wally

答えて

4

ファイルは、2番目のcopyが呼び出されるまでに読み込めません。 (コメントで彼の答えのためのピョートルSkotnickiのおかげで)

flushへの呼び出しは、プログラムが動作することができます:ifstreamが作成されたときに

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

int main() 
{ 
    std::string path("numbersfile"); 

    std::vector<int> myVector{1,16,32,64}; 
    std::vector<int> newVector{}; 

    std::ofstream FILE(path,std::ios::out | std::ofstream::binary); 
    std::copy(myVector.begin(),myVector.end(),std::ostreambuf_iterator<char>(FILE)); 
    FILE.flush(); // required here 

    std::ifstream INFILE(path,std::ios::in | std::ifstream::binary); 
    std::istreambuf_iterator<char> iter(INFILE); 
    //std::copy(iter.begin(),iter.end(),std::back_inserter(newVector)); //this doesn't compile 
    std::copy(iter,std::istreambuf_iterator<char>{},std::back_inserter(newVector)); // this leaves newVector empty 
    return 0; 
} 

ofstreamは、スコープ内にまだあります。 ofstreamのデストラクタが呼び出されていれば、ファイルはifstreamのために準備されているはずです。次のプログラムではifstreamが自動的に破壊されています

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

std::string filename("numbersfile"); 

std::vector<char> myVector{1,16,32,64}; 

void write_vector_to_file(const std::vector<char>& myVector, std::string filename); 
std::vector<char> read_vector_from_file(std::string filename); 

int main() 
{ 
    write_vector_to_file(myVector, filename); 
    auto newVector{read_vector_from_file(filename)}; 
    return 0; 
} 

void write_vector_to_file(const std::vector<char>& myVector,std::string filename) 
{ 
    std::ofstream ofs(filename,std::ios::out | std::ofstream::binary); 
    std::ostream_iterator<char> osi{ofs}; 
    std::copy(myVector.begin(),myVector.end(),osi); 
} 

std::vector<char> read_vector_from_file(std::string filename) 
{ 
    std::vector<char> newVector{}; 
    std::ifstream ifs(filename,std::ios::in | std::ifstream::binary); 
    std::istreambuf_iterator<char> iter(ifs); 
    std::istreambuf_iterator<char> end{}; 
    std::copy(iter,end,std::back_inserter(newVector)); 
    return newVector; 
} 
3

は、コードの欠陥の数があります。

  1. あなたは、これが BAD BAD BAD IS FILEという名前の変数を定義します。 FILEは既に存在するオブジェクトの名前です。vectorのインスタンスの名前をstd::vector<int>array{}とすることに匹敵します。
    紛らわしいだけでなく、命名の衝突につながる可能性が極めて高いため、非常に危険です。さらに、すべての議院名は、がマクロの予約番号に予約されている必要があります。

  2. ファイルが実際に開かれているかどうかを決して確認することはできません。コンパイラは警告を表示せず、ストリームには何も表示されません(明示的にチェックされていない限り)。だから、あなたは常にチェックするべきです。あまりにストリームのブール演算子を使用している最も簡単な方法は:
    if (!ifile) throw std::runtime_error("error opening file");

  3. あなたは、これはコンパイルできないことを書いた:

    std::copy(iter.begin(),iter.end(),std::back_inserter(newVector));

    なぜこの仕事がしませんか?イテレータ自体にはbeginendの関数がありません。イテレータに関連付けられたオブジェクトには、それらのメソッドがあります。ここで一緒にすべてのことを組み合せる

  4. はあなたのコードの修正版です:

    { 
        std::string path("numbersfile"); 
    
        std::vector<int> myVector{ 1,16,32,64 }; 
        std::vector<int> newVector{}; 
    
    
        std::ofstream outfile(path, std::ios_base::binary); 
        std::copy(myVector.begin(), myVector.end(), std::ostreambuf_iterator<char>(outfile)); 
    
        outfile.close(); 
    
        std::ifstream infile(path,std::ios_base::binary); 
        std::istreambuf_iterator<char> iter(infile); 
        std::copy(iter, std::istreambuf_iterator<char>(), std::back_inserter(newVector)); // this leaves newVector empty 
    
        infile.close(); // close explicilty for consistency 
    } 
    
+0

レビューをいただき、ありがとうございます。私は元の答えから命名しました。それは恐ろしいです。 :)コンパイルされていない部分も[受け入れられた回答](http:// stackoverflow。com/a/12372783/1460794)。この文脈では 'close'を明示的に使用することを示唆しています。私はあなたが提案した「スロー」を追加しようとしましたが(良い一般的な慣行ですが)、MSVCでプログラムを実行したときにこの問題に対処するのではなく、スローしませんでした。 – wally

+0

throw文がうまくいくはずです。あなたが ''ヘッダを含んでいることを確認してください。開かれるたびに 'if'-' throw'文を追加してください。 –

+0

いいえ、うまくいきませんでした。また、ここでは動作しません(http://coliru.stacked-crooked.com/a/90498043343607e1)。 – wally

関連する問題