我有一些文字(有意义的文本或算术表达式)拆分将一个字符串的话,我想将它拆分成词。
如果我有一个分隔符,我会使用:由多个分隔符
std::stringstream stringStream(inputString);
std::string word;
while(std::getline(stringStream, word, delimiter))
{
wordVector.push_back(word);
}
我怎样才能打破串入令牌与几个分隔符?
我有一些文字(有意义的文本或算术表达式)拆分将一个字符串的话,我想将它拆分成词。
如果我有一个分隔符,我会使用:由多个分隔符
std::stringstream stringStream(inputString);
std::string word;
while(std::getline(stringStream, word, delimiter))
{
wordVector.push_back(word);
}
我怎样才能打破串入令牌与几个分隔符?
假设分隔符中的一个是换行,下面读取的行和由分隔符进一步拆分它。在这个例子中,我选择了分隔符空格,撇号和分号。
std::stringstream stringStream(inputString);
std::string line;
while(std::getline(stringStream, line))
{
std::size_t prev = 0, pos;
while ((pos = line.find_first_of(" ';", prev)) != std::string::npos)
{
if (pos > prev)
wordVector.push_back(line.substr(prev, pos-prev));
prev = pos+1;
}
if (prev < line.length())
wordVector.push_back(line.substr(prev, std::string::npos));
}
对于我来说太快了:p如果换行符不是分隔符,那么只需选择其中一个“常规”分隔符(并将其从内部循环中移除)即可使用。 –
如果你有提升,你可以使用:
#include <boost/algorithm/string.hpp>
std::string inputString("One!Two,Three:Four");
std::string delimiters("|,:");
std::vector<std::string> parts;
boost::split(parts, inputString, boost::is_any_of(delimiters));
如果您在如何做自己感兴趣和不使用升压。
假设分隔符字符串可能非常长 - 比如说M,检查字符串中的每个字符(如果它是分隔符),将花费O(M)每个字符,因此在循环中为原始中的所有字符字符串,假设长度为N,是O(M * N)。
我会使用一个字典(如地图 - “分隔符”为“布尔值” - 但在这里我会使用一个简单的布尔数组,在每个分隔符的index = ascii值中为true)。
现在迭代在串并检查一个字符是分隔符是O(1),最终给了我们O(N)的整体。
这里是我的示例代码:
const int dictSize = 256;
vector<string> tokenizeMyString(const string &s, const string &del)
{
static bool dict[dictSize] = { false};
vector<string> res;
for (int i = 0; i < del.size(); ++i) {
dict[del[i]] = true;
}
string token("");
for (auto &i : s) {
if (dict[i]) {
if (!token.empty()) {
res.push_back(token);
token.clear();
}
}
else {
token += i;
}
}
if (!token.empty()) {
res.push_back(token);
}
return res;
}
int main()
{
string delString = "MyDog:Odie, MyCat:Garfield MyNumber:1001001";
//the delimiters are " " (space) and "," (comma)
vector<string> res = tokenizeMyString(delString, " ,");
for (auto &i : res) {
cout << "token: " << i << endl;
}
return 0;
}
注:tokenizeMyString按值返回向量和第一栈上创建的,所以我们在这里使用的编译器>>> RVO的力量 - 返回值优化:)
我不知道为什么没有人指出,手工的方式,但在这里它是:
const std::string delims(";,:. \n\t");
inline bool isDelim(char c) {
for (int i = 0; i < delims.size(); ++i)
if (delims[i] == c)
return true;
return false;
}
和功能:
std::stringstream stringStream(inputString);
std::string word; char c;
while (stringStream) {
word.clear();
// Read word
while (!isDelim((c = stringStream.get())))
word.push_back(c);
if (c != EOF)
stringStream.unget();
wordVector.push_back(word);
// Read delims
while (isDelim((c = stringStream.get())));
if (c != EOF)
stringStream.unget();
}
这样你就可以做一些事情,如果你想在delims有用。
你可以移动std :: string字;和char c;在循环内部避免使用clear()...变量应尽可能地保持本地化和短暂性。 – Mohan
Boost.StringAlgorithm或Boost.Tokenizer会有所帮助。 –
或者一些想法,你可以从这个答案得到:http://stackoverflow.com/questions/4888879/elegant-ways-to-count-the-frequency-of-words-in-a-file – Nawaz
@ K-BALLO :根据这个问题,你不应该使用像Boost这样的外部库。 – deepmax