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 );

但是,如果我的字符串如下所示,并且我只想用粗体逗号分隔值而忽略 &lt;&gt; 中出现的内容,该怎么办?

,,,,

我想得到:

<a,b>

<c,d>

"" //Empty string

<d,l>

""

    给定:,,应该返回: and "" and

    给定:,应该返回:

    鉴于:它应该返回: 和 ""

    给定:,,,应该返回: and "" and "" and

换句话说,我的程序应该像上面给定的解决方案一样,由 , 分隔(假设没有其他的,除了粗体的)


以下是一些建议的解决方案及其问题:

删除所有粗体逗号:这将导致以下 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,我不会删除逗号。我只是简单地消除了无效的。你要实现类似的逻辑 但是下面的输入 "," 会导致 "" 为什么我需要这个?【参考方案2】:

为什么不用一些已知不冲突的字符替换一组逗号,然后用其他逗号分割,然后反转替换?

所以把 里面的逗号换成一些东西,做字符串拆分,再替换。

【讨论】:

你对“一些已知不冲突的字符”有什么建议?任何东西都可能出现在那个字符串中...... @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】:

这是一个可能的代码,它一次扫描一个字符串并将其拆分为逗号 (','),除非它们在括号中 ('&lt;''&gt;') 被屏蔽

算法:

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(&current[0]));
            current.clear();
        
    
    // do not forget the last item...
    current.push_back('\0');
    result.push_back(std::string(&current[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++ 添加逗号分隔值

C ++:处理子字符串本身带有逗号的逗号分隔字符串的最简单方法? [关闭]

用逗号分隔的字符串转换为逗号分隔的整型数组(前端技巧)

用逗号分隔数组,但是当涉及到最后一个字符串时,删除逗号[重复]

SQL拆分逗号分隔的字符串

拆分用逗号分隔的字符串并将值存储到 int 数组中