如何迭代由空格分隔的单词组成的字符串中的单词?
注意,我对C字符串函数或那种字符操作/访问不感兴趣。比起效率,我更喜欢优雅。我当前的解决方案:
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
int main() {
string s = "Somewhere down the road";
istringstream iss(s);
do {
string subs;
iss >> subs;
cout << "Substring: " << subs << endl;
} while (iss);
}
根据Galik的回答,我做了这个。这大部分都在这里,所以我不必一遍又一遍地写。C++仍然没有原生拆分函数,这真是太疯狂了。特征:
应该很快。容易理解(我认为)。合并空节。使用多个分隔符(例如“\r\n”)很简单
#include <string>
#include <vector>
#include <algorithm>
std::vector<std::string> split(const std::string& s, const std::string& delims)
{
using namespace std;
vector<string> v;
// Start of an element.
size_t elemStart = 0;
// We start searching from the end of the previous element, which
// initially is the start of the string.
size_t elemEnd = 0;
// Find the first non-delim, i.e. the start of an element, after the end of the previous element.
while((elemStart = s.find_first_not_of(delims, elemEnd)) != string::npos)
{
// Find the first delem, i.e. the end of the element (or if this fails it is the end of the string).
elemEnd = s.find_first_of(delims, elemStart);
// Add it.
v.emplace_back(s, elemStart, elemEnd == string::npos ? string::npos : elemEnd - elemStart);
}
// When there are no more non-spaces, we are done.
return v;
}
这是我的版本
#include <vector>
inline std::vector<std::string> Split(const std::string &str, const std::string &delim = " ")
{
std::vector<std::string> tokens;
if (str.size() > 0)
{
if (delim.size() > 0)
{
std::string::size_type currPos = 0, prevPos = 0;
while ((currPos = str.find(delim, prevPos)) != std::string::npos)
{
std::string item = str.substr(prevPos, currPos - prevPos);
if (item.size() > 0)
{
tokens.push_back(item);
}
prevPos = currPos + 1;
}
tokens.push_back(str.substr(prevPos));
}
else
{
tokens.push_back(str);
}
}
return tokens;
}
它适用于多字符分隔符。它防止空令牌进入结果。它使用单个标头。当您不提供分隔符时,它将字符串作为一个标记返回。如果字符串为空,它还会返回一个空结果。不幸的是,它的效率很低,因为存在巨大的std::vector副本,除非您使用C++11进行编译,否则应该使用移动示意图。在C++11中,这段代码应该很快。
最近我不得不将一个骆驼大小写的单词拆分成子单词。没有分隔符,只有大写字符。
#include <string>
#include <list>
#include <locale> // std::isupper
template<class String>
const std::list<String> split_camel_case_string(const String &s)
{
std::list<String> R;
String w;
for (String::const_iterator i = s.begin(); i < s.end(); ++i) { {
if (std::isupper(*i)) {
if (w.length()) {
R.push_back(w);
w.clear();
}
}
w += *i;
}
if (w.length())
R.push_back(w);
return R;
}
例如,这将“AQueryTrades”拆分为“A”、“Query”和“Trades”。该函数适用于窄字符串和宽字符串。因为它尊重当前的语言环境,所以将“RaumfahrtÜberwachungsVerordnung”分为“Raumfahrt”、“Überwachungs”和“Verordnug”。
注意std::upper应该真正作为函数模板参数传递。然后,此函数的更广义的from也可以在分隔符(如“、”、“;”或“”)处拆分。
我用这个分隔符分隔字符串。第一个将结果放入预先构建的向量中,第二个返回新向量。
#include <string>
#include <sstream>
#include <vector>
#include <iterator>
template <typename Out>
void split(const std::string &s, char delim, Out result) {
std::istringstream iss(s);
std::string item;
while (std::getline(iss, item, delim)) {
*result++ = item;
}
}
std::vector<std::string> split(const std::string &s, char delim) {
std::vector<std::string> elems;
split(s, delim, std::back_inserter(elems));
return elems;
}
请注意,此解决方案不会跳过空令牌,因此下面将找到4项,其中一项为空:
std::vector<std::string> x = split("one:two::three", ':');
我刚刚写了一个很好的例子,说明如何按符号拆分一个字符,然后将每个字符数组(由符号分隔的单词)放入一个向量中。为了简单起见,我创建了std字符串的向量类型。
我希望这对你有帮助,并且对你可读。
#include <vector>
#include <string>
#include <iostream>
void push(std::vector<std::string> &WORDS, std::string &TMP){
WORDS.push_back(TMP);
TMP = "";
}
std::vector<std::string> mySplit(char STRING[]){
std::vector<std::string> words;
std::string s;
for(unsigned short i = 0; i < strlen(STRING); i++){
if(STRING[i] != ' '){
s += STRING[i];
}else{
push(words, s);
}
}
push(words, s);//Used to get last split
return words;
}
int main(){
char string[] = "My awesome string.";
std::cout << mySplit(string)[2];
std::cin.get();
return 0;
}