c++sstream

Is there any easy way to read a line from a file, split the first text part into a string, then split the last number part into a float?


I have an issue that I haven't been able to find a good way to solve, mostly because I am relatively new to C++, but not new to programming. I have a file with several lines in it, one of them being:

Plain Egg 1.45

I need to be able to read that line and split the first part, "Plain Egg", into a string, and then the last part, 1.45, into a float, and then do that for the rest of the lines. The following is some code I have so far, but I have been having an issue where it refuses to even read the file for some reason:

string line;
ifstream menuFile("menu.txt");
if (menuFile.is_open())
{
    int i = 0;
    while (getline(menuFile, line));
    {
        cout << line << endl;

        istringstream iss(line);

        iss >> dataList[i].menuItem >> dataList[i].menuPrice;
        /*iss >> dataList[i].menuPrice;*/
        i++;
    }

}
else
{
    cout << "Unable to open file.";
}

When I run it, it doesn't spit out "Unable to open file.", and when I trace it, it does enter the if loop, but it just doesn't read it. Besides that problem though, I want to know if this code would work in the way I want it to, and if doesn't, how to solve this problem.

EDIT: When I run it, it outputs what the last line of the file said, that being "Tea 0.75". The full file is as follows:

Plain Egg 1.45
Bacon and Egg 2.45
Muffin 0.99
French Toast 1.99
Fruit Basket 2.49
Cereal 0.69
Coffee 0.50 
Tea 0.75

EDIT 2: For some reason, the following code goes straight to the last line, Tea 0.75, and I have no idea why, shouldn't the getline just go line by line until the last line(?):

string line;
int index;
ifstream menuFile("menu.txt");
if (menuFile.is_open())
{
    while (getline(menuFile, line));
    {
        cout << line << endl;
        index = line.find_last_of(' ');
        cout << index << endl;
    }

}

EDIT 3: Above code has a semicolon at the end of the while loop, no wonder it was just ending on the last line, ughhh.


Solution

  • [Demo]

    #include <iostream>  // cout
    #include <string>  // find_last_of, getline, stod
    
    int main()
    {
        std::string line{};
        while (std::getline(std::cin, line))
        {
            auto pos{line.find_last_of(' ')};
            auto text{line.substr(0, pos)};
            auto number{std::stod(line.substr(pos))};
            std::cout << "text = " << text << ", number = " << number << "\n";
        }
    }
    
    // Outputs
    //
    //   text = Plain Egg, number = 1.45
    //   text = Bacon and Egg, number = 2.45
    //   text = Muffin, number = 0.99
    //   text = French Toast, number = 1.99
    //   text = Fruit Basket, number = 2.49
    //   text = Cereal, number = 0.69
    //   text = Coffee, number = 0.5
    //   text = Tea, number = 0.75
    //   
    

    A more robust solution taking into account @DĂșthomhas' comments:

    This solution detects:

    [Demo]

    #include <boost/algorithm/string.hpp>
    #include <fmt/core.h>
    #include <iostream>  // cout
    #include <string>  // find_last_of, getline, stod
    
    int main()
    {
        std::string line{};
        while (std::getline(std::cin, line))
        {
            try
            {
                boost::trim_right(line);
                auto pos{line.find_last_of(' ')};
                auto text{line.substr(0, pos)};
                auto number{std::stod(line.substr(pos))};
                std::cout << "text = " << text << ", number = " << number << "\n";
            }
            catch (const std::exception&)
            {
                std::cout << fmt::format("* Error: invalid line '{}'\n", line);
            }
        }
    }
    
    // Outputs:
    //
    //   text = Plain Egg, number = 1.45
    //   text = Bacon and Egg, number = 2.45
    //   text = Muffin, number = 0.99
    //   text = French Toast, number = 1.99
    //   * Error: invalid line ''
    //   * Error: invalid line 'Fruit Basket'
    //   * Error: invalid line '0.75'
    //   * Error: invalid line 'Coffee blah'