The best way to do it would be using strtok. That link should be self explanatory on how to use it, and you can use multiple delimiters as well. Very handy C function.
views:
260answers:
7In C++, it's probably easiest to use a stsringstream
:
std::istringstream buffer("kas\nhjkfh kjsdjkasf");
std::vector<std::string> strings;
std::copy(std::istream_iterator<std::string>(buffer),
std::istream_iterator<std::string>(),
std::back_inserter(strings));
I haven't tried to stick to exactly the same signature, mostly because most of it is non-standard, so it doesn't apply to C++ in general.
Another possibility would be to use Boost::tokenizer
, though obviously that does involve another library, so I won't try to cover it in more detail.
I'm not sure if that qualifies as "bizarro syntax" or not. I may have to work a bit on that part...
Edit: I've got it -- initialize the vector instead:
std::istringstream buffer("kas\nhjkfh kjsdjkasf");
std::vector<std::string> strings(
(std::istream_iterator<std::string>(buffer)),
std::istream_iterator<std::string>());
The "bizarro" part is that without the extra parentheses around the first argument, this would invoke the "most vexing parse", so it would declare a function instead of defining a vector. :-)
Edit2: As far as the edit to the question goes, it seems nearly impossible to answer directly -- it depends on too many types (e.g., CGXStyle, CLVDateTime) that are neither standard nor explained. I, for one, can't follow it in any detail at all. Offhand, this looks like a fairly poor design, letting the user enter things that are more or less ambiguous, and then trying to sort out the mess. Better to use a control that only allows unambiguous input to start with, and you can just read some fields that contain a date and time directly.
Edit3: code to do the splitting that also treats commas as separators could be done like this:
#include <iostream>
#include <locale>
#include <algorithm>
#include <vector>
#include <sstream>
class my_ctype : public std::ctype<char> {
public:
mask const *get_table() {
// this copies the "classic" table used by <ctype.h>:
static std::vector<std::ctype<char>::mask>
table(classic_table(), classic_table()+table_size);
// Anything we want to separate tokens, we mark its spot in the table as 'space'.
table[','] = (mask)space;
// and return a pointer to the table:
return &table[0];
}
my_ctype(size_t refs=0) : std::ctype<char>(get_table(), false, refs) { }
};
int main() {
// put our data in a strea:
std::istringstream buffer("first kas\nhjkfh kjsdjk,asf\tlast");
// Create a ctype object and tell the stream to use it for parsing tokens:
my_ctype parser;
buffer.imbue(std::locale(std::locale(), &parser));
// separate the stream into tokens:
std::vector<std::string> strings(
(std::istream_iterator<std::string>(buffer)),
std::istream_iterator<std::string>());
// copy the tokes to cout so we can see what we got:
std::copy(strings.begin(), strings.end(),
std::ostream_iterator<std::string>(std::cout, "\n"));
return 0;
}
Parsing strings in C/C++ rarely turns out to be a simple matter. The method you posted looks like it has quite a bit of "history" involved in it. For example, you state that you want to split the string on white space. But the method itself appears to be using a member variable m_strDelim as part of the splitting decision. Simply replacing the method could lead to other unexpected issues.
Using an existing tokenizing class such as this Boost library could simplify things quite a bit.
Quite an over the top way of sorting this problem is to use the Qt libraries. If you're using KDE then they're installed already. The QString
class has a member function split which works like the python version. For example
QString("This is a string").split(" ", QString::SkipEmptyParts)
returns a QStringList
of QString
s:
["This", "is", "a", "string"]
(in pythonic syntax). Note the second argument is required or else should the words be split by multiple spaces, each individual one would be returned.
In general I find with the help of the Qt libraries, most of the simplicity of python, eg. simple string parsing and list iteration, can be handled with ease and with the power of C++.
The String Toolkit Library (Strtk) has the following solution to your problem:
#include <string>
#include <deque>
#include "strtk.hpp"
int main()
{
std::string data("kas\nhjkfh kjsdjkasf");
std::deque<std::string> str_list;
strtk::parse(data, ", \r\n", str_list);
return 0;
}
More examples can be found Here
You can use boost::algorithm::split
. I.e.:
std::string myString;
std::vector<std::string> splitStrings;
boost::algorithm::split(splitStrings, myString, boost::is_any_of(" \r\n"));