C++按空格拆分参数,但不拆分带有空格的值。

huangapple go评论98阅读模式
英文:

C++ splitting args by space, but dont split values with spaces

问题

我有一个命令行参数,格式如下字符串

"-opt1 val1 -opt2 val1 val2 -opt3 val3"

当我使用 boost 按空格拆分时,结果将如下

boost::split(target_vector, inputString, boost::is_any_of(" "), boost::token_compress_on);

["-opt1", "val1", "-opt2", "val1", "val2", "-opt3", "val3"]

我更希望结果是

["-opt1", "val1", "-opt2", "val1 val2", "-opt3", "val3"]

我可以编写一些逻辑来处理遇到的 -,但想知道是否有内置的方法来做到这一点。

英文:

I have a command line argument as following string

"-opt1 val1 -opt2 val1 val2 -opt3 val3"

When I use boost split by space, result will be following

boost::split(target_vector, inputString, boost::is_any_of(" "), boost::token_compress_on);

["-opt1", "val1", "-opt2", "val1", "val2", "-opt3", "val3"]

I would rather like result to be

["-opt1", "val1", "-opt2", "val1 val2", "-opt3", "val3"]

I can write some logic around encountering - but wanted to see if theer was some built in way to do it.

答案1

得分: 1

以下是翻译好的部分:

使用通用字符串拆分函数(分词器),可以将字符串拆分为以下输出:

option : opt1 val1
  option name = opt1
  - value : val1
option : opt2 val1 val2
  option name = opt2
  - value : val1 val2
option : opt3 val3
  option name = opt3
  - value : val3

以下是源代码:

#include <iostream>
#include <limits>
#include <vector>
#include <string_view>

// 通用字符串拆分算法(分词器)
// 使用字符串视图以避免涉及字符串副本。
auto split(std::string_view string, std::string_view delimiters, std::size_t maximum_number_of_substrings = std::numeric_limits<std::size_t>::max())
{
    std::vector<std::string_view> substrings;

    if (string.size() == 0ul)
    {
        return substrings;
    }

    if (delimiters.size() == 0ul)
    {
        substrings.emplace_back(string);
        return substrings;
    }

    auto start_pos = string.find_first_not_of(delimiters);
    auto end_pos = start_pos;
    auto max_length = string.length();

    while (start_pos < max_length)
    {
        maximum_number_of_substrings--;
        if (maximum_number_of_substrings != 0ul)
        {
            end_pos = std::min(max_length, string.find_first_of(delimiters, start_pos));
        }
        else
        {
            end_pos = max_length;
        }

        if (end_pos != start_pos)
        {
            substrings.emplace_back(&string[start_pos], end_pos - start_pos);
            start_pos = string.find_first_not_of(delimiters, end_pos);
        }
    }

    return substrings;
}

int main()
{
    // 演示命令行
    // 注意,我现在不检查输入字符串的有效性
    // 这只是一种快速的方法示意。
    std::string command_line{ "-opt1 val1 -opt2 val1 val2 -opt3 val3" };

    // 首先根据“-”拆分创建字符串视图向量
    auto options = split(command_line, "-");

    // 然后可以通过空格“ ”拆分每个拆分的子字符串
    for (const auto& option : options)
    {
        std::cout << "option : " << option << "\n";

        auto values = split(option, " ", 2ul);

        // 第一个拆分值将是选项名称
        std::cout << "  option name = " << values[0] << "\n";

        // 其他子字符串将是值
        for (std::size_t n{ 1ul }; n < values.size(); ++n)
        {
            std::cout << "  - value : " << values[n] << "\n";
        }
    }

    return 0;
}

希望这对你有所帮助。

英文:

With a generic string split function (tokenizer) the string can be split to generate output like this :

option : opt1 val1
  option name = opt1
  - value : val1
option : opt2 val1 val2
  option name = opt2
  - value : val1 val2
option : opt3 val3
  option name = opt3
  - value : val3

Here is the source code:

#include <iostream>
#include <limits>
#include <vector>
#include <string_view>

// a generic string splitting algorithm (tokenizer)
// string_views are used so there will be no string copies involved.
auto split(std::string_view string, std::string_view delimiters, std::size_t maximum_number_of_substrings = std::numeric_limits<std::size_t>::max())
{
    std::vector<std::string_view> substrings;

    if (string.size() == 0ul)
    {
        return substrings;
    }

    if (delimiters.size() == 0ul)
    {
        substrings.emplace_back(string);
        return substrings;
    }

    auto start_pos = string.find_first_not_of(delimiters);
    auto end_pos = start_pos;
    auto max_length = string.length();

    while (start_pos < max_length)
    {
        maximum_number_of_substrings--;
        if (maximum_number_of_substrings != 0ul)
        {
            end_pos = std::min(max_length, string.find_first_of(delimiters, start_pos));
        }
        else
        {
            end_pos = max_length;
        }

        if (end_pos != start_pos)
        {
            substrings.emplace_back(&string[start_pos], end_pos - start_pos);
            start_pos = string.find_first_not_of(delimiters, end_pos);
        }
    }

    return substrings;
}

int main()
{
    // demo command line
    // note I do NOT check for validity of the input string right now
    // this is a quick sketch of the approach.
    std::string command_line{ "-opt1 val1 -opt2 val1 val2 -opt3 val3" };

    // first create a vector of string_views based on splitting by "-"
    auto options = split(command_line, "-");

    // then each of those split substrings can be split by a space " "
    for (const auto& option : options)
    {
        std::cout << "option : " << option << "\n";

        auto values = split(option, " ", 2ul);

        // the first split value will be the option name
        std::cout << "  option name = " << values[0] << "\n";

        // the other substrings will be the values 
        for (std::size_t n{ 1ul }; n < values.size(); ++n)
        {
            std::cout << "  - value : " << values[n] << "\n";
        }
    }

    return 0;
}

huangapple
  • 本文由 发表于 2023年6月22日 02:30:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/76526175.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定