我正在尝试迭代字符串的单词 .
可以假设该字符串由用空格分隔的单词组成 .
请注意,我对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);
}
有没有更优雅的方式来做到这一点?
30 回答
短而优雅
可以使用任何字符串作为分隔符,也可以与二进制数据一起使用(std :: string支持二进制数据,包括空值)
使用:
输出:
使用
std::stringstream
,因为你的工作非常好,并完全按照自己的意愿行事 . 如果你只是在寻找不同的做事方式,你可以使用std::find() / std::find_first_of()和std::string::substr() .这是一个例子:
我喜欢使用boost / regex方法执行此任务,因为它们为指定拆分条件提供了最大的灵活性 .
使用Boost的可能解决方案可能是:
这种方法可能比
stringstream
方法更快 . 由于这是一个通用模板函数,因此可以使用各种分隔符来分割其他类型的字符串(wchar等或UTF-8) .有关详细信息,请参阅documentation .
如果需要使用非空格符号解析字符串,则stringstream可能很方便:
这个答案接受字符串并将其放入字符串向量中 . 它使用boost库 .
我喜欢以下内容,因为它将结果放入向量中,支持字符串作为delim并控制保持空值 . 但是,它看起来并不那么好 .
当然,Boost有一个split(),其工作原理与此类似 . 并且,如果通过'white-space',你真的意味着任何类型的空白区域,使用Boost与
is_any_of()
的分割效果很好 .下面的代码使用
strtok()
将字符串拆分为标记并将标记存储在向量中 .那这个呢:
这是另一种做法..
又一种灵活而快速的方式
将它与字符串向量一起使用(编辑:因为某人指出不继承STL类... hrmf;)):
而已!这只是使用标记器的一种方法,比如如何计算单词:
受想象力限制;)
如果您想使用boost,但希望使用整个字符串作为分隔符(而不是像之前提出的大多数解决方案中那样使用单个字符),则可以使用
boost_split_iterator
.示例代码包括方便的模板:
这是一个仅使用标准正则表达式库的正则表达式解决方案 . (我有点生疏,所以可能会有一些语法错误,但这至少是一般的想法)
对于那些不能很好地牺牲代码大小的所有效率并将“高效”视为一种优雅的人来说,下面的内容应该是一个最佳点(我认为模板容器类是一个非常优雅的添加 . ):
我通常选择使用
std::vector<std::string>
类型作为我的第二个参数(ContainerT
)...但list<>
比不需要直接访问时更快list<>
,你甚至可以创建自己的字符串类并使用类似std::list<subString>
的地方subString
不做任何副本以获得惊人的速度提升 .它比本页面上最快的标记化速度快一倍以上,几乎是其他标记的5倍 . 此外,使用完美的参数类型,您可以消除所有字符串和列表副本,以提高速度 .
此外,它不会(非常低效)返回结果,而是将标记作为参考传递,因此如果您愿意,还可以使用多个调用来构建标记 .
最后,它允许您指定是否通过最后一个可选参数从结果中修剪空标记 .
它所需要的只是
std::string
......其余的都是可选的 . 它不使用流或boost库,但足够灵活,能够自然地接受这些外来类型中的一些 .对于它的 Value ,这是从输入字符串中提取标记的另一种方法,仅依赖于标准库设施 . 这是STL设计背后的力量和优雅的一个例子 .
可以使用相同的通用
copy
算法将它们插入到容器中,而不是将提取的标记复制到输出流 ....或直接创建
vector
:这是我最喜欢的迭代字符串的方法 . 你可以随心所欲地做任何事 .
这是另一种解决方案 . 它结构紧凑,效率高:
它可以很容易地进行处理,以处理字符串分隔符,宽字符串等 .
请注意,拆分
""
会产生一个空字符串,并且拆分","
(即sep)会产生两个空字符串 .它也可以轻松扩展为跳过空标记:
如果在跳过空的情况下将字符串拆分为多个分隔符需要令牌,可以使用此版本:
STL没有这样的方法 .
但是,您可以使用std::string::c_str()成员使用C的strtok()函数,也可以编写自己的函数 . 以下是我在快速Google搜索( "STL string split" )后找到的代码示例:
摘自:http://oopweb.com/CPP/Documents/CPPHOWTO/Volume/C++Programming-HOWTO-7.html
如果您对代码示例有疑问,请发表评论,我会解释 .
并且因为它没有实现
typedef
调用迭代器或重载<<
运算符并不意味着它是错误的代码 . 我经常使用C函数 . 例如,printf和scanf都比std::cin和std::cout(显着)快,fopen语法对二进制类型更友好,并且它们也倾向于生成更小的EXE .不要在这个 "Elegance over performance" 交易中被卖掉 .
这是一个只使用标准正则表达式库的简单解决方案
regex参数允许检查多个参数(空格,逗号等)
我通常只检查分隔空格和逗号,所以我也有这个默认函数:
"[\\s,]+"
检查空格(\\s
)和逗号(,
) .注意,如果要拆分
wstring
而不是string
,将所有
std::regex
更改为std::wregex
将所有
sregex_token_iterator
更改为wsregex_token_iterator
注意,您可能还希望通过引用获取字符串参数,具体取决于您的编译器 .
我有一个解决这个问题的2行解决方案:
然后,您可以将其放在矢量中,而不是打印 .
我这样做是因为我需要一种简单的方法来分割字符串和基于c的字符串......希望其他人也能发现它很有用 . 它也不依赖于令牌,你可以使用字段作为分隔符,这是我需要的另一个键 .
我相信可以进一步改善其优雅的改进,请务必做
StringSplitter.hpp:
StringSplitter.cpp:
例子:
将输出:
这个
是
一个
例
CString的
保留空条目(默认情况下将排除清空):
目标是使其类似于C#的Split()方法,其中拆分字符串就像:
我希望其他人能像我一样认为这很有用 .
我使用strtok自己滚动并使用boost来分割字符串 . 我找到的最好的方法是C++ String Toolkit Library . 它非常灵活和快速 .
该工具包比这个简单的示例具有更多的灵活性,但它在将字符串解析为有用元素方面的实用性令人难以置信 .
最近我不得不将一个带有骆驼字的单词分成子字 . 没有分隔符,只有上面的字符 .
例如,这将“AQueryTrades”拆分为“A”,“查询”和“交易” . 该函数适用于窄字符串和宽字符串 . 因为它尊重当前的地点,所以它将“RaumfahrtÜberwachungsVerordnung”分为“Raumfahrt”,“Überwachungs”和“Verordnung” .
注意
std::upper
应该作为函数模板参数传递 . 然后,这个函数的更一般化也可以分割为","
,";"
或" "
等分隔符 .我用它来分隔字符串 . 第一个将结果放在预先构造的向量中,第二个返回一个新向量 .
请注意,此解决方案不会跳过空标记,因此以下内容将找到4个项目,其中一个项目为空:
有一个名为strtok的函数 .
到目前为止,我使用了Boost中的那个,但我需要的东西不依赖于它,所以我来到这个:
一个好处是在
separators
中你可以传递多个角色 .这是一个拆分函数:
是通用的
使用标准C(无增强)
接受多个分隔符
忽略空标记(可以轻松更改)
用法示例:
这类似于Stack Overflow问题How do I tokenize a string in C++? .
得到Boost! : - )
这个例子给出了输出 -