How to fill vectors by reading a file?

2019-01-29 11:47发布

问题:

I am trying to read a file which contains the adjacency list as

1 37 79 164 15
2 123 134 10 141 13

where first number in every line is vertex and following numbers are its adjacent vertices.

This is my code to read from the file . I have been able to put a line in a string but don't know how to proceed to populate the vector.

    ifstream ifs;
string line;
ifs.open("kargerMinCut.txt");
std::vector<vector <int> > CadjList(vertices);
while(getline(ifs,line)){
}

Any suggestions ?

回答1:

You can use stringstream in the sstream header.

ifstream ifs;
string line;
ifs.open("kargerMinCut.txt");
std::vector<vector <int> > CadjList(vertices);
while(getline(ifs,line)){

    // transfer the line contents to line_stream.
    stringstream line_stream( line );

    // transfer line_stream to int variables.
    int tail_node;
    if ( line_stream >> tail_node ) // now do whatever you want with it.
    {
        int head_node;
        while ( line_stream >> head_node )
            CadjList[tail_node].push_back( head_node );
    }    
}


回答2:

Use the power of STL! ;-)

  • std::istringstream to create a stream from a string.
  • std::copy to copy stuff from something to something else (yes, it can be that generic!).
  • std::istream_iterator and std::ostream_iterator to read and write to stream with an iterator interface, very useful in combination with std::copy.
  • std::back_inserter to use push_back with std::copy.
  • std::vector's constructor can take iterators to initilize its content.
  • std::map might be better than a std::vector if your vertex are not a continuous range starting from 0.

Which gives something like:

// vertex -> adjacent vertices
std::map<int, std::vector<int>> map;

std::string line;
while (std::getline(ifs, line))
{
    std::istringstream is(line);
    std::vector<int> ns;
    std::copy(std::istream_iterator<int>(is), std::istream_iterator<int>(), 
              std::back_inserter(ns));

    assert(ns.size() > 1); // or throw something

    // The first is the vertex
    map[ns[0]] = std::vector<int>(ns.begin() + 1, ns.end());
}

Live example

Alternative implementation, assuming the file is not corrupt:

// vertex -> adjacent vertices
std::map<int, std::vector<int>> map;

std::string line;
while (std::getline(ifs, line))
{
    std::istringstream is(line);
    std::vector<int> ns;

    // assuming we know for sure the file is valid
    auto it = std::istream_iterator<int>(is);
    auto end = std::istream_iterator<int>();
    auto vertex = *(it++); // and not ++it !
    map[vertex] = std::vector<int>(it, end);
}

live example

Generally speaking, <algorithm> contains many nice functions.



回答3:

Code in the while loop:

while(std::getline(ifs,line))
{
  std::vector<int> temp;
  std::istringstream str(line);
  int n;
  while ( str >> n )
  {
     temp.push_back(n);
  }

  CadjList.push_back(temp);
}