Search code examples
c++stringdoublereadfile

Reading line with mixed values in C++


I am trying to write a C++ code to read a text file, each line of the file contains double values, and string values, and there is not specific order for where the double values and the string values appears in the line. an example of how my line looks like:

Inf 1.8 1.4 Inf Inf 3.48. 

I am currently using this piece of code:

vector<double>temp;
string line;
ifstream travelFile(filepath);
while (getline(travelFile, line)) {
    string delimiter = " ";
    size_t pos = 0;
    string token; 
    while ((pos = line.find(delimiter)) != string::npos) {
        token = line.substr(0, pos);
        if ((token[0] == 'I') || (token[0] == 'i')) { temp.push_back(DBL_MAX); }
        else{ temp.push_back(stod(token)); };
        line.erase(0, pos + delimiter.length());
    }
    if (line.size() != 0){
        if ((line[0] == 'I') || (line[0] == 'i')) { temp.push_back(DBL_MAX); }
        else { temp.push_back(stod(line)); }
        travelTime.push_back(temp);
    }
    temp.clear();
}

However, it has few limitation that I don't like: first it doesn't accept any other delimiter other than the space and sometimes I have to deal with files with tab delimiter. Also it doesn't accept any string value except for "Inf", and some times the files can contain "inf" instead.


Solution

  • There is an easier way to split lines on whitespace: The same way you normally read formatted input from an input stream.

    Read the lines as you do now. But instead of using find and such to parse the string, use an std::istringstream for the line, and use the normal input operator >> to extract white-space separated "tokens" from the line.

    Something like

    while (std::getline(travelFile, line))
    {
        std::istringstream iss(line);
        std::string token;
        while (iss >> token)
        {
            // Do something with the extracted token
        }
    }
    

    To convert a string to a double, you can do the same as above, but attempt to read into a double value and check for success or failure. Or use e.g. std::stod to convert the string to a double with validation.