C ++ отдельная строка выбранными запятыми - PullRequest
2 голосов
/ 05 августа 2020

Я читал следующий вопрос Разбор разделенного запятыми 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>

""
  1. Дано:,, Он должен вернуть: and "" and

  2. Дано:, Он должен вернуть: и

  3. Дано:, Он должен вернуть: и ""

  4. Дано:,,, Он должен вернуть: and "" and "" и

Другими словами, моя программа должна вести себя так же, как данное решение выше, разделенное, ( Допустим, нет других, кроме жирных)

Вот некоторые предлагаемые решения и их проблемы:

Удалите все жирные запятые: Это приведет к тому, что следующие 2 ввода будут обрабатываться одинаково, хотя они не должны 'т

,

,,

Замените все полужирные запятые на некоторые символы и используйте приведенный выше алгоритм: Я не могу выбрать какой-нибудь символ для замены запятых, поскольку любое значение может появляются в остальной части моей строки

Ответы [ 5 ]

2 голосов
/ 05 августа 2020

Добавление к ответу @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;
        }
    }
}
1 голос
/ 05 августа 2020

Почему бы не заменить один набор запятых на какой-нибудь символ sh, а затем разделить его на другие запятые, а затем отменить замену?

Так что замените запятые внутри <> чем-нибудь, разделите строку, замените снова.

0 голосов
/ 05 августа 2020

Мне это кажется довольно прямым.

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;
}
0 голосов
/ 05 августа 2020

Вот возможный код, который сканирует строку по одному символу за раз и разбивает ее на запятые (','), если они не замаскированы между скобками ('<' и '>').

Al go:

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

Я тестировал его со всеми вашими примерами строк, и он дает ожидаемые результаты.

0 голосов
/ 05 августа 2020

Думаю, вам нужно что-то вроде этого:

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]);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...