my goal is to read in a data file consisting of just one number per line and write the data into a histogram. There are some comments in the file behind #
characters. I want to skip these lines.
I have started writing:
TH1F *hist = new TH1F("hist","",4096, -0.5,4095.5);
//TF1 *fitfunc;
char filename[100];
double val;
int i;
char line[256];
sprintf(filename,"test.dat");
FILE* pfile = fopen(filename, "r");
for (i=0;i<=14;i++) {
fgets(line,256,pfile);
cout<<line<<endl;
fscanf(pfile, "%lf /n", &val);
hist->SetBinContent(i,val);
}
But only every other line gets written as "line" while the others are fscanfed.
Would be very nice, if someone could give me a hint.
...so this will obviously not work properly:
TH1F *hist = new TH1F("hist","",4096, -0.5,4095.5);
//TF1 *fitfunc;
char filename[100];
double val;
int i;
char zeile[256];
sprintf(filename,"test.dat");
FILE* pfile = fopen(filename, "r");
for (i=0;i<=14;i++)
{
fgets(zeile,256,pfile);
cout<<"fgets: "<<zeile<<endl;
if (zeile[0]!='#')
{
fscanf(pfile, "%lf /n", &val);
cout<<"val: "<<val<<endl;
hist->SetBinContent(i,val);
}
}
You need to use sscanf()
instead of fscanf()
after you've read the line with fgets()
:
TH1F *hist = new TH1F("hist", "", 4096, -0.5, 4095.5);
char filename[100];
char zeile[256];
sprintf(filename, "test.dat");
FILE *pfile = fopen(filename, "r");
if (pfile == 0)
…handle error; do not continue…
for (int i = 0; i < 14 && fgets(zeile, sizeof(zeile), pfile) != 0; i++)
{
cout << "fgets: " << zeile << endl;
if (zeile[0] != '#')
{
double val;
if (sscanf(zeile, "%lf", &val) == 1)
{
cout << "val: " << val << endl;
hist->SetBinContent(i, val);
}
// else … optionally report that line was erroneous
}
}
I left the sprintf()
for the file name in place, but it provides marginal value. I'd be tempted to use const char *filename = "test.dat";
so that the error message can report the file name that failed to open without repeating the string literal.
Converted into a standalone test program:
#include <cstdlib>
#include <iostream>
using namespace std;
int main()
{
char filename[100];
char zeile[256];
sprintf(filename, "test.dat");
FILE *pfile = fopen(filename, "r");
if (pfile != 0)
{
for (int i = 0; i < 14 && fgets(zeile, sizeof(zeile), pfile) != 0; i++)
{
cout << "fgets: " << zeile;
if (zeile[0] != '#')
{
double val;
if (sscanf(zeile, "%lf", &val) == 1)
cout << "val: " << val << endl;
}
}
fclose(pfile);
}
return 0;
}
and given a test data file test.dat
containing:
1.234
2.345
#3.456
#4.567
5.678
the output from the program shown is:
fgets: 1.234
val: 1.234
fgets: 2.345
val: 2.345
fgets: #3.456
fgets: #4.567
fgets: 5.678
val: 5.678
This generates the three expected val
lines and reads but ignores the two comment lines.