How to read integers of space and newline in a 2D array in C ++?

I have a .txt file of numbers (in this case, everything is less than 100), separated by spaces, in lines separated by new lines. Something like that:

41 53 07 91 44 52 17 13 03 21 

I would like to read these numbers in a 2d array exactly the same as they appear, so that spaces separate the columns of the array and new lines highlight the lines.

I can make it read lines as lines, but then I have problems separating individual numbers and getting them to treat them as integers.

+6
source share
5 answers

Try the following:

 #include <vector> #include <string> #include <fstream> #include <sstream> #include <iostream> int main() { // The result of the read is placed in here // In C++, we use a vector like an array but vectors can dynamically grow // as required when we get more data. std::vector<std::vector<int> > data; // Replace 'Plop' with your file name. std::ifstream file("Plop"); std::string line; // Read one line at a time into the variable line: while(std::getline(file, line)) { std::vector<int> lineData; std::stringstream lineStream(line); int value; // Read an integer at a time from the line while(lineStream >> value) { // Add the integers from a line to a 1D array (vector) lineData.push_back(value); } // When all the integers have been read, add the 1D array // into a 2D array (as one line in the 2D array) data.push_back(lineData); } } 
+15
source

Well, the requirement of “exactly how they look” means that you need a dangling array if different numbers of columns appear on different rows. I would use std::vector< std::vector<long> > . Each contained vector corresponds to one line.

So, every time you read a line of text, create a new empty vector.

Call strtol several times on the line you are reading using push_back to assemble them into a vector. When the output pointer matches the input pointer (this indicates a failure, possibly because you have reached the end of the line), push_back entire vector and start the next line.

Something like that:

 std::vector< std::vector<long> > all_data; std::string text_row; while(getline(fin, text_row)) { all_data.push_back(); std::vector<long>& this_row = *all_data.rend(); const char* p1 = text_row.c_str(); const char* p2; while (1) { long num = strtol(p2 = p1, &p1, 0); if (p1 == p2) break; this_row.push_back(num); } /* to ignore blank lines, add this code if (this_row.empty()) all_data.pop_back(); */ } 
+1
source

The following code shows how to solve your problem. It also shows how you can use RAII when opening a file. This is good practice when acquiring resources. By acquiring a resource in the constructor and freeing it in the destructor, resource leakage can be prevented if an exception is thrown. This is considered good practice in the C ++ world.

 #include <fstream> #include <vector> struct FileHandle { std::ifstream file_; FileHandle(std::string file_name) { file_.open(file_name); } ~FileHandle() { file_.close(); } }; bool next_char_is_end_of_line(std::ifstream &file) { bool found = false; char c; file.get(c); if(c == '\n') found = true; file.unget(); return found; } int main() { FileHandle fh("c:\\your_file.txt"); std::vector<std::vector<int> > v; std::vector<int> current_line; int x; while(fh.file_ >> x) { current_line.push_back(x); if(next_char_is_end_of_line(fh.file_)) { v.push_back(current_line); current_line.clear(); } } //Then just access each std::vector<std::vector<int>> //v[0].size(); ... return 0; } 

This code gives you a “jagged” vector, putting all the numbers on each line in a separate vector. Then this vector is added to the main vector. Therefore, each line in the "vector" may have a different length. I think you understand that ...

Good luck

+1
source

There are actually two problems:

  • how to recognize the entrance and ...
  • how to imagine it in memory.

You talked about "2d Array": is it a requirement or just a hypothesis? 2x5 size required or just a sample?

You talked about the layout of the file. Is that necessary or not? Do you have to admit (and verify) the ultimate misleading as there are more numbers, or misalignment? What do you need to do if the line has 6 numbers first and 4 second?

A very simple solution can use a 2x5 array and fill it with a secure loop:

 #include <iostream> #include <fstream> #include <iomanip> #include <stdexcept> const int ROWS=2; const int COLS=5; int main(int argc, char** argv) { int m[ROWS][COLS]; try { std::ifstream s(argv[1]); if(!s) throw std::runtime_error("cannot open file"); for(int r=0; r<ROWS; ++r) for(int c=0; c<COLS; ++c) if(!(s >>m[r][c]) throw std::runtime_error("insufficient or bad input"); } catch(const std::exception& e) { std::cout << "Reading error: " << e.what() << std::endl; return -1; } std::cout << "read matrix is \n"; for(int r=0; r<ROWS; ++r) { for(int c=0; c<COLS; ++c) std::cout << std::setw(8) << m[r][c]; std::cout << '\n'; } std::cout << std::endl; return 0; } 

This will read 10 numbers separated by "spaces", regardless of how they are distributed and aligned. (2x5 is assumed to be an adversary.)

On the other hand, you may have to determine how wide the matrix is: a file can have any number of lines, each of which contains any number of elements.

In this case, you need a “flexible structure” and you need to identify the rows and elements in the rows.

 #include <iostream> #include <fstream> #include <string> #include <vector> #include <sstream> #include <iomanip> #include <stdexcept> #include <utility> int main(int argc, char** argv) { std::vector<std::vector<int> > m; try { std::ifstream fs(argv[1]); if(!fs) throw std::runtime_error("cannot open input file"); while(fs) { std::string line; std::getline(fs,line); std::vector<int> row; std::stringstream ss(line); int x; while(ss >> x) row.push_back(x); if(!row.empty()) m.emplace_back(std::move(row)); } } catch(const std::exception& e) { std::cout << "Reading error: " << e.what() << std::endl; return -1; } std::cout << "read lines: \n"; for(auto i=m.begin(); i!=m.end(); ++i) { for(auto j=i->begin(); j!=i->end(); ++j) std::cout << std::setw(8) << *j; std::cout << '\n'; } std::cout << std::endl; return 0; } 
0
source
-1
source

Source: https://habr.com/ru/post/910015/


All Articles