1

I want to learn how to read a text file (contain 3 columns 300000+ rows) and assign each column of the text file to different arrays in c++. I searched this on the internet but i could not find any suitable solution for this. I found a code to do this but the code read only 547 rows. The code is below.

#include <iostream>
#include <vector>
#include <fstream>
#include <string>
#include <iomanip>
using namespace std;


int main() {

    vector<double> vecX, vecY, vecZ;
    double x, y, z;

    ifstream inputFile("filetext.txt");

    while (inputFile >> x >> y >> z)
    {
        vecX.push_back(x);
        vecY.push_back(y);
        vecZ.push_back(z);
    }

    for(int i = 0; i < vecX.size(); i++) {
        cout << vecX[i] << ", " << vecY[i] << ", " << vecZ[i] << endl;
        cout << i << endl;
    }
}

A sample input text file data is below:

3.862015625000000e+03   5.611499505259664e-01   1.183793839633211e-02
3.862031250000000e+03   5.587474540972663e-01   1.186382272148924e-02
3.862046875000000e+03   7.376678568236076e-01   1.032568525995413e-02
3.862062500000000e+03   8.921759412061890e-01   9.389467084403112e-03
3.862078125000000e+03   8.003829513850249e-01   9.913663338280957e-03
.                       .                       .
.                       .                       .
.                       .                       .

I have one more question. The above code give an output such this: 3862.02, 0.56115, 0.0118379. But i want full digit as in the text file. How can i get.

Thanks in advance.

5
  • 3
    please show what rows #546..#548 look like Commented Jun 14, 2020 at 21:11
  • 3
    There must be something on the 548th row that fails to be parsed as a double value. You will have to inspect the contents of the file, to determine what it is. As far as formatting the output goes, do you know how to use std::setprecision? Commented Jun 14, 2020 at 21:12
  • You should first learn to search the internet. There are already a plethora of Comma Separated Value questions and answers. Search for "C++ read file CSV Comma Separated Value". Commented Jun 14, 2020 at 21:12
  • 2
    Rather than using parallel vectors, I recommend one vector of a struct. Create a struct that has x,y, and z values. Create a vector of these structures. This is generally more efficient than parallel vectors (the processor's cache can hold at least one of these structures, there is no guarantee that the processor's cache can hold all 3 arrays). The processor may have to reload it's cache in order to get values in the arrays. Commented Jun 14, 2020 at 21:16
  • Thank you for your quick reply. I checked the data. You are right, there is a "nan" value in third column (i am sorry). And i don't how to use std::setprecision beacuse i am new in c++, but i try to learn. I will consider your suggestions, thank you. Commented Jun 14, 2020 at 22:00

1 Answer 1

2

As mentioned in the comments, you probably have some garbage in the file and you are probably better off storing what you read in one vector.

To be able to find garbage more easily, you could throw an exception when reading fails.

Example:

#include <stdexcept>

// a class to store the values on one line in the file
struct cols_t {
    double cols[3];
};

// a function to read one cols_t from a stream
std::istream& operator>>(std::istream& is, cols_t& c) {
    return is >> c.cols[0] >> c.cols[1] >> c.cols[2];
}

// a function to read a stream until it's depleated, throwing an exception if it fails:
auto read_stream(std::istream& is) {   
    std::vector<cols_t> res;
    size_t no = 0;
    cols_t tmp;

    while(is >> tmp) {
        res.push_back(tmp);
        ++no;
    }

    if(not is.eof()) { // stream not depleated, something is wrong
        is.clear();    // clear error state
        std::string word;
        is >> word;    // and read whatever is in the stream

        // throw an exception showing where the problem is
        throw
            std::runtime_error(
                "could not read double on line " + std::to_string(no) +
                ", got \"" + word + "\"."
            );
    }

    return res;
}
int main() {
    std::ifstream inputFile("filetext.txt");
    try {
        auto vec = read_stream(inputFile);
    }
    catch(const std::exception& ex) {
        std::cerr << ex.what() << '\n';
    }
}

Setting the precision can be done using the ostreams precision() member function or using std::setprecision(). You also have a few other formatting options like std::fixed and std::scientific


If you want to be able to handle input containing -nan and nan (not a number) you can instead read the file word by word using a std::string and use std::strtod to convert the string to a double. strtod handles nans while formatted input (using >>) does not.

Example:

// a function to read one cols_t from a stream
std::istream& operator>>(std::istream& is, cols_t& c) {
    std::string word;
    char* end;
    for(auto& v : c.cols) {
        is >> word;
        v = std::strtod(word.c_str(), &end);     // convert word to double
        if(end == word.c_str()) {                // conversion to double failed
            is.setstate(std::istream::failbit);  // set the failbit on the stream
            break;                               // and break out of the loop
        }
    }
    return is;
}

// a function to read a stream until it's depleated, throwing an exception if it fails:
auto read_stream(std::istream& is) {   
    std::vector<cols_t> res;
    size_t no = 0;
    cols_t tmp;

    while(is >> tmp) {
        res.push_back(tmp);
        ++no;
    }

    if(not is.eof()) { // stream not depleated, something went wrong
        // throw an exception showing the line with the problem
        throw
            std::runtime_error(
                "could not read double on line " + std::to_string(no)
            );
    }

    return res;
}

Demo

Sign up to request clarification or add additional context in comments.

3 Comments

Thank you for the useful code. Is there a way pass the row causing the error and continue assigning the data to the array?
@user3927651 You're welcome! Yes, there are serveral options. I added an example how to be able to handle nans. I don't recommend silently ignoring errors and just continue reading though.
Your code solved all my problems. Thank you again for your help and useful comments in the code.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.