Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

c++

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

 41 53 07 91 44
 52 17 13 03 21

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

I can get it to read the lines in as strings, but then I'm having trouble separating out individual numbers, and getting it to treat them as integers.

like image 242
Sam Elliott Avatar asked Mar 05 '12 17:03

Sam Elliott


2 Answers

Try this:

#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);
    }
}
like image 86
Martin York Avatar answered Oct 23 '22 13:10

Martin York


Ok, the "exactly as they appear" requirement means that you need a ragged array, in case different number of columns appear in different rows. I would use std::vector< std::vector<long> >. Each contained vector corresponds to one row.

So, each time you read a row of text, create a new empty vector.

Call strtol repeatedly on the row you read, using push_back to collect them into the vector. When the output pointer is the same as the input pointer (this indicates failure, probably because you reached the end of the line), push_back the whole vector and start the next row.

Something like this:

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();
     */
}
like image 38
Ben Voigt Avatar answered Oct 23 '22 13:10

Ben Voigt