Тернарный оператор + конструктор C ++ 11 из initializer_list

Меня раздражает, что нет функции разбить строку на основе функции, которая проверяет каждый символ. Если бы это было так, вы могли бы написать это следующим образом:

    public static IEnumerable<string> SplitCommandLine(string commandLine)
    {
        bool inQuotes = false;

        return commandLine.Split(c =>
                                 {
                                     if (c == '\"')
                                         inQuotes = !inQuotes;

                                     return !inQuotes && c == ' ';
                                 })
                          .Select(arg => arg.Trim().TrimMatchingQuotes('\"'))
                          .Where(arg => !string.IsNullOrEmpty(arg));
    }

Хотя написав это, почему бы не написать необходимые методы расширения. Хорошо, вы говорили мне об этом ...

Во-первых, моя собственная версия Split, которая принимает функцию, которая должна решить, должен ли указанный символ разбивать строку:

    public static IEnumerable<string> Split(this string str, 
                                            Func<char, bool> controller)
    {
        int nextPiece = 0;

        for (int c = 0; c < str.Length; c++)
        {
            if (controller(str[c]))
            {
                yield return str.Substring(nextPiece, c - nextPiece);
                nextPiece = c + 1;
            }
        }

        yield return str.Substring(nextPiece);
    }

Это может привести к некоторым пустым строкам в зависимости от ситуации, но, возможно, эта информация будет полезна в других случаях, поэтому я не удаляю пустые записи в этой функции.

Во-вторых (и более обыденно) a маленький помощник, который обрезает совпадающую пару кавычек от начала и конца строки. Это более суетливый, чем стандартный метод Trim - он будет обрезать только один символ с каждого конца, и он не будет обрезать только с одного конца:

    public static string TrimMatchingQuotes(this string input, char quote)
    {
        if ((input.Length >= 2) && 
            (input[0] == quote) && (input[input.Length - 1] == quote))
            return input.Substring(1, input.Length - 2);

        return input;
    }

И я полагаю, вам понадобятся и некоторые тесты , Ну, ладно. Но это должно быть абсолютно последнее! Сначала вспомогательная функция, которая сравнивает результат разделения с ожидаемым содержимым массива:

    public static void Test(string cmdLine, params string[] args)
    {
        string[] split = SplitCommandLine(cmdLine).ToArray();

        Debug.Assert(split.Length == args.Length);

        for (int n = 0; n < split.Length; n++)
            Debug.Assert(split[n] == args[n]);
    }

Затем я могу написать тесты следующим образом:

        Test("");
        Test("a", "a");
        Test(" abc ", "abc");
        Test("a b ", "a", "b");
        Test("a b \"c d\"", "a", "b", "c d");

Вот тест для вашего Требования:

        Test(@"/src:""C:\tmp\Some Folder\Sub Folder"" /users:""abcdefg@hijkl.com"" tasks:""SomeTask,Some Other Task"" -someParam",
             @"/src:""C:\tmp\Some Folder\Sub Folder""", @"/users:""abcdefg@hijkl.com""", @"tasks:""SomeTask,Some Other Task""", @"-someParam");

Обратите внимание, что в реализации есть дополнительная функция, которая будет удалять кавычки вокруг аргумента, если это имеет смысл (благодаря функции TrimMatchingQuotes). Я считаю, что это часть обычной интерпретации в командной строке.

24
задан Ryan Haining 9 August 2014 в 05:18
поделиться

2 ответа

Когда вы делаете {}, компилятор не знает тип ожидаемого, так что это просто бессмысленное выражение, с которым компилятор не знает, что делать. Обе стороны : оцениваются отдельно, и только тогда компилятор будет жаловаться, если типы не совпадают. Я бы просто сделал это:

return generator ? generator() : std::list<std::string>();
7
ответ дан spencercw 9 August 2014 в 05:18
поделиться

Другая возможность состоит в том, чтобы определить функцию-обертку для условного оператора:

template<class T> T& conditional(bool b, T&x, T&y) { return b ? x : y; }
template<class T> const T& conditional(bool b, const T&x, const T&y) { return b ? x : y; }

, которая позволяет вам вызывать:

return conditional(generator, generator(), {});
0
ответ дан Roland Schulz 9 August 2014 в 05:18
поделиться
Другие вопросы по тегам:

Похожие вопросы: