如何迭代由空格分隔的单词组成的字符串中的单词?
注意,我对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);
}
如果您喜欢使用boost,但希望使用整个字符串作为分隔符(而不是之前提出的大多数解决方案中的单个字符),可以使用boost_split_iterator。
示例代码包括方便的模板:
#include <iostream>
#include <vector>
#include <boost/algorithm/string.hpp>
template<typename _OutputIterator>
inline void split(
const std::string& str,
const std::string& delim,
_OutputIterator result)
{
using namespace boost::algorithm;
typedef split_iterator<std::string::const_iterator> It;
for(It iter=make_split_iterator(str, first_finder(delim, is_equal()));
iter!=It();
++iter)
{
*(result++) = boost::copy_range<std::string>(*iter);
}
}
int main(int argc, char* argv[])
{
using namespace std;
vector<string> splitted;
split("HelloFOOworldFOO!", "FOO", back_inserter(splitted));
// or directly to console, for example
split("HelloFOOworldFOO!", "FOO", ostream_iterator<string>(cout, "\n"));
return 0;
}
我的实施可以是另一种解决方案:
std::vector<std::wstring> SplitString(const std::wstring & String, const std::wstring & Seperator)
{
std::vector<std::wstring> Lines;
size_t stSearchPos = 0;
size_t stFoundPos;
while (stSearchPos < String.size() - 1)
{
stFoundPos = String.find(Seperator, stSearchPos);
stFoundPos = (stFoundPos == std::string::npos) ? String.size() : stFoundPos;
Lines.push_back(String.substr(stSearchPos, stFoundPos - stSearchPos));
stSearchPos = stFoundPos + Seperator.size();
}
return Lines;
}
测试代码:
std::wstring MyString(L"Part 1SEPsecond partSEPlast partSEPend");
std::vector<std::wstring> Parts = IniFile::SplitString(MyString, L"SEP");
std::wcout << L"The string: " << MyString << std::endl;
for (std::vector<std::wstring>::const_iterator it=Parts.begin(); it<Parts.end(); ++it)
{
std::wcout << *it << L"<---" << std::endl;
}
std::wcout << std::endl;
MyString = L"this,time,a,comma separated,string";
std::wcout << L"The string: " << MyString << std::endl;
Parts = IniFile::SplitString(MyString, L",");
for (std::vector<std::wstring>::const_iterator it=Parts.begin(); it<Parts.end(); ++it)
{
std::wcout << *it << L"<---" << std::endl;
}
测试代码的输出:
The string: Part 1SEPsecond partSEPlast partSEPend
Part 1<---
second part<---
last part<---
end<---
The string: this,time,a,comma separated,string
this<---
time<---
a<---
comma separated<---
string<---
我一直在寻找用任意长度的分隔符分割字符串的方法,所以我开始从头开始编写,因为现有的解决方案不适合我。
这是我的小算法,仅使用STL:
//use like this
//std::vector<std::wstring> vec = Split<std::wstring> (L"Hello##world##!", L"##");
template <typename valueType>
static std::vector <valueType> Split (valueType text, const valueType& delimiter)
{
std::vector <valueType> tokens;
size_t pos = 0;
valueType token;
while ((pos = text.find(delimiter)) != valueType::npos)
{
token = text.substr(0, pos);
tokens.push_back (token);
text.erase(0, pos + delimiter.length());
}
tokens.push_back (text);
return tokens;
}
根据我的测试,它可以与任何长度和形式的分隔符一起使用。使用string或wstring类型实例化。
该算法所做的就是搜索分隔符,获取字符串中与分隔符相邻的部分,删除分隔符,然后再次搜索,直到不再找到为止。
当然,可以使用任意数量的空格作为分隔符。
我希望这有帮助。
这是我的版本获取了Kev的来源:
#include <string>
#include <vector>
void split(vector<string> &result, string str, char delim ) {
string tmp;
string::iterator i;
result.clear();
for(i = str.begin(); i <= str.end(); ++i) {
if((const char)*i != delim && i != str.end()) {
tmp += *i;
} else {
result.push_back(tmp);
tmp = "";
}
}
}
之后,调用函数并执行以下操作:
vector<string> hosts;
split(hosts, "192.168.1.2,192.168.1.3", ',');
for( size_t i = 0; i < hosts.size(); i++){
cout << "Connecting host : " << hosts.at(i) << "..." << endl;
}
这是我的版本
#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中,这段代码应该很快。