1

ファイルからフロートを読み取り、ベクターにプッシュする必要があります。一時フロートを使用して彼を機能させることができますが、今はフロートなしで試しています。

何らかの理由で、以下が機能しません。

std::ifstream fileHandle(filename);
std::vector<float> vect;
std::string id;
while (!fileHandle.eof()){
    fileHandle >> id;
    std::copy(std::istream_iterator<float>(fileHandle),
              std::istream_iterator<float>(),
              std::back_inserter(vect));
    std::copy(std::istream_iterator<float>(fileHandle),
              std::istream_iterator<float>(),
              std::back_inserter(vect));
    std::copy(std::istream_iterator<float>(fileHandle),
              std::istream_iterator<float>(),
              std::back_inserter(vect));
}

次のようなファイルで

v 0.000000 0.000000 1.000000
v 1.000000 0.000000 1.000000
...

デバッグすると、最初の呼び出しで3 つのフロート (行全体) がベクターにcopyプッシュされているようです。次の行の 'v' でファイル イテレータがフリーズするように見えることを除いて、これは実際には問題ありません。行と呼び出しは、ファイル反復子をその時点から前方に移動せず、無限ループを作成します。1 つの呼び出しのみを使用しても、同じ結果が得られました。fileHandle >> id;copycopy

私は何を間違っていますか?

4

2 に答える 2

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

// it is a good idea to create an structure to hold the data you will
// be working with. In this case I am creating a bare-bones struct
// containing a single data element
struct entry {
  double data[3];  
};

// when you have an structure, you can overload the >> operator; this
// will allow you to simplify later calls (as you will see below). In
// this case, because your data file contains a "dummy" character I
// use a dummy string. Notice that the return type is bool, and it
// means "I was able to read what you wanted me to read", in this case
// a line with one string and three doubles (because the type of each
// e.data[k] is "double")
bool operator>>(std::istream& is, entry& e) {
  std::string dummy;
  return is>>dummy>>e.data[0]>>e.data[1]>>e.data[2];
}


int main() {
  // create a vector to hold the entries (notice that "entry" is the
  // data type you created above)
  std::vector<entry> entries;

  { // the bracket on the left will provide a "scope" for the "fp"
    // variable. When the scope ends, "fp" will be automatically
    // destroyed. For "fp" that means that the "close()" method will
    // be called upon destruction, and you don't need to worry about
    // ensuring that your files are closed (to lear more about this
    // google for RAII)

    std::ifstream fp("test.txt");
    // the iterators DO NOT REQUIRE A LOOP (they "provide" the loop;
    // they are used precisely to avoid coding the loop)

    std::copy(std::istream_iterator<entry>(fp),
              std::istream_iterator<entry>(),
              std::back_inserter<std::vector<entry>>(entries));
    // notice that the back inserter will insert "entry" types into
    // the "entries" vector as long as it can continue reading them
    // (that is, as long as ">>" continues to return "true"

  } // the bracket on the left is finishing the scope I talked about
    // above. Past this point fp no longer exists, and the file has
    // been closed

  // off you go - you have your vector full of "entry" instances which
  // you can use normally
  std::cout<<"read "<<entries.size()<<" entries: "<<std::endl;
  for(auto e:entries) {
    std::cout<<e.data[0]<<", "<<e.data[1]<<", "<<e.data[2]<<std::endl;
  }

  return 0;
}

以下を使用して、gcc 4.7.2 を使用してこのソース コードをコンパイルしました。

g++ example.cpp -std=c++11

あなたが提供したとおりのファイル(私はそれを「test.txt」と呼びました)を使用すると、次のようになります。

read 2 entries: 
0, 0, 1
1, 0, 1
于 2013-05-10T18:38:42.527 に答える
2

ブーストスピリットを使用した簡単なアプローチを次に示します。

これにより、実際の文法がインラインで定義されるため、驚くほどの柔軟性が得られます。

('v' >> qi::float_ >> qi::float_ >> qi::float_) % qi::eol,

完全なプログラムは次のとおりです。

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/karma.hpp>

namespace qi    = boost::spirit::qi;

int main()
{
    std::cin >> std::noskipws;
    boost::spirit::istream_iterator f(std::cin), l;

    std::vector<float> vect;

    bool ok = qi::phrase_parse(f,l, // std::cin
            ('v' >> qi::float_ >> qi::float_ >> qi::float_) % qi::eol,
            qi::blank, // ignore any whitespace separators
            vect);     // keep appending to a vector 
            // (this could easily be a vector of structs containing 3 floats)

    if (ok)   
    {
        std::cout << "parse success\n";

        // only for verification output:
        using namespace boost::spirit::karma;
        std::cout << "parsed vect: \n" << format_delimited(columns(3) [ *auto_ ], ' ', vect) << "\n";
    }
    else std::cerr << "parse failed: '" << std::string(f,l) << "'\n";

    if (f!=l) std::cerr << "trailing unparsed: '" << std::string(f,l) << "'\n";
    return ok;
}
于 2013-05-10T19:06:32.460 に答える