如何使用两个不同的分隔符拆分字符串

How to split a string with two different delimiters

本文关键字:分隔符 拆分 字符串 两个 何使用      更新时间:2023-10-16

我想将数据存储在对象数组中,但我不知道如何拆分字符串。

我希望看到的结果是:

tab[0].username = "user1"
tab[0].ip = "192.168.0.1"
tab[1].username = "user2"
tab[1].ip = "192.168.0.2"
tab[2].username = "user3"
tab[2].ip = "192.168.0.3"

这是我的字符串的外观:

user1:192.168.0.1|user2:192.168.0.2|user3:192.168.0.3

我目前拥有的代码,它只允许您在不管理管道的情况下拆分:

void addInTab(std::vector<std::string> vec, client *tab, int total_user)
{
for(int i = 0; i < 2; ++i) {
if (i == 0)
tab[total_user].username = vec[i];
if (i == 1)
tab[total_user].ip = vec[i];
}
}
void split(std::string str, char delim)
{
std::vector<std::string> vec;
std::string::size_type tmp = str.find(delim);
while(tmp != std::string::npos) {
vec.push_back(str.substr(0, tmp));
str = str.substr(tmp + 1);
tmp = str.find(delim);
}
vec.push_back(str);
addInTab(vec);
}

谢谢提前

我建议您创建split函数的更通用版本,该函数返回向量而不是调用某些特殊函数。

然后,您可以先调用它以拆分管道字符,然后在循环中再次调用它以拆分每个子字符串。

像这样的东西

std::vector<std::string> split(std::string str, char delim);
// ...
for (auto pair : split(original_input_with_pipes, '|'))
{
// Here pair is a string containing values like "user1:192.168.0.1" etc.
auto values = split(pair, ':');  // Split each pair
// Now values[0] should be e.g. "user1"
// and values[1] should be "192.168.0.1"
}

你来了。

#include <iostream>
#include <string>
#include <vector>
std::vector<std::string> splitStr( const std::string &s, 
const std::string &delim = " t" )
{
std::vector<std::string> v;
for ( std::string::size_type pos = 0, n = 0;
( pos = s.find_first_not_of( delim, pos ) ) != std::string::npos; 
pos += n )
{
n = s.find_first_of( delim, pos );
n = ( n == std::string::npos ? s.size() : n ) - pos;
v.push_back( s.substr( pos, n ) );
}
return v;
}
int main() 
{
const std::string s( "user1:192.168.0.1|user2:192.168.0.2|user3:192.168.0.3 " );
for ( const auto &item : splitStr( s, ":|" ) )
{
std::cout << item << std::endl;
}
return 0;
}

程序输出为

user1
192.168.0.1
user2
192.168.0.2
user3
192.168.0.3 

也就是说,您可以使用搜索成员函数find_first_of和类std::stringfind_first_not_of

您可以为函数提供任何一组分隔符。

如果你有提升

你可以做:

std::vector<std::string> tokens;
boost::split(tokens, input, boost::is_any_of("|:."));    

(然后只需将令牌填充到您的结构中即可(


自己试试吧! :

#include <boost/algorithm/string.hpp>
#include <iostream>
int main(){
auto input = "user1:192.168.0.1|user2:192.168.0.2|user3:192.168.0.3";
std::vector<std::string> tokens;
boost::split(tokens, input, boost::is_any_of("|:."));    
for (auto tok : tokens) {
std::cout << tok << std::endl;
}
return 0;
}

如果你没有提升

std::regex可以做同样的事情:

std::regex re("\.;\|");
std::sregex_token_iterator first{input.begin(), input.end(), re, -1}, last;//the '-1' is what makes it split
std::vector<std::string> tokens{first, last};

您可以使用正则表达式来执行复杂的字符串过程。它通常比手工处理更容易维护和使用。

#include <regex>
#include <string>
#include <iostream>
#include <iterator>
#include <algorithm>
int main() {
const std::string s = "user1:192.168.0.1|user2:192.168.0.2|user3:192.168.0.3";
std::regex r(R"_((userd+):((?:d{1,3}.?){4}))_");
struct record {
std::string username;
std::string ip;
};
std::vector<record> records;
std::transform(
std::sregex_iterator{ s.begin(), s.end(), r }, std::sregex_iterator{},
std::back_inserter(records),
[](auto& sm) -> record { return { sm[1],sm[2] }; }
);
std::transform(
records.begin(), records.end(),
std::ostream_iterator<std::string>{std::cout, "n"},
[](auto& rec) { return rec.username + ':' + rec.ip; }
);
}

只需拆分两次,第一次使用|,第二次(在每个结果上(以:作为分隔符。这是一个非常高效和紧凑的拆分功能

std::vector<std::string> split(const std::string& text, const char separator)
{
std::vector<std::string> items;
std::istringstream f(text);
std::string s;
while (getline(f, s, separator)) {
items.push_back(s);
}
return items;
}

如果您确定分隔符交替的事实,您可以通过交换分隔符来构建一个专门的函数,这里有一个简短的演示:


#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <sstream>
int main()
{
std::string text = "user1:192.168.0.1|user2:192.168.0.2|user3:192.168.0.3";
std::vector<std::pair<std::string, std::string> > pairs;
std::istringstream f(text);
std::string name, ip;
while (getline(f, name, ':')) {
if (getline(f, ip, '|')) {
pairs.push_back(std::pair<std::string,std::string>(name, ip));
} else {
break;
}
}
for (auto pair: pairs) {
std::cout << pair.first << ", " << pair.second << std::endl;
}
}