Stod() and fstream in a macro

This is my first question here so feedback on question style and customs is welcomed.

I am trying to write a macro that will read a .txt file with one column of numbers so I can play around with these data and make pretty graphs and the like, specifically histograms. I am having trouble with the code that reads the file. I am using what is essentially the ‘stock code’ for reading files. Ideally I would like it to read a text file called example.txt and push these values into a vector. This code works fine in plain C++ 11 but doesn’t work in ROOT.

#include <iostream>
#include <string>
#include <vector>
#include "Riostream.h"

using namespace std;

void testMacro(){

    vector<double> jets;

    string line;
    ifstream inputFile;
    inputFile.open("example.txt");

    while (getline(inputFile,line)){
        jets.push_back(stod(line));
    }
    inputFile.close();
 }

When I run it, I get:

terminate called after throwing an instance of 'std::invalid_argument’
what(): stod

It seems rather obvious that the issue is with the stod() but I can’t seem to fix it. I am using ROOT 6.08/6 on 64 bit ubuntu 16.04. The file example.txt is just a single column of random numbers.

[quote=“Liam_F, post:1, topic:25280”]
This code works fine in plain C++ 11 but doesn’t work in ROOT.
[/quote] For me, it looks like it is vice versa. Your code does not even compile in plain C++11 because there is no standard header called Riostream.h, you would need to include <fstream> instead. (Riostream.h is a ROOT header that just includes <fstream>, <iostream>, and <iomanip>). On the other hand, your code does work correctly in ROOT (at least using ROOT 6.11).

Can you try to add try…catch around the stod to check which line is causing the exception?

    while (getline(inputFile,line)){
        try {
            jets.push_back(stod(line));
        } catch (...) {
            cout << "Line <" << line << "> cannot be converted\n";
        }
    }

Also it is at least debatable if getline is “‘stock code’ for reading files” in C++. It usually leads to an extra copy that one can avoid when using operator>> instead.

Also, your code happily converts lines like “42.1 add some junk”.

When using ROOT, I would suggest something different instead:

auto t = new TTree("t", "t");
t->ReadFile("example.txt", "col/D");

I have seen people use TTree to solve similar problems as well. Is a TTree the correct way to go about this?

Is stod() broken in root 6.08?

Define “the correct way”. Does any correct way count? Does correct imply efficient? What do you need the array for? Do you need the whole array in memory at once? One cannot really answer this question without knowing what you want to do, how large the data is and …

Test stod: just start root and type stod("123.456")! It should look like this:

% root -l
root [0] stod("12345.678")
(double) 12345.678000
root [1] .q

My suspicion is that your input file is corrupt (maybe some empty line? Some non printable characters?). Before thinking about alternative solutions, find out which line stod cannot convert.

I would like to have the entire dataset at once. By correct I mean the way that would make people experienced in ROOT not cringe.

The stod() in ROOT in terminal worked but it doesn’t work in the macro. Here is my input file:
example.txt (24 Bytes)

I repeat my question for the third time: which line fails to convert?

Try a std::cout << "trying to convert <<" << line << ">>\n"; right in front of the stod line.

It seems to be working now. I did not change anything so maybe it was a glitch in root?

Hi, I would not be sure about that.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.