Usman Naseer
Usman Naseer

Reputation: 637

Read Numeric Data from a Text File in C++

For example, if data in an external text file is like this:

45.78   67.90   87
34.89   346     0.98

How can I read this text file and assign each number to a variable in c++? Using ifstream, I am able to open the text file and assign first number to a variable, but I don't know how to read the next number after the spaces.

#include <iostream>
#include <fstream>
using namespace std;

int main()
{
    float a;
    ifstream myfile;
    myfile.open("data.txt");
    myfile >> a;
    cout << a;
    myfile.close();
    system("pause");
    return 0;
}

#include <iostream>
#include <fstream>
using namespace std;
int main()
{
    int data[6], a, b, c, d, e, f;
    ifstream myfile;
    myfile.open("a.txt");

    for(int i = 0; i << 6; i++)
        myfile >> data[i];

    myfile.close();
    a = data[0];
    b = data[1];
    c = data[2];
    d = data[3];
    e = data[4];
    f = data[5];
    cout << a << "\t" << b << "\t" << c << "\t" << d << "\t" << e << "\t" << f << "\n";
    system("pause");
    return 0;
}

Upvotes: 63

Views: 443252

Answers (5)

Alan
Alan

Reputation: 1

You can use a 2D vector for storing the numbers that you read from the text file as shown below:

#include <iostream>
#include <vector>
#include <string>
#include <sstream>
#include<fstream>
int main() {
    std::string line;
    double word;

    
    std::ifstream inFile("data.txt");
    
    //create/use a std::vector
    std::vector<std::vector<double>> vec;
    
    if(inFile)
    {
        while(getline(inFile, line, '\n'))        
        {
            //create a temporary vector that will contain all the columns
            std::vector<double> tempVec;
            
            
            std::istringstream ss(line);
            
            //read word by word(or double by double) 
            while(ss >> word)
            {
                //std::cout<<"word:"<<word<<std::endl;
                //add the word to the temporary vector 
                tempVec.push_back(word);
            
            }      
            
            //now all the words from the current line has been added to the temporary vector 
            vec.emplace_back(tempVec);
        }    
    }
    
    else 
    {
        std::cout<<"file cannot be opened"<<std::endl;
    }
    
    inFile.close();
    
    //lets check out the elements of the 2D vector so the we can confirm if it contains all the right elements(rows and columns)
    for(std::vector<double> &newvec: vec)
    {
        for(const double &elem: newvec)
        {
            std::cout<<elem<<" ";
        }
        std::cout<<std::endl;
    }
    
    
    
    return 0;
}

The output of the above program can be seen here.

Upvotes: 0

Mike22LFC
Mike22LFC

Reputation: 997

you could read and write to a seperately like others. But if you want to write into the same one, you could try with this:

#include <iostream>
#include <fstream>

using namespace std;

int main() {

    double data[size of your data];

    std::ifstream input("file.txt");

    for (int i = 0; i < size of your data; i++) {
        input >> data[i];
        std::cout<< data[i]<<std::endl;
        }

}

Upvotes: 3

Jerry Coffin
Jerry Coffin

Reputation: 490623

It can depend, especially on whether your file will have the same number of items on each row or not. If it will, then you probably want a 2D matrix class of some sort, usually something like this:

class array2D { 
    std::vector<double> data;
    size_t columns;
public:
    array2D(size_t x, size_t y) : columns(x), data(x*y) {}

    double &operator(size_t x, size_t y) {
       return data[y*columns+x];
    }
};

Note that as it's written, this assumes you know the size you'll need up-front. That can be avoided, but the code gets a little larger and more complex.

In any case, to read the numbers and maintain the original structure, you'd typically read a line at a time into a string, then use a stringstream to read numbers from the line. This lets you store the data from each line into a separate row in your array.

If you don't know the size ahead of time or (especially) if different rows might not all contain the same number of numbers:

11 12 13
23 34 56 78

You might want to use a std::vector<std::vector<double> > instead. This does impose some overhead, but if different rows may have different sizes, it's an easy way to do the job.

std::vector<std::vector<double> > numbers;

std::string temp;

while (std::getline(infile, temp)) {
    std::istringstream buffer(temp);
    std::vector<double> line((std::istream_iterator<double>(buffer)),
                             std::istream_iterator<double>());

    numbers.push_back(line);
}

...or, with a modern (C++11) compiler, you can use brackets for line's initialization:

    std::vector<double> line{std::istream_iterator<double>(buffer),
                             std::istream_iterator<double>()};

Upvotes: 9

Spook
Spook

Reputation: 25919

Repeat >> reads in loop.

#include <iostream>
#include <fstream>
int main(int argc, char * argv[])
{
    std::fstream myfile("D:\\data.txt", std::ios_base::in);

    float a;
    while (myfile >> a)
    {
        printf("%f ", a);
    }

    getchar();

    return 0;
}

Result:

45.779999 67.900002 87.000000 34.889999 346.000000 0.980000

If you know exactly, how many elements there are in a file, you can chain >> operator:

int main(int argc, char * argv[])
{
    std::fstream myfile("D:\\data.txt", std::ios_base::in);

    float a, b, c, d, e, f;

    myfile >> a >> b >> c >> d >> e >> f;

    printf("%f\t%f\t%f\t%f\t%f\t%f\n", a, b, c, d, e, f);

    getchar();

    return 0;
}

Edit: In response to your comments in main question.

You have two options.

  • You can run previous code in a loop (or two loops) and throw away a defined number of values - for example, if you need the value at point (97, 60), you have to skip 5996 (= 60 * 100 + 96) values and use the last one. This will work if you're interested only in specified value.
  • You can load the data into an array - as Jerry Coffin sugested. He already gave you quite nice class, which will solve the problem. Alternatively, you can use simple array to store the data.

Edit: How to skip values in file

To choose the 1234th value, use the following code:

int skipped = 1233;
for (int i = 0; i < skipped; i++)
{
    float tmp;
    myfile >> tmp;
}
myfile >> value;

Upvotes: 93

Some programmer dude
Some programmer dude

Reputation: 409442

The input operator for number skips leading whitespace, so you can just read the number in a loop:

while (myfile >> a)
{
    // ...
}

Upvotes: 7

Related Questions