Read Numeric Data from a Text File in C++

C++

C++ Problem Overview


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;
}

C++ Solutions


Solution 1 - C++

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;

Solution 2 - C++

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>()};

Solution 3 - C++

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

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

Solution 4 - C++

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;
        }

}

Solution 5 - C++

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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionUsman NaseerView Question on Stackoverflow
Solution 1 - C++SpookView Answer on Stackoverflow
Solution 2 - C++Jerry CoffinView Answer on Stackoverflow
Solution 3 - C++Some programmer dudeView Answer on Stackoverflow
Solution 4 - C++Mike22LFCView Answer on Stackoverflow
Solution 5 - C++Anoop RanaView Answer on Stackoverflow