Here is what I'm trying to do:
say I have a stringstream. Then I << "\"hello world\" today";
then when I do
sstr >> myString1 >> myString2;
I would like myString1 to have "hello world" and for myString2 to have "today"
Is there a way, possibly with a manipulator, to achieve this?
Thanks
Short Answer: No
Long Answer:
There are no manipulates that will do that for you.
Alternative Answer:
You could write your own type that could be used in conjunction with the stream operators do do this task.
#include <string>
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
class QuotedWord
{
public:
operator std::string const& () const { return data;}
private:
std::string data;
friend std::ostream& operator<<(std::ostream& str, QuotedWord const& value);
{
return str << value.data;
}
friend std::istream& operator>>(std::istream& str, QuotedWord& value);
{
char x;
str >> x;
if ((str) && (x == '"'))
{
std::string extra;
std::getline(str, extra, '"');
value.data = std::string("\"").append(extra).append("\"");
}
else
{
str.putback(x);
str >> value.data;
}
return str;
}
};
Then it can be used normally.
int main()
{
QuotedWord word;
std::cin >> word;
std::cout << word << "\n";
// Easily convertible to string
std::string tmp = word;
std::cout << tmp << "\n"
// because it converts to a string easily it can be used where string is needed.
std::vector<std::string> data;
std::copy(std::istream_iterator<QuotedWord>(std::cin),
std::istream_iterator<QuotedWord>(),
// Notice we are using a vector of string here.
std::back_inserter(data)
);
}
> ./a.out
"This is" a test // Input
"This is" // Output
"This is"
No.
You either need to change the stream type (and hence the parsing semantics) or use your own string type (and hence change the parsing semantics in your overloaded op>>).
Instead, consider writing a function, similar to getline, which parses a possibly-quoted "word" out of a stream:
getqword(sstr, myString1);
getqword(sstr, myString2);
if (sstr) { /* both succeeded */ }
Note that input into a std::string already terminates at whitespace, so you only need to handle peeking ahead for a quote and then handle edge cases, of which there are plenty:
"\"hello world\"today"
Not directly, you need a "wrapper" class that terminates where you want it to.
struct QuotedStringReader
{
std::string& str;
QuotedStringReader( std::string& s ) : str( s ) {}
};
std::istream operator>>( std::istream&, const QuotedStringReader& qsr );
std::string s, s2;
stream >> QuotedStringReader( s ) << s2;
Note that this is a rare occasion where you stream into a const - because you can write to the internal str even though it is const, and this way I can pass in a temporary.
Actually as you probably don't know what you are about to read you could simply call it "TokenReader" which reads whatever you define as a "token".
Nope. Not that particular way. You could create a "strong typedef" for string though and design a new operator>> for it that behaves that way.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With