使用 strtok 解析字符串 - 在 C++ 中两次

Posted

技术标签:

【中文标题】使用 strtok 解析字符串 - 在 C++ 中两次【英文标题】:parsing a string using strtok - twice in C++ 【发布时间】:2019-11-12 10:41:43 【问题描述】:

我想使用 strtok 解析给定的字符串 - 但使用它两次。 要解析的字符串:“x=2;y=30”。 期望的输出: 一个包含 [x,y] 的字符串数组和一个包含 [2,30] 的字符串数组。 意思是,我想先用“;”作为分隔符,然后使用“=”作为分隔符。 我该怎么做 - 在 cpp 中?

【问题讨论】:

你好。向我们展示您的代码,看看您的阻塞点是什么 一定要使用strtok吗? boost::string::split 或 std::regex 可能更容易 【参考方案1】:

在 C++ 中,我不会使用 std::strtok()std::string 提供多种风格的 find 方法,例如std::string::find_first_of().

因为我忍不住要摆弄古老的strtok(),所以一个小演示:

#include <cassert>
#include <cstring>
#include <iostream>
#include <vector>

int main()

  char input[] = "x=2;y=30";
  std::vector<char*> leftHandSides, rightHandSides;
  for (char *in = input;;) 
    char *lhs = strtok(in, "=");
    in = nullptr;
    if (!lhs) break;
    char *rhs = strtok(in, ";");
    if (!rhs) break;
    leftHandSides.push_back(lhs);
    rightHandSides.push_back(rhs);
  
  for (size_t i = 0, n = rightHandSides.size(); i < n; ++i) 
    std::cout << leftHandSides[i] << '=' << rightHandSides[i] << '\n';
  

输出:

x=2
y=30

Live Demo on coliru

注意事项:

    strtok() 必须第一次使用指向缓冲区的指针(用于标记化)调用,并使用 0 指针来获取(相同缓冲区的)进一步结果。因此,char *in = input;char *lhs = strtok(in, "="); 之后被in = nullptr; 覆盖。在第一次迭代中完成这一点很重要。它也发生在所有其他迭代中是可以容忍的,因为它不会造成伤害。 (我本可以使用额外的 if 进行检查,但没有赢得任何东西。)

    strtok() 修改输入字符串。因此,我有意使用了char input[] = "x=2;y=30";。(使用const char *input = "x=2;y=30";,我会使用U.B. 编写代码)


最后,使用std::istringstreamstd::getline() 代替std::strtok() 的变体:

#include <iostream>
#include <sstream>
#include <string>
#include <vector>

int main()

  std::string input = "x=2;y=30";
  std::vector<std::string> leftHandSides, rightHandSides;
  for (std::istringstream in(input);;) 
    std::string lhs, rhs;
    if (!std::getline(in, lhs, '=')
      || !std::getline(in, rhs, ';')) break;
    leftHandSides.push_back(lhs);
    rightHandSides.push_back(rhs);
  
  for (size_t i = 0, n = rightHandSides.size(); i < n; ++i) 
    std::cout << leftHandSides[i] << '=' << rightHandSides[i] << '\n';
  

输出:

x=2
y=30

Live Demo on coliru

【讨论】:

第二个变体效果很好,关于 strtok(),你是对的。谢谢! @SarahDe-Paz 我的第一个反应是使用外部循环来分隔分配,使用内部循环来分隔 LHS 和 RHS。但后来我意识到,每次调用strtok() 都可以更改分隔符(即使对于相同的输入缓冲区也是如此)。 ;-)

以上是关于使用 strtok 解析字符串 - 在 C++ 中两次的主要内容,如果未能解决你的问题,请参考以下文章

使用strtok从字符串中解析空标记

strtok 并替换 C++ 中的子字符串

Android C++系列:Linux信号

strtok - 详细示例解析

strtok函数怎么用啊?

C语言最短时间带你实现strtok,字符串分割函数,建议收藏!!!