c++ - Reading formatted input from an istream -



c++ - Reading formatted input from an istream -

the problem below has been simplified real requirements.

consider next program:

#include <iostream> #include <iterator> #include <string> #include <set> #include <algorithm> using namespace std; typedef string t; // simplify, consider t string template<typename input_iterator> void do_something(const input_iterator& first, const input_iterator& last) { const ostream_iterator<t> os(cout, "\n"); const set<t> words(first, last); copy(words.begin(), words.end(), os); } int main(int argc, char** argv) { const istream_iterator<t> is(cin), eof; do_something(is, eof); homecoming 0; }

the programme extracts words istream (cin) , them. each word seperated white space default. logic behind formatted extraction within istream_iterator.

what need pass do_something() 2 iterators extracted words separated punctuation character instead of white space (white spaces considered "normal" characters). how in "clean c++ way" (that is, minimum effort)?

although isn't priori obvious there relatively simple way alter stream considers whitespace. way imbue() stream std::locale object std::ctype<char> facet replaced consider desired characters whitespace. imbue(), locale, ctype - huh?!? ok, well, these aren't things utilize day day here quick illustration set's std::cin utilize comma , newline characters spaced:

#include <locale> template <char s0, char s1> struct commactype_base { commactype_base(): table_() { this->table_[static_cast<unsigned char>(s0)] = std::ctype_base::space; this->table_[static_cast<unsigned char>(s1)] = std::ctype_base::space; } std::ctype<char>::mask table_[std::ctype<char>::table_size]; }; template <char s0, char s1 = s0> struct ctype: commactype_base<s0, s1>, std::ctype<char> { ctype(): std::ctype<char>(this->table_, false) {} };

actually, particular implementation of std::ctype<char> can used utilize 1 or 2 arbitrary chars spaces (a proper c++2011 version allow arbitrary number of arguments; also, don't have template argumentss). anyway, in place, drop next line @ origin of main() function , set:

std::cin.imbue(std::locale(std::locale(), new ::ctype<',', '\n'>));

note considers , , \n space characters. means no other characters skipped whitespace. ... and, of course, sequence of multiple comma characters considered 1 separator rather perchance creating bunch of empty strings. note above std::ctype<char> facet removes other character classification. if want parse other objects strings might want retain other character classification , alter spaces. here way done:

template <char s0, char s1> struct commactype_base { commactype_base(): table_() { std::transform(std::ctype<char>::classic_table(), std::ctype<char>::classic_table() + std::ctype<char>::table_size, this->table_, [](std::ctype_base::mask m) -> std::ctype_base::mask { homecoming m & ~(std::ctype_base::space); }); this->table_[static_cast<unsigned char>(s0)] |= std::ctype_base::space; this->table_[static_cast<unsigned char>(s1)] |= std::ctype_base::space; } std::ctype<char>::mask table_[std::ctype<char>::table_size]; };

sadly, crashes version of gcc have on scheme (apparently std::ctype<char>::classic_table() yields null pointer. compiling current version of clang doesn't work because clang doesn't back upwards lambda. 2 caveats above code should correct, though...

c++

Comments

Popular posts from this blog

How do I check if an insert was successful with MySQLdb in Python? -

delphi - blogger via idHTTP : error 400 bad request -

postgresql - ERROR: operator is not unique: unknown + unknown -