【问题标题】:How do I get a particular instance of a string that repeats multiple times in a string如何获取在字符串中重复多次的字符串的特定实例
【发布时间】:2017-05-29 09:36:53
【问题描述】:

我想将字符串KeyData(存在的是<eg2keydata> 属性)中的数据转换为*。但它总是采用字符串msgkeyData 的第一个实例。每次我想转换时如何获取特定实例?我是新手,我无法调试它。我不确定 for 循环。任何人请帮我找出错误。谢谢!

  const std::string& msg = "<PolicyAction><ManualKeyPolicyAction><TransformData SPI=\"1219546177\"><eg1KeyData Protocol=\"abc\" KeyLength=\"64\" KeyData=\"d789c\"></eg1KeyData><eg2KeyData Protocol=\"hm\" KeyLength=\"64\" KeyData=\"4328a036abfcf5e9\"></eg2KeyData><Tunne<PolicyAction><ManualKeyPolicyAction><TransformData SPI=\"1219546177\"><eg1KeyData Protocol=\"aes-cbc\" KeyLength=\"64\" KeyData=\"d789c\"></eg1KeyData><eg2KeyData Protocol=\"hmac-sha1-96\" KeyLength=\"64\" KeyData=\"4328a03\"></eg2KeyData><SaltData ";
  std::size_t search1 = msg.find("<eg2KeyData");
  const std::string from1 = "KeyData=\"";
  const std::string to1 = "\"></eg2KeyData>";
  std::size_t endpos1 = msg.find(to1);
  std::string s = msg;
  std::size_t l1 = 0;
  if (msg.find("<eg2KeyData") != std::string::npos)
  {
      l1 = msg.find("KeyData=\"",search1);

    if (l1 != 0)
    {
      std::size_t r1 = endpos1 - l1 - from1.length();
      s.replace(l1 + from1.length(), r1, r1, '*');
    }
  }
  std::cout << s;

【问题讨论】:

  • 如果你想解析 XML 数据,为什么不使用 XML 解析器呢?不乏可供选择的。
  • 但我的任务是用 C++ 来完成。我想知道如何使用 find 命令查找子字符串的所有出现,而不仅仅是第一次出现。
  • 我会指出纯 C++ XML 解析器确实存在(谷歌的第一个热门,tinyxml),并且自己解析 XML 数据,这种艰难的方式是一个可怕的、可怕的想法。随意将其传递给为您设置任务的人,他们应该更清楚。
  • 您尝试做的事情需要认真解析。如果您仍想使用临时解决方案,请参阅this
  • 您的 XML 数据格式仍然不正确。里面有&lt;Tunne&lt;之类的东西。

标签: c++


【解决方案1】:

首先要注意最重要的一点:不使用 XML 库为您执行此操作太疯狂了。尝试在不使用理解 XML 格式的东西的情况下正确处理复杂数据是一个非常非常糟糕的主意。


如果你想找到你刚刚找到的子字符串的下一个实例,你只需要告诉find你想从哪里开始搜索,例如。

const std::string& msg = "<PolicyAction><ManualKeyPolicyAction><TransformData SPI=\"1219546177\"><eg1KeyData Protocol=\"abc\" KeyLength=\"64\" KeyData=\"d789c\"></eg1KeyData><eg2KeyData Protocol=\"hm\" KeyLength=\"64\" KeyData=\"4328a036abfcf5e9\"></eg2KeyData><Tunne<PolicyAction><ManualKeyPolicyAction><TransformData SPI=\"1219546177\"><eg1KeyData Protocol=\"aes-cbc\" KeyLength=\"64\" KeyData=\"d789c\"></eg1KeyData><eg2KeyData Protocol=\"hmac-sha1-96\" KeyLength=\"64\" KeyData=\"4328a03\"></eg2KeyData><SaltData ";

size_t p = msg.find("KeyData=");

while (p != std::string::npos)
{
  std::cout << p << " ";
  p = msg.find("KeyData=", p + 1);
}

std::cout << std::endl;

然后给出结果

111 181 342 422

然后,您可以搜索字符串 \" 的下两个实例,并使用这些位置来计算要更改的文本的起点和终点。

只需阅读文档! http://en.cppreference.com/w/cpp/string/basic_string/find

或者,您可以考虑使用正则表达式:

std::regex r("KeyData=\\\"([a-z0-9]+)\\\"");

for (auto i = std::sregex_iterator(msg.begin(), msg.end(), r); i != std::sregex_iterator(); i++)
  std::cout << i->position() << " ";

std::cout << std::endl;

这给出了相同的结果。不过这里我不打算详细介绍如何使用正则表达式。

http://en.cppreference.com/w/cpp/regex

【讨论】:

  • 如果 仅出现一次,此方法有效。如果我多次出现 怎么办
  • @leenvr 除非您可以提供源数据的实际示例,以及您想要查找的实际示例,否则我们只需要猜测您想要什么。我已经回答了你目前的问题。如果这不是您想要的答案,您将不得不编辑您的问题,以便它实际上询问您想要什么
  • 很抱歉没有提供正确的源字符串。我已经编辑了我的代码。在更新的代码中,能否请您帮我在字符串中的两个位置转换 eg2KeyData 中的 KeyData
  • @leenvr 我对我的代码进行了非常小的编辑以使用 while 循环。正在使用相同的基本技术。返回KeyData 的所有位置。这是你想要的吗?
猜你喜欢
  • 1970-01-01
  • 2021-03-03
  • 1970-01-01
  • 2019-01-07
  • 1970-01-01
  • 2017-07-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多