I know this is a quite easy problem but I just want to solve it for myself once and for all
I would simply like to split a string into an array using a character as
Take a look at boost::tokenizer
If you'd like to roll up your own method, you can use std::string::find() to determine the splitting points.
Another possibility is to imbue a stream with a locale that uses a special ctype
facet. A stream uses the ctype facet to determine what's "whitespace", which it treats as separators. With a ctype facet that classifies your separator character as whitespace, the reading can be pretty trivial. Here's one way to implement the facet:
struct field_reader: std::ctype<char> {
field_reader(): std::ctype<char>(get_table()) {}
static std::ctype_base::mask const* get_table() {
static std::vector<std::ctype_base::mask>
rc(table_size, std::ctype_base::mask());
// we'll assume dates are either a/b/c or a-b-c:
rc['/'] = std::ctype_base::space;
rc['-'] = std::ctype_base::space;
return &rc[0];
}
};
We use that by using imbue
to tell a stream to use a locale that includes it, then read the data from that stream:
std::istringstream in("07/3/2011");
in.imbue(std::locale(std::locale(), new field_reader);
With that in place, the splitting becomes almost trivial -- just initialize a vector using a couple of istream_iterator
s to read the pieces from the string (that's embedded in the istringstream
):
std::vector<std::string>((std::istream_iterator<std::string>(in),
std::istream_iterator<std::string>());
Obviously this tends toward overkill if you only use it in one place. If you use it much, however, it can go a long ways toward keeping the rest of the code quite clean.