Search code examples
c++vectorfilestreamstringstream

Problem with converting vector of string to vector of doubles


I am trying to write a program that reads some numerical values from a .csv file, stores them in a std::vector<std::string>, and then converts these values into doubles and stores them in a std::vector<double>.

I am trying to do the conversion using stringstreams, which has worked fine for me in the past.

I have managed to import the numerical values and store them in the std::vector<std::string>, however I am getting a weird problem when trying to do the conversions to double. Only the very first value is stored in the std::vector<double> with a lot of significant figures missing, and the other entries are just ignored and not stored in the std::vector<double> at all.

Here is my code so far:

#include <string>
#include <fstream>
#include <iostream>
#include <sstream> 
#include <vector>

double extract_double(std::string str) 
{ 
    std::stringstream ss;
    double grade;
    //Pass all the course details to string stream
    ss << str; 
    //Extract the double type part of the string stream which is the course grade
    ss >> grade;
    str = "";
    ss.ignore();
    return grade;
}

int main()
{
    std::ifstream my_input_file;
    std::string file_name;
    my_input_file.open("scale_free_gamma_2_fitnesses.csv");
    int number_of_data_in_file;
    std::vector<std::string> fitnesses_string;
    std::vector<double> fitnesses;
    std::string string_temp;
    while (my_input_file.good()) {
        //Extract strings from file
        std::getline(my_input_file, string_temp, ',');
        fitnesses_string.push_back(string_temp);     
    }
    
    for (auto fitnesses_it = fitnesses_string.begin(); 
      fitnesses_it < fitnesses_string.end(); ++fitnesses_it){
        fitnesses.push_back(extract_double(*fitnesses_it));
    }

    for (auto fitnesses_itt = fitnesses.begin(); 
      fitnesses_itt < fitnesses.end(); ++fitnesses_itt){
        std::cout << *fitnesses_itt << std::endl;
    }
    return 0;
}

Solution

  • You should be reading individual lines from the file first, and then splitting up each line on commas.

    And there are easier ways to handle the rest of your code, too.

    Try something more like this instead:

    #include <string>
    #include <fstream>
    #include <iostream>
    #include <sstream> 
    #include <vector>
    
    int main()
    {
        std::ifstream my_input_file("scale_free_gamma_2_fitnesses.csv");
        std::vector<std::string> fitnesses_string;
        std::vector<double> fitnesses;
        std::string line, string_temp;
    
        while (std::getline(my_input_file, line)) {
            //Extract strings from line
            std:::istringstream iss(line);
            while (std::getline(iss, string_temp, ','))
                fitnesses_string.push_back(string_temp);
        }
        
        for (const auto &s : fitnesses_string){
            fitnesses.push_back(std:stod(s));
        }
    
        for (auto value : fitnesses){
            std::cout << value << std::endl;
        }
    
        return 0;
    }
    

    In which case, even simpler would be to just get rid of the std::vector<std::string> altogether:

    #include <string>
    #include <fstream>
    #include <iostream>
    #include <sstream> 
    #include <vector>
    
    int main()
    {
        std::ifstream my_input_file("scale_free_gamma_2_fitnesses.csv");
        std::vector<double> fitnesses;
        std::string line, string_temp;
    
        while (std::getline(my_input_file, line)) {
            //Extract strings from line
            std:::istringstream iss(line);
            while (std::getline(iss, string_temp, ','))
                fitnesses.push_back(std:stod(string_temp));
        }
        
        for (auto value : fitnesses){
            std::cout << value << std::endl;
        }
    
        return 0;
    }