我试图从字符串中提取某些数据,如下所示:
2833ae7~2be;2833ae8~2272
我想要做的是首先用冒号拆分它,然后每条记录,找到它是否包含2be
然后用~2be
拆分包含它的记录,然后再给我一个值~2be
我做了一些文章,这段代码就是这样做的,但问题是它没有给我全部输出:
#include <string>
#include <sstream>
#include <vector>
#include <iostream>
using namespace std;
vector<string> split(string str,string sep){
char* cstr=const_cast<char*>(str.c_str());
char* current;
vector<string> arr;
current=strtok(cstr,sep.c_str());
while(current!=NULL){
arr.push_back(current);
current=strtok(NULL,sep.c_str());
}
return arr;
}
int main(){
string items = "2833ae7~2be;2833ae8~2272";
vector<string> food = split(items, ";");
for(unsigned int i = 0; i < food.size(); i++)
{
if(food[i].find("2be") != string::npos)
{
vector<string> arr = split(food[i],"~2be");
cout << "Output ("<< i << ") = " << arr[0] << endl;
}// end if
}// end for
return 0;
}// end main
我得到的输出是:
Output <0> = 833a
应该是:
Output <0> = 2833ae7
我做错了什么?
答案 0 :(得分:0)
正如其他人在评论中提到的那样,修改从std::string::c_str()
获得的字符数组是未定义的行为。 strtok()
修改其参数以标记令牌,因此您无法在此处使用它。
通过单个字符分隔符拆分std::string
并不难。你可以这样做的一种方式是:
std::vector<std::string> split(const std::string &input, std::string::value_type delim)
{
std::stringstream ss(input);
std::vector<std::string> tokens;
std::string token;
while (std::getline(ss, token, delim))
{
tokens.push_back(token);
}
return tokens;
}
然后您可以像这样拆分字符串:
std::vector<std::string> tokens = split("2833ae7~2be;2833ae8~2272", ';');
这将为您提供一个包含两个元素的向量:&#34; 2833ae7~2be&#34;和&#34; 2833ae8~2272&#34;。
现在对于第二部分,您不能使用相同的split()
方法,因为它仅适用于单字符分隔符。但你可以这样做:
for (std::size_t index = 0; index < tokens.size(); ++index)
{
if (tokens[index].find("2be") != std::string::npos)
{
std::string::size_type pos = tokens[index].find("~2be");
std::cout << "Output (" << index << ") = " << tokens[index].substr(0, pos) << "\n";
}
}
使用相同的想法,您也可以尝试重写split()
方法,使其适用于字符串分隔符,而不仅仅是像我的版本那样的单字符。