Java有一个方便的分割方法:
String str = "The quick brown fox";
String[] results = str.split(" ");
在c++中有简单的方法来做到这一点吗?
Java有一个方便的分割方法:
String str = "The quick brown fox";
String[] results = str.split(" ");
在c++中有简单的方法来做到这一点吗?
当前回答
下面是一种方法,允许您控制是否包含空标记(如strsep)或排除空标记(如strtok)。
#include <string.h> // for strchr and strlen
/*
* want_empty_tokens==true : include empty tokens, like strsep()
* want_empty_tokens==false : exclude empty tokens, like strtok()
*/
std::vector<std::string> tokenize(const char* src,
char delim,
bool want_empty_tokens)
{
std::vector<std::string> tokens;
if (src and *src != '\0') // defensive
while( true ) {
const char* d = strchr(src, delim);
size_t len = (d)? d-src : strlen(src);
if (len or want_empty_tokens)
tokens.push_back( std::string(src, len) ); // capture token
if (d) src += len+1; else break;
}
return tokens;
}
其他回答
Boost标记器类可以使这类事情变得非常简单:
#include <iostream>
#include <string>
#include <boost/foreach.hpp>
#include <boost/tokenizer.hpp>
using namespace std;
using namespace boost;
int main(int, char**)
{
string text = "token, test string";
char_separator<char> sep(", ");
tokenizer< char_separator<char> > tokens(text, sep);
BOOST_FOREACH (const string& t, tokens) {
cout << t << "." << endl;
}
}
针对c++ 11更新:
#include <iostream>
#include <string>
#include <boost/tokenizer.hpp>
using namespace std;
using namespace boost;
int main(int, char**)
{
string text = "token, test string";
char_separator<char> sep(", ");
tokenizer<char_separator<char>> tokens(text, sep);
for (const auto& t : tokens) {
cout << t << "." << endl;
}
}
下面是一种方法,允许您控制是否包含空标记(如strsep)或排除空标记(如strtok)。
#include <string.h> // for strchr and strlen
/*
* want_empty_tokens==true : include empty tokens, like strsep()
* want_empty_tokens==false : exclude empty tokens, like strtok()
*/
std::vector<std::string> tokenize(const char* src,
char delim,
bool want_empty_tokens)
{
std::vector<std::string> tokens;
if (src and *src != '\0') // defensive
while( true ) {
const char* d = strchr(src, delim);
size_t len = (d)? d-src : strlen(src);
if (len or want_empty_tokens)
tokens.push_back( std::string(src, len) ); // capture token
if (d) src += len+1; else break;
}
return tokens;
}
这是一个简单的循环,只对标准库文件进行标记
#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++;
}
}
}
我知道这个问题已经有了答案,但我想有所贡献。也许我的解决方案有点简单,但这就是我想到的:
vector<string> get_words(string const& text, string const& separator)
{
vector<string> result;
string tmp = text;
size_t first_pos = 0;
size_t second_pos = tmp.find(separator);
while (second_pos != string::npos)
{
if (first_pos != second_pos)
{
string word = tmp.substr(first_pos, second_pos - first_pos);
result.push_back(word);
}
tmp = tmp.substr(second_pos + separator.length());
second_pos = tmp.find(separator);
}
result.push_back(tmp);
return result;
}
如果在我的代码中有更好的方法,或者有什么错误,请评论。
更新:添加通用分隔符
无意冒犯,但对于这样一个简单的问题,你把事情搞得太复杂了。使用Boost有很多理由。但对于这么简单的事情,就像用20号雪橇打苍蝇一样。
void
split( vector<string> & theStringVector, /* Altered/returned value */
const string & theString,
const string & theDelimiter)
{
UASSERT( theDelimiter.size(), >, 0); // My own ASSERT macro.
size_t start = 0, end = 0;
while ( end != string::npos)
{
end = theString.find( theDelimiter, start);
// If at end, use length=maxLength. Else use length=end-start.
theStringVector.push_back( theString.substr( start,
(end == string::npos) ? string::npos : end - start));
// If at end, use start=maxSize. Else use start=end+delimiter.
start = ( ( end > (string::npos - theDelimiter.size()) )
? string::npos : end + theDelimiter.size());
}
}
例如(以Doug为例),
#define SHOW(I,X) cout << "[" << (I) << "]\t " # X " = \"" << (X) << "\"" << endl
int
main()
{
vector<string> v;
split( v, "A:PEP:909:Inventory Item", ":" );
for (unsigned int i = 0; i < v.size(); i++)
SHOW( i, v[i] );
}
是的,我们可以split()返回一个新的向量,而不是传入一个。包装和重载是很简单的。但根据我所做的事情,我经常发现重用已有的对象比总是创建新对象更好。(只要我不忘记清空中间的向量!)
参考:http://www.cplusplus.com/reference/string/string/。
(我最初是在写一个回应Doug的问题:基于分隔符的c++字符串修改和提取(关闭)。但由于马丁·约克用这里的指针结束了这个问题……我将泛化我的代码。)