Java有一个方便的分割方法:
String str = "The quick brown fox";
String[] results = str.split(" ");
在c++中有简单的方法来做到这一点吗?
Java有一个方便的分割方法:
String str = "The quick brown fox";
String[] results = str.split(" ");
在c++中有简单的方法来做到这一点吗?
当前回答
这里有许多过于复杂的建议。试试这个简单的std::string解决方案:
using namespace std;
string someText = ...
string::size_type tokenOff = 0, sepOff = tokenOff;
while (sepOff != string::npos)
{
sepOff = someText.find(' ', sepOff);
string::size_type tokenLen = (sepOff == string::npos) ? sepOff : sepOff++ - tokenOff;
string token = someText.substr(tokenOff, tokenLen);
if (!token.empty())
/* do something with token */;
tokenOff = sepOff;
}
其他回答
你可以利用boost::make_find_iterator。类似于这个:
template<typename CH>
inline vector< basic_string<CH> > tokenize(
const basic_string<CH> &Input,
const basic_string<CH> &Delimiter,
bool remove_empty_token
) {
typedef typename basic_string<CH>::const_iterator string_iterator_t;
typedef boost::find_iterator< string_iterator_t > string_find_iterator_t;
vector< basic_string<CH> > Result;
string_iterator_t it = Input.begin();
string_iterator_t it_end = Input.end();
for(string_find_iterator_t i = boost::make_find_iterator(Input, boost::first_finder(Delimiter, boost::is_equal()));
i != string_find_iterator_t();
++i) {
if(remove_empty_token){
if(it != i->begin())
Result.push_back(basic_string<CH>(it,i->begin()));
}
else
Result.push_back(basic_string<CH>(it,i->begin()));
it = i->end();
}
if(it != it_end)
Result.push_back(basic_string<CH>(it,it_end));
return Result;
}
这是一个简单的循环,只对标准库文件进行标记
#include <iostream.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <conio.h>
class word
{
public:
char w[20];
word()
{
for(int j=0;j<=20;j++)
{w[j]='\0';
}
}
};
void main()
{
int i=1,n=0,j=0,k=0,m=1;
char input[100];
word ww[100];
gets(input);
n=strlen(input);
for(i=0;i<=m;i++)
{
if(context[i]!=' ')
{
ww[k].w[j]=context[i];
j++;
}
else
{
k++;
j=0;
m++;
}
}
}
pystring是一个小型库,实现了Python的一系列字符串函数,包括split方法:
#include <string>
#include <vector>
#include "pystring.h"
std::vector<std::string> chunks;
pystring::split("this string", chunks);
// also can specify a separator
pystring::split("this-string", chunks, "-");
c++标准库算法普遍基于迭代器,而不是具体的容器。不幸的是,这使得在c++标准库中很难提供类似java的split函数,尽管没有人认为这很方便。但是它的返回类型是什么呢?std::向量< std:: basic_string <…> >吗?也许吧,但这样我们就被迫执行(可能是冗余的和昂贵的)分配。
相反,c++提供了大量基于任意复杂的分隔符分割字符串的方法,但它们都没有像其他语言中那样封装得很好。各种各样的方法填满了整个博客文章。
在最简单的情况下,你可以使用std::string::find进行迭代,直到你击中std::string::npos,然后使用std::string::substr提取内容。
一个更流畅的(和惯用的,但基本的)版本在空格上拆分将使用std::istringstream:
auto iss = std::istringstream{"The quick brown fox"};
auto str = std::string{};
while (iss >> str) {
process(str);
}
使用std::istream_iterators,还可以使用vector的迭代器范围构造函数将string流的内容复制到vector中。
多个库(如Boost.Tokenizer)提供特定的标记器。
更高级的分裂需要正则表达式。c++特别为此提供了std::regex_token_iterator:
auto const str = "The quick brown fox"s;
auto const re = std::regex{R"(\s+)"};
auto const vec = std::vector<std::string>(
std::sregex_token_iterator{begin(str), end(str), re, -1},
std::sregex_token_iterator{}
);
使用strtok。在我看来,没有必要围绕标记化构建类,除非strtok不能提供您所需要的东西。可能不会,但在用C和c++编写各种解析代码的15年多时间里,我一直在使用strtok。这里有一个例子
char myString[] = "The quick brown fox";
char *p = strtok(myString, " ");
while (p) {
printf ("Token: %s\n", p);
p = strtok(NULL, " ");
}
一些注意事项(可能不适合您的需要)。该字符串在该过程中被“销毁”,这意味着EOS字符内联放置在分隔符点中。正确的用法可能需要创建字符串的非const版本。还可以在解析过程中更改分隔符列表。
在我看来,上面的代码比为它单独编写一个类要简单得多,也更容易使用。对我来说,这是语言提供的功能之一,而且它做得很好,很干净。这只是一个“基于C”的解决方案。它很合适,很简单,而且你不需要写很多额外的代码:-)