C++ 用选定的逗号分隔字符串
Posted
技术标签:
【中文标题】C++ 用选定的逗号分隔字符串【英文标题】:C++ separate string by selected commas 【发布时间】:2020-08-05 12:07:09 【问题描述】:我正在阅读以下问题Parsing a comma-delimited std::string,关于如何用逗号分割字符串(有人给了我上一个问题的链接),其中一个答案是:
stringstream ss( "1,1,1,1, or something else ,1,1,1,0" );
vector<string> result;
while( ss.good() )
string substr;
getline( ss, substr, ',' );
result.push_back( substr );
但是,如果我的字符串如下所示,并且我只想用粗体逗号分隔值而忽略 <>
中出现的内容,该怎么办?
,
,,
,
我想得到:
<a,b>
<c,d>
"" //Empty string
<d,l>
""
给定:,,
给定:,
鉴于:,它应该返回: 和 ""
给定:,,,
换句话说,我的程序应该像上面给定的解决方案一样,由 , 分隔(假设没有其他的,除了粗体的)
以下是一些建议的解决方案及其问题:
删除所有粗体逗号:这将导致以下 2 个输入以相同的方式处理,而它们不应该
,
,,
用一些字符替换所有粗体逗号并使用上述算法:我不能选择一些字符来替换逗号,因为任何值都可能出现在我的字符串的其余部分
【问题讨论】:
chat.***.com/rooms/219271/… 如果你有时间:) 评论不用于扩展讨论;这个对话是moved to chat。 【参考方案1】:添加到@Carlos 的答案,除了正则表达式(看看我的评论);您可以像下面这样实现替换(这里,我实际上构建了一个新字符串):
#include <algorithm>
#include <iostream>
#include <string>
int main()
std::string str;
getline(std::cin,str);
std::string str_builder;
for (auto it = str.begin(); it != str.end(); it++)
static bool flag = false;
if (*it == '<')
flag = true;
else if (*it == '>')
flag = false;
str_builder += *it;
if (flag)
str_builder += *it;
【讨论】:
您正在删除逗号,那么我现在如何分隔这些值? @daniel,我不会删除逗号。我只是简单地消除了无效的。你要实现类似的逻辑 但是下面的输入 ",为什么不用一些已知不冲突的字符替换一组逗号,然后用其他逗号分割,然后反转替换?
所以把 里面的逗号换成一些东西,做字符串拆分,再替换。
【讨论】:
你对“一些已知不冲突的字符”有什么建议?任何东西都可能出现在那个字符串中...... @daniel,看看我的回答。我已经在我的代码中改进并实现了这个答案:) @daniel 如何使用非 ASCII 字符,例如'\x01'`? 抱歉,我离开了一会儿。什么 char 不冲突取决于您的用例。明智地遵循@PaulSanders 的建议。 这在 C++11 中有效吗?如何在字符串 @PaulSanders 中用非 acsii 替换一个字符【参考方案3】:我认为你想要的是这样的:
vector<string> result;
string s = "<a,b>,,<c,d>"
int in_string = 0;
int latest_comma = 0;
for (int i = 0; i < s.size(); i++)
if(s[i] == '<')
result.push_back(s[i]);
in_string = 1;
latest_comma = 0;
else if(s[i] == '>')
result.push_back(s[i]);
in_string = 0;
else if(!in_string && s[i] == ',')
if(latest_comma == 1)
result.push_back('\n');
else
latest_comma = 1;
else
result.push_back(s[i]);
【讨论】:
我刚刚检查过,你的答案是错误的,而且它不能编译,因为结果是一个字符串向量而不是字符 不,仔细看看。他正在推动介于''之间的字符 @d4rk4ng31 但这不是我的问题,我想获取 和另一个 之间的值,换句话说: ,, 应该返回 a 和 "" 和 b 【参考方案4】:这是一个可能的代码,它一次扫描一个字符串并将其拆分为逗号 (','
),除非它们在括号中 ('<'
和 '>'
) 被屏蔽。
算法:
assume starting outside brackets
loop for each character:
if not a comma, or if inside brackets
store the character in the current item
if a < bracket: note that we are inside brackets
if a > bracket: note that we are outside brackets
else (an unmasked comma)
store the current item as a string into the resulting vector
clear the current item
store the last item into the resulting vector
只有 10 行,我的橡皮鸭同意它应该可以工作......
C++ 实现:我将使用向量来处理当前项目,因为一次构建一个字符更容易
std::vector<std::string> parse(const std::string& str)
std::vector<std::string> result;
bool masked = false;
std::vector<char> current; // stores chars of the current item
for (const char c : str)
if (masked || (c != ','))
current.push_back(c);
switch (c)
case '<': masked = true; break;
case '>': masked = false;
else // unmasked comma: store item and prepare next
current.push_back('\0'); // a terminating null for the vector data
result.push_back(std::string(¤t[0]));
current.clear();
// do not forget the last item...
current.push_back('\0');
result.push_back(std::string(¤t[0]));
return result;
我用你所有的示例字符串对其进行了测试,它给出了预期的结果。
【讨论】:
【参考方案5】:对我来说似乎很直接。
vector<string> customSplit(string s)
vector<string> results;
int level = 0;
std::stringstream ss;
for (char c : s)
switch (c)
case ',':
if (level == 0)
results.push_back(ss.str());
stringstream temp;
ss.swap(temp); // Clear ss for the new string.
else
ss << c;
break;
case '<':
level += 2;
case '>':
level -= 1;
default:
ss << c;
results.push_back(ss.str());
return results;
【讨论】:
以上是关于C++ 用选定的逗号分隔字符串的主要内容,如果未能解决你的问题,请参考以下文章
C ++:处理子字符串本身带有逗号的逗号分隔字符串的最简单方法? [关闭]