如何迭代由空格分隔的单词组成的字符串中的单词?
注意,我对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);
}
#include <iostream>
#include <string>
#include <deque>
std::deque<std::string> split(
const std::string& line,
std::string::value_type delimiter,
bool skipEmpty = false
) {
std::deque<std::string> parts{};
if (!skipEmpty && !line.empty() && delimiter == line.at(0)) {
parts.push_back({});
}
for (const std::string::value_type& c : line) {
if (
(
c == delimiter
&&
(skipEmpty ? (!parts.empty() && !parts.back().empty()) : true)
)
||
(c != delimiter && parts.empty())
) {
parts.push_back({});
}
if (c != delimiter) {
parts.back().push_back(c);
}
}
if (skipEmpty && !parts.empty() && parts.back().empty()) {
parts.pop_back();
}
return parts;
}
void test(const std::string& line) {
std::cout << line << std::endl;
std::cout << "skipEmpty=0 |";
for (const std::string& part : split(line, ':')) {
std::cout << part << '|';
}
std::cout << std::endl;
std::cout << "skipEmpty=1 |";
for (const std::string& part : split(line, ':', true)) {
std::cout << part << '|';
}
std::cout << std::endl;
std::cout << std::endl;
}
int main() {
test("foo:bar:::baz");
test("");
test("foo");
test(":");
test("::");
test(":foo");
test("::foo");
test(":foo:");
test(":foo::");
return 0;
}
输出:
foo:bar:::baz
skipEmpty=0 |foo|bar|||baz|
skipEmpty=1 |foo|bar|baz|
skipEmpty=0 |
skipEmpty=1 |
foo
skipEmpty=0 |foo|
skipEmpty=1 |foo|
:
skipEmpty=0 |||
skipEmpty=1 |
::
skipEmpty=0 ||||
skipEmpty=1 |
:foo
skipEmpty=0 ||foo|
skipEmpty=1 |foo|
::foo
skipEmpty=0 |||foo|
skipEmpty=1 |foo|
:foo:
skipEmpty=0 ||foo||
skipEmpty=1 |foo|
:foo::
skipEmpty=0 ||foo|||
skipEmpty=1 |foo|
我一直在寻找用任意长度的分隔符分割字符串的方法,所以我开始从头开始编写,因为现有的解决方案不适合我。
这是我的小算法,仅使用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类型实例化。
该算法所做的就是搜索分隔符,获取字符串中与分隔符相邻的部分,删除分隔符,然后再次搜索,直到不再找到为止。
当然,可以使用任意数量的空格作为分隔符。
我希望这有帮助。
STL还没有这样的方法。
但是,您可以通过使用std::string::C_str()成员来使用C的strtok()函数,也可以编写自己的函数。下面是我在快速谷歌搜索(“STL字符串分割”)后找到的代码示例:
void Tokenize(const string& str,
vector<string>& tokens,
const string& delimiters = " ")
{
// Skip delimiters at beginning.
string::size_type lastPos = str.find_first_not_of(delimiters, 0);
// Find first "non-delimiter".
string::size_type pos = str.find_first_of(delimiters, lastPos);
while (string::npos != pos || string::npos != lastPos)
{
// Found a token, add it to the vector.
tokens.push_back(str.substr(lastPos, pos - lastPos));
// Skip delimiters. Note the "not_of"
lastPos = str.find_first_not_of(delimiters, pos);
// Find next "non-delimiter"
pos = str.find_first_of(delimiters, lastPos);
}
}
摘自:http://oopweb.com/CPP/Documents/CPPHOWTO/Volume/C++编程-HOWTO-7.html
如果您对代码示例有疑问,请留下评论,我会解释。
仅仅因为它没有实现称为迭代器的typedef或重载<<运算符,并不意味着它是错误的代码。我经常使用C函数。例如,printf和scanf都比std::cin和std::cout快(很明显),fopen语法对二进制类型更友好,它们也倾向于生成更小的EXE。
不要被这种“优雅胜过性能”的交易所吸引。