Load A Matrix from An ASCII Format File (C++ and Python)

It is common for an scientific program to load an ASCII format matrix file, i.e. an ASCII text file consisting of lines of float numbers separated by whitespaces. In this post, I am gonna show my code (C++ and Python) to load a matrix from an ASCII file.

C++

The following C++ function is to load a matrix from an ASCII file into a vector< vector > object, some kind of “C++ style” 2D array.

The code is also available on GitHub Gist.

Python

The Python code loads the matrix into a numpy.matrix object.

The code is also available on GitHub Gist.

If you want to get a nested list instead of such a numpy.matrix object, you can use the following lines to convert the object to a nested list:

  • Borja Ribes Blanquer

    Hello Hong!

    I’m a beginner in C++ programming and I need to load a txt file (containing a huge matrix of floating numbers) into c++. I have copied and pasted your code in a Visual studio 2010 new project. It compiles correctly but when I run it gives me an error.fatal error LNK1561: entry point must be defined. I assume this error is because I need to set a main() function and call the function load_matrix. However, I dont know how to call it because for the function declaration you have included 3 arguments.
    void load_matrix(std::istream* is,
    std::vector< std::vector >* matrix,
    const std::string& delim = ” t”)

    I don’t understand what this arguments are used for.

    In which line of your code can I write the directory where my txt file is located?

    Thank you

  • kammo

    Hi,

    I’ve tested the C++ code, and I noticed that the last number in the line is not added to the row vector. I am assuming that there is no delimiter before the EOL character. The reason for which the last number is not pushed back is that when EOL is reached the push_back instruction at line 40 is skipped. I have fixed this problem by conditioning the “continue” at line 30 in the following way:

    […]
    if (delim.find(*i) == string::npos)
    {
    strnum += *i;
    if(i+1 != line.end())
    continue;
    }
    […]

    Correct me if I’m wrong. 🙂

    • You are right that the last number is not read. Probably it’s more elegant to append a delimiter to the end of line in the code before iteration rather than mess up the loop 🙂

    • OK, I adopted your method and updated the code, since your method can also handle empty delim string.

      • kammo

        Great, I’m glad it helped. Thank you again for sharing the code!

  • grapeot

    Just curious about why you use pointers (istream *) rather than references (istream &) for the input stream in the C++ code… Is that some specific reason or it’s just personal preference? Thanks!

    • Just my personal preference. I think passing a variable reference that is going to be changed inside the function body is counter-intuitive. Thus, whenever I see I need to pass in a pointer, I’ll be aware that this variable is going to be changed somehow.

      • grapeot

        Yeah that makes sense. Thanks for your explanation. I also notice you put const before general references, possibly just to save the time of a copy constructor, which is consistent with your “pointer indicating changes” habit. 🙂