Reading data file in c++ code

Hello,
I need to read the data from a .dat file like the following one:

#Curve 0 of 1, 286 points
#x y type
13.9896 -0.0426566 i
13.9861 -0.0137144 i
13.9826 0.00222783 i
13.9792 0.0421701 i
13.9757 0.0271066 i
13.9722 0.0330488 i
and so on…

I need to jump the empty lines or the ones with “#” and put the values in X[], Y[].
I was able to open the file, count the data lines to know X and Y length then I did the following:

string line1;
i=0; double x1[dim]; double y1[dim];
while (!file1.eof())
{
getline(file1, line1);
if (line1.length() == 0 || line1[0] == ‘#’){continue;}
else{fscanf(file1, “%lf %lf\n”, &x1[i], &y1[i]);}
}
cout << x1 << ’ ’ << y1 << endl;

but the compiler says:
my_prog.C: In function ‘int main(int, char**)’:
my_prog.C:65: error: invalid conversion from ‘void*’ to ‘FILE*’
my_prog.C:65: error: initializing argument 1 of ‘int fscanf(FILE*, const char*, …)’

How can I do?
Besides, I am just compiling with: c++ my_prog.C -o my_prog.exe
Is there a better way?

Thank you very much!
Elena

Hello.

You can do something like this (a macro to be executed in CINT):

[code]#include
#include
#include

void read()
{
std::ifstream inputFile(“data.dat”);
std::string line;

while(getline(inputFile, line)) {
if (!line.length() || line[0] == ‘#’)
continue;
std::istringstream iss(line);
double x = 0., y = 0.;
iss>>x>>y;
std::cout<<"point: "<<x<<’ '<<y<<std::endl;
}
}
[/code]

Or, if you prefer scanf:

[code]#include
#include
#include

void read()
{
std::ifstream inputFile(“data.dat”);
std::string line;

while(getline(inputFile, line)) {
if (!line.length() || line[0] == ‘#’)
continue;
double x = 0., y = 0.;
sscanf(line.c_str(), “%lf %lf”, &x, &y);
std::cout<<"point: "<<x<<’ '<<y<<std::endl;
}
}
[/code]

And now with arrays:

[code]#include
#include
#include
#include

//int main()//uncomment if you prefer to compile as a standalone program.
void read()//comment if you prefer to compile as a standalone program.
{
std::ifstream inputFile(“data.dat”);
std::string line;
std::vector xs, ys;

while(getline(inputFile, line)) {
if (!line.length() || line[0] == ‘#’)
continue;
double x = 0., y = 0.;
sscanf(line.c_str(), “%lf %lf”, &x, &y);
xs.push_back(x);
ys.push_back(y);
}

std::cout<<“points read:\n”;
for (int i = 0; i < int(xs.size()); ++i)
std::cout<<“point[”<<i<<"]: ("<<xs[i]<<", “<<ys[i]<<”)\n";
}[/code]

If your file contains “invalid” lines (different from ‘#’, empty lines or ‘x y i’-format - you’ll have to add more code to handle them.

Since “<<” and “>>” operators really confuse me, my solution would be to use one of the “file as input” constructors from a ROOT class, e.g.:

http://root.cern.ch/root/html/TNtuple.html#TNtuple:TNtuple@2
http://root.cern.ch/root/html/TGraph.html#TGraph:TGraph@10

Then get the data back out if necessary with TGraph::GetX() or TNtuple::GetV1() after Draw(), etc. Obviously this is less efficient than writing your own parser, but parsing text in C++ is hard to get right (for me). If you don’t like using the ROOT classes for this, I would recommend looking up a CSV C++ library (e.g. https://github.com/psibi/csv-parser).

Some reformatting might be required before these classes accept the data (e.g. the “#” as a commented-line indicator), but that’s easily done in the shell beforehand with sed or awk, and probably only needs to be done once per input data file.

Jean-François