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

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

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

问题

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

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

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

  1. boost::split(target_vector, inputString, boost::is_any_of(" "), boost::token_compress_on);
  2. ["-opt1", "val1", "-opt2", "val1", "val2", "-opt3", "val3"]

我更希望结果是

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

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

英文:

I have a command line argument as following string

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

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

  1. boost::split(target_vector, inputString, boost::is_any_of(" "), boost::token_compress_on);
  2. ["-opt1", "val1", "-opt2", "val1", "val2", "-opt3", "val3"]

I would rather like result to be

  1. ["-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

以下是翻译好的部分:

  1. 使用通用字符串拆分函数(分词器),可以将字符串拆分为以下输出:
  2. option : opt1 val1
  3. option name = opt1
  4. - value : val1
  5. option : opt2 val1 val2
  6. option name = opt2
  7. - value : val1 val2
  8. option : opt3 val3
  9. option name = opt3
  10. - value : val3
  11. 以下是源代码:
  12. #include <iostream>
  13. #include <limits>
  14. #include <vector>
  15. #include <string_view>
  16. // 通用字符串拆分算法(分词器)
  17. // 使用字符串视图以避免涉及字符串副本。
  18. auto split(std::string_view string, std::string_view delimiters, std::size_t maximum_number_of_substrings = std::numeric_limits<std::size_t>::max())
  19. {
  20. std::vector<std::string_view> substrings;
  21. if (string.size() == 0ul)
  22. {
  23. return substrings;
  24. }
  25. if (delimiters.size() == 0ul)
  26. {
  27. substrings.emplace_back(string);
  28. return substrings;
  29. }
  30. auto start_pos = string.find_first_not_of(delimiters);
  31. auto end_pos = start_pos;
  32. auto max_length = string.length();
  33. while (start_pos < max_length)
  34. {
  35. maximum_number_of_substrings--;
  36. if (maximum_number_of_substrings != 0ul)
  37. {
  38. end_pos = std::min(max_length, string.find_first_of(delimiters, start_pos));
  39. }
  40. else
  41. {
  42. end_pos = max_length;
  43. }
  44. if (end_pos != start_pos)
  45. {
  46. substrings.emplace_back(&string[start_pos], end_pos - start_pos);
  47. start_pos = string.find_first_not_of(delimiters, end_pos);
  48. }
  49. }
  50. return substrings;
  51. }
  52. int main()
  53. {
  54. // 演示命令行
  55. // 注意,我现在不检查输入字符串的有效性
  56. // 这只是一种快速的方法示意。
  57. std::string command_line{ "-opt1 val1 -opt2 val1 val2 -opt3 val3" };
  58. // 首先根据“-”拆分创建字符串视图向量
  59. auto options = split(command_line, "-");
  60. // 然后可以通过空格“ ”拆分每个拆分的子字符串
  61. for (const auto& option : options)
  62. {
  63. std::cout << "option : " << option << "\n";
  64. auto values = split(option, " ", 2ul);
  65. // 第一个拆分值将是选项名称
  66. std::cout << " option name = " << values[0] << "\n";
  67. // 其他子字符串将是值
  68. for (std::size_t n{ 1ul }; n < values.size(); ++n)
  69. {
  70. std::cout << " - value : " << values[n] << "\n";
  71. }
  72. }
  73. return 0;
  74. }

希望这对你有所帮助。

英文:

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

  1. option : opt1 val1
  2. option name = opt1
  3. - value : val1
  4. option : opt2 val1 val2
  5. option name = opt2
  6. - value : val1 val2
  7. option : opt3 val3
  8. option name = opt3
  9. - value : val3

Here is the source code:

  1. #include <iostream>
  2. #include <limits>
  3. #include <vector>
  4. #include <string_view>
  5. // a generic string splitting algorithm (tokenizer)
  6. // string_views are used so there will be no string copies involved.
  7. auto split(std::string_view string, std::string_view delimiters, std::size_t maximum_number_of_substrings = std::numeric_limits<std::size_t>::max())
  8. {
  9. std::vector<std::string_view> substrings;
  10. if (string.size() == 0ul)
  11. {
  12. return substrings;
  13. }
  14. if (delimiters.size() == 0ul)
  15. {
  16. substrings.emplace_back(string);
  17. return substrings;
  18. }
  19. auto start_pos = string.find_first_not_of(delimiters);
  20. auto end_pos = start_pos;
  21. auto max_length = string.length();
  22. while (start_pos < max_length)
  23. {
  24. maximum_number_of_substrings--;
  25. if (maximum_number_of_substrings != 0ul)
  26. {
  27. end_pos = std::min(max_length, string.find_first_of(delimiters, start_pos));
  28. }
  29. else
  30. {
  31. end_pos = max_length;
  32. }
  33. if (end_pos != start_pos)
  34. {
  35. substrings.emplace_back(&string[start_pos], end_pos - start_pos);
  36. start_pos = string.find_first_not_of(delimiters, end_pos);
  37. }
  38. }
  39. return substrings;
  40. }
  41. int main()
  42. {
  43. // demo command line
  44. // note I do NOT check for validity of the input string right now
  45. // this is a quick sketch of the approach.
  46. std::string command_line{ "-opt1 val1 -opt2 val1 val2 -opt3 val3" };
  47. // first create a vector of string_views based on splitting by "-"
  48. auto options = split(command_line, "-");
  49. // then each of those split substrings can be split by a space " "
  50. for (const auto& option : options)
  51. {
  52. std::cout << "option : " << option << "\n";
  53. auto values = split(option, " ", 2ul);
  54. // the first split value will be the option name
  55. std::cout << " option name = " << values[0] << "\n";
  56. // the other substrings will be the values
  57. for (std::size_t n{ 1ul }; n < values.size(); ++n)
  58. {
  59. std::cout << " - value : " << values[n] << "\n";
  60. }
  61. }
  62. return 0;
  63. }

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:

确定