Подтвердить что ты не робот

Разделение строки в С++

Я пытаюсь разделить строку на несколько строк, чтобы создать настраиваемый терминал. До сих пор я разделял управляющие сигналы с помощью strtok, однако я не понимаю, как отделить конкретные экземпляры персонажа. Например:

string input = "false || echo \"hello world\" | grep hello";

При попытке strtok в этом input и попытке разделения с помощью | выход будет выглядеть следующим образом:

false, echo "hello world", grep hello

Вместо этого я хотел бы, чтобы результат был:

false || echo "hello world", grep hello

Как я могу использовать strtok | и || по-другому, а не говорить, что они одинаковы?

4b9b3361

Ответ 1

#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
using namespace std;

vector<string> split(string sentence,char delim)
{
    string tempSentence = "";
    tempSentence += delim;
    tempSentence += sentence;
    tempSentence += delim;

     string token;
     vector<string> tokens;
    for (int i=1;i<tempSentence.length()-1;++i)
    {
        if (tempSentence[i] == delim && tempSentence[i-1] != delim && tempSentence[i+1] != delim)
        {
            if (token.length()) tokens.push_back(token);
            token.clear();
        }
        else
        {
            token += tempSentence[i];
        }
    }
    if (token.length()) tokens.push_back(token);

    return tokens;
}

int main() {
    string sentence = "false || echo \"hello world\" | grep hello";
    char delim='|';

    vector<string> tokens = split(sentence,delim);


    for_each(tokens.begin(), tokens.end(), [&](string t) {   
        cout << t << endl;
    });

}

уродливый и длинный! но работает!

Ответ 2

strtok() будет сканировать символ по символу, независимо от символов до и после того, что он ищет. Если вы хотите более разумное сканирование, вам нужно будет выполнить дополнительную проверку самостоятельно.

Так как strtok просто возвращает местоположение внутри строки, где найден токен, вам нужно вручную проверить первый символ возвращаемого токена, чтобы увидеть, является ли он также '|', а затем действовать соответственно.

Лучшим решением было бы изучить использование здесь регулярного выражения. Похоже, что символ, который вы хотите разбить, - это не просто |, а скорее | окруженный пробелами - т.е. вы на самом деле выполняете поиск и разделение на трехсимвольный символ (космос - труба - пространство)

Ответ 3

Я бы сказал, что ответ на ваш вопрос в первую очередь не должен использовать strtok(), который имеет множество проблем, которые даже задокументированы в man-странице (по крайней мере, в Linux).

Во-вторых, убедитесь, что у вас есть тесты. Использование тестовой разработки является обязательным условием для этих задач, поскольку здесь несколько простых вещей могут плохо взаимодействовать друг с другом, а исправление ошибки в одном месте может вызвать проблемы в другом.

Кроме того, существуют инструменты (например, различные варианты YACC и аналогичные генераторы), которые позволяют вам указать абстрактный синтаксис, а затем превратить это определение в код С++. Я бы предложил их для любой нетривиальной задачи.

Наконец, если вы делаете это только для удовольствия и обучения, пишите цикл или набор функций для извлечения различных токенов из строки - хороший подход.

Ответ 4

#include <iostream>
#include <string>
#include <algorithm>

using namespace std;

int main() {
    string input = "false || echo \"hello world\" | grep hello";

    string::iterator itr;

    itr = input.begin();

    do {
        itr = search_n(itr, input.end(), 1, '|');

        if (itr < input.end() - 1)
        {
            if (*(itr + 1) == '|')
            {
                itr = itr + 2;
                continue;
            }
        }        

        if (itr < input.end())
        {
                *itr = ',';
                itr ++;
        }

    } while (itr < input.end());

    cout << input << endl;

    return 0;
}

Ответ 5

Довольно простое и простое решение, которое, кажется, решает ваш вопрос.

std::string:: find() выполняет поиск строки для первого вхождения последовательности, заданной его аргументами (в этом случае строка 'delimiter'). Когда pos задано, поиск включает только символы в позиции pos или после.

Edited

    #include <iostream>
    #include <string>
    int main(int argc, char const *argv[])
    {
        std::string s = "false || echo \"hello world\" | grep hello";
        std::string delimiter = "|";

        size_t pos = 0, pos1 = 0, flag = 0;
        std::string token, token1;
        while ((pos = s.find(delimiter)) != std::string::npos) {
            pos1 = s.find(delimiter, pos + delimiter.length());
            while (pos1 == pos+1){
                pos = pos1;
                pos1 = s.find(delimiter, pos + delimiter.length());
                flag = 1;
            }
            if (flag) {
                token = s.substr(0, pos1);
                std::cout << token << std::endl;
                if (pos1 > s.length())
                    exit(0);
                s.erase(0, pos1 + delimiter.length());
            }
            else{
                token = s.substr(0, pos);
                std::cout << token << std::endl;
                s.erase(0, pos + delimiter.length());
            }

        }
        std::cout << s << std::endl;
        return 0;
    }

ВЫХОД:

false || echo "hello world"

grep hello