如何通过分隔符将字符串拆分为数组?
Posted
技术标签:
【中文标题】如何通过分隔符将字符串拆分为数组?【英文标题】:How can I split a string by a delimiter into an array? 【发布时间】:2009-05-20 20:48:22 【问题描述】:我是编程新手。我一直在尝试用 C++ 编写一个函数,将字符串的内容分解为给定参数的字符串数组,例如:
string str = "___this_ is__ th_e str__ing we__ will use__";
应该返回字符串数组:
cout << stringArray[0]; // 'this'
cout << stringArray[1]; // ' is'
cout << stringArray[2]; // ' th'
cout << stringArray[3]; // 'e str'
cout << stringArray[4]; // 'ing we'
cout << stringArray[5]; // ' will use'
我可以很好地标记字符串,但对我来说最困难的部分是如何在为其分配当前字符串之前指定 stringArray 中的元素数量以及如何从函数返回 stringArray。
有人能告诉我如何编写函数吗?
Edit1:我不一定需要将结果放在字符串数组中,只要我可以将其作为具有某种索引的常规变量调用的任何容器即可。
【问题讨论】:
家庭作业,也许?没关系,当然,但我来自不同人群的家庭作业问题的答案...... 重复:***.com/questions/53849/… @Iothar 的答案似乎更有效。 【参考方案1】:这是我第一次尝试使用向量和字符串:
vector<string> explode(const string& str, const char& ch)
string next;
vector<string> result;
// For each character in the string
for (string::const_iterator it = str.begin(); it != str.end(); it++)
// If we've hit the terminal character
if (*it == ch)
// If we have some characters accumulated
if (!next.empty())
// Add them to the result vector
result.push_back(next);
next.clear();
else
// Accumulate the next character into the sequence
next += *it;
if (!next.empty())
result.push_back(next);
return result;
希望这能让您对如何进行此操作有所了解。在您的示例字符串中,它使用此测试代码返回正确的结果:
int main (int, char const **)
std::string blah = "___this_ is__ th_e str__ing we__ will use__";
std::vector<std::string> result = explode(blah, '_');
for (size_t i = 0; i < result.size(); i++)
cout << "\"" << result[i] << "\"" << endl;
return 0;
【讨论】:
explode() 的第一个参数应该是一个常量引用。然后编译器会报错,所以 'it' 需要是一个 string::const_iterator。 @Magnus:谢谢,添加了修复:) 您应该检查next
是否不为空,如果是,请将其附加到循环后的结果中。否则,explode char 之后的最后一个元素将不会被包含。
最后一个元素被忽略!我在下面提出了一个解决方案,它有效!
@Veseliq 我编辑了评论并添加了 if 语句 - 一旦我的编辑获得批准,它就会显示出来。【参考方案2】:
使用 STL(抱歉没有未测试的编译器)
#include <vector>
#include <string>
#include <sstream>
int main()
std::vector<std::string> result;
std::string str = "___this_ is__ th_e str__ing we__ will use__";
std::stringstream data(str);
std::string line;
while(std::getline(data,line,'_'))
result.push_back(line); // Note: You may get a couple of blank lines
// When multiple underscores are beside each other.
// 或定义一个令牌
#include <vector>
#include <string>
#include <iterator>
#include <algorithm>
#include <sstream>
struct Token: public std::string // Yes I know this is nasty.
// But it is just to demosntrate the principle.
;
std::istream& operator>>(std::istream& s,Token& t)
std::getline(s,t,'_');
// ***
// Remove extra '_' characters from the stream.
char c;
while(s && ((c = s.get()) != '_')) /*Do Nothing*/
if (s)
s.unget(); // Put back the last char as it is not '_'
return s;
int main()
std::string str = "___this_ is__ th_e str__ing we__ will use__";
std::stringstream data(str);
std::vector<std::string> result(std::istream_iterator<Token>(data),
std::istream_iterator<Token>());
【讨论】:
因此在 while 循环中添加检查以跳过空“行”。 这是用户的练习。【参考方案3】:它对我有用:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
vector<string> explode( const string &delimiter, const string &explodeme);
int main(int argc, char *argv[])
string str = "I have a lovely bunch of cocoa nuts";
cout<<str<<endl;
vector<string> v = explode(" ", str);
for(int i=0; i<v.size(); i++)
cout <<i << " ["<< v[i] <<"] " <<endl;
vector<string> explode( const string &delimiter, const string &str)
vector<string> arr;
int strleng = str.length();
int delleng = delimiter.length();
if (delleng==0)
return arr;//no change
int i=0;
int k=0;
while( i<strleng )
int j=0;
while (i+j<strleng && j<delleng && str[i+j]==delimiter[j])
j++;
if (j==delleng)//found delimiter
arr.push_back( str.substr(k, i-k) );
i+=delleng;
k=i;
else
i++;
arr.push_back( str.substr(k, i-k) );
return arr;
来源: http://www.zedwood.com/article/106/cpp-explode-function
【讨论】:
【参考方案4】:您可以使用字符串向量(std::vector<std::string>
),使用 push_back 将每个标记附加到它,然后从您的标记化函数中返回它。
【讨论】:
【参考方案5】:使用 std::vector 作为动态数组并将其作为结果返回。
【讨论】:
【参考方案6】:也许您应该使用列表而不是数组。这样你就不需要提前知道元素的数量。您也可以考虑使用 STL 容器。
【讨论】:
【参考方案7】:如果您坚持将 stringArray
设为与 std::vector<>
相对的数组(这是正确的做法),您必须:
-
进行两次传球(你看,一次数)
自己实现一个动态数组。
使用向量更容易vector::push_back()
将新内容附加到末尾。所以:
vector* explode(string s)
vector<string> *v = new vector<string>
//...
// in a loop
v->push_back(string_fragment);
//...
return v;
毕竟不需要为了完整起见。
要返回您使用char **
的字符串数组。
如
char ** explode(const char *in)
...
顺便说一句——调用函数如何知道返回数组中有多少元素?你也必须解决这个问题。使用std::vector<>
除非您受到外力的约束...
【讨论】:
v->push_back(string_fragment); 我认为将堆栈分配的向量传回,或获取对要填充的向量的引用是更好的选择,然后在函数中分配原始向量,然后将删除职责传递给客户端。 @GMan:也许你是对的。我还在翻译中说 c++,并且有很多 c 的习惯徘徊...【参考方案8】:等到你的数据结构类,然后用链表编码。不过,如果是为了家庭作业,您可能只需初始化非常大的数组即可。
【讨论】:
【参考方案9】:以下代码:
template <typename OutputIterator>
int explode(const string &s, const char c, OutputIterator output)
stringstream data(s);
string line;
int i=0;
while(std::getline(data,line,c)) *output++ = line; i++;
return i;
int main(...)
string test="H:AMBV4:2:182.45:182.45:182.45:182.45:182.41:32:17700:3229365:201008121711:0";
cout << test << endl;
vector<string> event;
**This is the main call**
int evts = explode(test,':', back_inserter(event));
for (int k=0; k<evts; k++)
cout << event[k] << "~";
cout << endl;
输出
H:AMBV4:2:182.45:182.45:182.45:182.45:182.41:32:17700:3229365:201008121711:0
H~AMBV4~2~182.45~182.45~182.45~182.45~182.41~32~17700~3229365~201008121711~0~
【讨论】:
【参考方案10】:这是我编写的代码(完整)。可能对有相同需求的人有用。
#include <string>
#include <iostream>
#include <sstream>
#include <vector>
using namespace std;
int main()
std::string s = "scott:tiger:mushroom";
std::string delimiter = ":";
std::vector<std::string> outputArr;
size_t pos = 0;
std::string token;
while ((pos = s.find(delimiter)) != std::string::npos)
token = s.substr(0, pos);
s.erase(0, pos + delimiter.length());
outputArr.push_back(token);
outputArr.push_back(s);
// Printing Array to see the results
std::cout<<"====================================================================================\n";
for ( int i=0;i<outputArr.size();i++)
std::cout<<outputArr[i]<<"\n";
std::cout<<"====================================================================================\n";
干杯!!
【讨论】:
【参考方案11】:我认为我已经写了一个更简单的解决方案。
std::vector<std::string> explode(const std::string& string, const char delimiter)
std::vector<std::string> result;
unsigned int start = 0, pos = 0;
while (pos != string.length())
if (string.at(pos) == delimiter || pos + 1 == string.length())
unsigned int size = (pos - start) + ((pos + 1) == string.length() ? 1 : 0);
if (size != 0) // Make this 'if' as a option? like a parameter with removeEmptyString?
result.push_back(string.substr(start, size));
start = pos + 1;
pos++;
return std::move(result);
【讨论】:
【参考方案12】:这对我有用:
#include <iostream>
#include <vector>
#include <string>
#include <sstream>
using namespace std;
vector<string> split(string str, char delimiter)
vector<string> internal;
stringstream ss(str); // Turn the string into a stream.
string tok;
while(getline(ss, tok, delimiter))
internal.push_back(tok);
return internal;
int main(int argc, char **argv)
string myCSV = "one,two,three,four";
vector<string> sep = split(myCSV, ',');
// If using C++11 (which I recommend)
/* for(string t : sep)
* cout << t << endl;
*/
for(int i = 0; i < sep.size(); ++i)
cout << sep[i] << endl;
来源:http://code.runnable.com/VHb0hWMZp-ws1gAr/splitting-a-string-into-a-vector-for-c%2B%2B
【讨论】:
【参考方案13】:# turn a string into a deque based on a delimiter string
bool tolist(deque<string>& list,string basis,const string& cutter)
bool found = false;
if (!cutter.empty())
while (!basis.empty() )
string::size_type pos = basis.find(cutter);
if (pos != string::npos)
found = true;
list.push_back(basis.substr(0, pos)); //pos says 2
basis = basis.substr(pos+cutter.size(),string::npos);
else
list.push_back(basis);
basis.clear();
return found;
【讨论】:
以上是关于如何通过分隔符将字符串拆分为数组?的主要内容,如果未能解决你的问题,请参考以下文章