c++istream

Is there a unget() method for putting back everything extracted by std::getline back into an istream?


I am extracting each full row of a csv file using std::getline:

for (std::string row; std::getline(is, row); )  // reads entire row in csv file
{
    if (std::ranges::count(row, ',') != Temp_reading::read_parameters - 1) // checks if row has right amount of columns
    {
        std::cerr << "Row: " << row << " contains too many columns in csv file" << "\n";
        is.unget(); // Want this to put entire row back into istream
        is.clear(std::ios_base::failbit);
        return;
     } 
     // does other stuff if the row has right amount of columns
 }

In this case is.unget() will only put back the last character in the istream. Is there a way to make is.unget() put back the entire row? Or is there another simple way to achieve the same?


Solution

  • unget only makes the most recently extracted single character available. You can use seekg to rewind by the size of the extracted string

    #include <string>
    #include <sstream>
    #include <iostream>
    
    int main() {
        std::istringstream input{"hello\nworld"};
        std::string word;
        std::getline(input,word);
        std::cout << word <<"\n";
        input.seekg(-word.size());
        std::getline(input,word);
        std::cout << word <<"\n";
    }
    

    Live Demo


    However, I have doubts whether this is the right approach for your use case. From the CSV file the row needs to be extracted anyhow. Instead of rewinding the input stream just to extract the same line again you should consider to use the already extracted string.