This is an improvement on Robᵩ's answer, because that is the right one (and I'm disappointed that it hasn't been accepted.)
What you need to do is change the array that ctype
looks at to decide what a delimiter is.
In the simplest case you could create your own:
const ctype<char>::mask foo[ctype<char>::table_size] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ctype_base::space};
On my machine '\n'
is 10. I've set that element of the array to the delimiter value: ctype_base::space
. A ctype
initialized with foo
would only delimit on '\n'
not ' '
or '\t'
.
Now this is a problem because the array passed into ctype
defines more than just what a delimiter is, it also defines leters, numbers, symbols, and some other junk needed for streaming. (Ben Voigt's answer touches on this.) So what we really want to do is modify a mask
, not create one from scratch.
That can be accomplished like this:
const auto temp = ctype<char>::classic_table();
vector<ctype<char>::mask> bar(temp, temp + ctype<char>::table_size);
bar[' '] ^= ctype_base::space;
bar['\t'] &= ~(ctype_base::space | ctype_base::cntrl);
bar[':'] |= ctype_base::space;
A ctype
initialized with bar
would delimit on '\n'
and ':'
but not ' '
or '\t'
.
You go about setting up cin
, or any other istream
, to use your custom ctype
like this:
cin.imbue(locale(cin.getloc(), new ctype<char>(data(bar))));
You can also switch between ctype
s and the behavior will change mid-stream:
cin.imbue(locale(cin.getloc(), new ctype<char>(foo)));
If you need to go back to default behavior, just do this:
cin.imbue(locale(cin.getloc(), new ctype<char>));
Live example
operator<<
withstd::cin
, did you mean>>
? – Coverlet