In this SO question, there is a brilliant answer due to @HowardHinnant that extracts numbers from a text file into a vector very efficiently. Here is the code for brevity:
#include <fstream>
#include <iostream>
#include <vector>
#include <string>
#include <sstream>
#include <iterator>
// g++ -std=c++11 test.cpp -o t
int main()
{
std::ifstream theStream("data.txt");
if( ! theStream )
std::cerr << "data.txt\n";
while (true)
{
std::string line;
std::getline(theStream, line);
if (line.empty())
break;
std::istringstream myStream( line );
std::istream_iterator<int> begin(myStream), eof;
std::vector<int> numbers(begin, eof);
// process line however you need
std::copy(numbers.begin(), numbers.end(),
std::ostream_iterator<int>(std::cout, " "));
std::cout << '\n';
}
}
A sample of the data would be
800 170 84 439
129 902 103 492 394 140 496 893
229 645
164 389 74 208 726 315
291 421 230 789 246 791 762
416 241 538 810 605
714 555 54 863
288 465 563 831
0 339 740 427 718
449 675 545 842 779 607
274 958
I have studied this code for two days now, and can't quite grasp how to extract the numbers from each line. So, how can I access, lets say, the 3rd number on the second row (103), or more generally, the nth number on the mth row?
Any explanation of how this solution works would really help too!
Use a vector
of vectors
to store each lines numbers seperately:
#include <fstream>
#include <iostream>
#include <vector>
#include <string>
#include <sstream>
#include <iterator>
int main()
{
std::ifstream theStream("data.txt");
if (!theStream)
std::cerr << "data.txt\n";
std::vector<std::vector<int>> data; // vector to hold the numbers of each line seperately
while (true)
{
std::string line;
std::getline(theStream, line);
if (line.empty())
break;
std::istringstream myStream(line);
std::istream_iterator<int> begin(myStream), eof;
std::vector<int> numbers(begin, eof);
// process line however you need
data.push_back(numbers); // add numbers of current line to data
}
std::cout << data[1][2] << '\n'; // 2nd row, 3rd number: 103
}
Assuming the query will only be made once, you can do it in one pass by counting which row and column you're on while you're extracting (and with each iteration of the while loop); then break from there. This is so that you don't have to read the entire file.
Which might look like:
#include <cstddef>
#include <fstream>
#include <iostream>
#include <string>
#include <sstream>
int main()
{
std::ifstream theStream("data.txt");
if (!theStream)
std::cerr << "data.txt\n";
std::size_t target_row = 2; // 1-based
std::size_t target_col = 3; // 1-based
int value = 0;
int valid = false;
for (std::size_t current_row = 1; true; ++current_row)
{
std::string line;
if (!std::getline(theStream, line) || line.empty())
break;
if (current_row != target_row)
continue;
std::istringstream myStream(line);
for (std::size_t current_col = 1; myStream >> value; ++current_col)
if (current_col == target_col) {
valid = true;
break;
}
break;
}
if (!valid)
std::cerr << "No such row and column!\n\n";
else
std::cout << value;
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.