c++parametersistringstream

Is it possible to use istringstream to read in more than one parameter of a stream function?


Instead of writing a new istringstream argument, can I add another parameter inside nameStream? I have what I think below, and if this method is elligible, then can I tell the input stream to read in a space or endline to separate the two fullnames?

#include <iostream>
#include <string>

using namespace std;

string lastNameFirst (string fullname){
    fullname = "Don Blaheta";
    fullname2 = "Julian Dymacek";
    istringstream nameStream(fullname, fullname2);

    string firstName;
    string lastName;
    string firstName2;
    string lastName2;
    nameStream>>firstName>>lastName>>firstName2>>lastName2;

    return 0;
}

Solution

  • No, that will not work.

    As you can see in the definition of std::istringstreams constructor, it will not take 2 std::strings as parameter. So, you cannot do in this way.

    You have to concatenate the 2 strings before and then handover to the constructor.

    Please see below some example for illustrating what I was explaining:

    #include <iostream>
    #include <string>
    #include <sstream>
    using namespace std::string_literals;
    
    int main() {
        // Define source strings
        std::string fullname1{ "Don Blaheta"s };
        std::string fullname2{ "Julian Dymacek"s };
    
        // here we will store the result
        std::string firstName1{}, lastName1{}, firstName2{}, lastName2{};
    
        // Create stream from concatenated strings
        std::istringstream nameStream(fullname1 + " "s + fullname2);
    
        // Extract the name parts
        nameStream >> firstName1 >> lastName1 >> firstName2 >> lastName2;
    
        // Show some debug output
        std::cout << firstName1 << ' ' << lastName1 << '\n' << firstName2 << ' ' << lastName2 << ' ';
    }
    

    In more advanced C++ (starting with C++17) you could use variadic template parameters and fold expresssions to concatenate an arbitary number of names, and then split the parts into a std::vector. Here we can make use of the std::vectors range constructor(5) in combination with the std::istream_iterators constructor.

    But here you need to learn more . . .

    #include <iostream>
    #include <string>
    #include <sstream>
    #include <vector>
    #include <iterator>
    #include <algorithm>
    using namespace std::string_literals;
    
    template<typename... Strings>
    std::vector<std::string> split(Strings&& ...strings) {
        std::istringstream iss(((strings + " "s) + ...));
        return { std::istream_iterator<std::string>(iss),{} };
    }
    
    int main() {
        // Any number of names
        std::string fullname1{ "Don Blaheta"s };
        std::string fullname2{ "Julian Dymacek"s };
        std::string fullname3{ "John Doe"s };
    
        // Split all the names into parts
        std::vector nameParts = split(fullname1, fullname2, fullname3);
    
        // Show debug output
        for (const std::string& s : nameParts) std::cout << s << '\n';
    }