简体   繁体   English

从字符串C ++中提取子字符串

[英]Extract substring from string C++

I have a text file with GCode commands. 我有一个带有GCode命令的文本文件。 When I encounter a specific command, I want to place a new line after it with a new command. 当我遇到特定命令时,我想用新命令在其后放置新行。 That part is not an issue. 这部分不是问题。 The issue I have is that the command has the following form G0/G1 Xnnn Ynnn Znnn where the X/Y/Z params may or may not be present (at least one is required, but not all). 我的问题是该命令具有以下格式G0/G1 Xnnn Ynnn Znnn ,其中X / Y / Z参数可能存在或不存在(至少需要一个,但不是全部)。 What I want are the numbers after the X/Y/Z. 我想要的是X / Y / Z之后的数字。 My current working solution would involve using substring(start + 1, end - 1) and find(X/Y/Z) , then checking for all combinations as: 我当前的工作解决方案将涉及使用substring(start + 1, end - 1)find(X/Y/Z) ,然后检查所有组合,如下所示:

size_t xPos = str.find("X");
size_t yPos = str.find("Y");
size_t zPos = str.find("Z");
float x, y, z;
if(xPos != std::string::npos && yPos != std::string::npos) 
    x = std:stof(str.substring(xPos + 1, yPos - 1);

Is this an appropriate method of doing this? 这是合适的方法吗? Am I overcomplicating things? 我是否使事情复杂化了?

Edit: So, an input would look like G0 X101.1 Y102.3 or G0 Y122 or G0 X55 Z123 , so the n refers to a digit and the command is to tell something like a 3D printer how many units to move in a given direction, so it may need to make a move in one, two, or three directions. 编辑:因此,输入看起来像G0 X101.1 Y102.3G0 Y122G0 X55 Z123 ,因此n表示一个数字,命令是告诉类似3D打印机的对象在给定的范围内要移动多少单位方向,因此可能需要沿一个,两个或三个方向移动。

Each time I need to parse something in C++, I consider using Boost.Spirit. 每次我需要用C ++解析某些内容时,我都会考虑使用Boost.Spirit。 It is suitable for both trivial and quite complex parsing tasks. 它适用于琐碎和非常复杂的解析任务。

With Boost.Spirit, it would look like this : 使用Boost.Spirit,它看起来像这样

#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>

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

int main()
{
  namespace qi = boost::spirit::qi;
  namespace ascii = boost::spirit::ascii;
  std::string input = "G0/G1 X001 Y123 Z321";
  int x, y, z;
  bool result = qi::phrase_parse(input.begin(), input.end(),
     qi::lit("G0/G1") >> "X" >> qi::int_ >> "Y" >> qi::int_ >> "Z" >> qi::int_ , ascii::space, x, y, z);
  if (result)
  {
      std::cout << "X:" << x << std::endl;
      std::cout << "Y:" << y << std::endl;
      std::cout << "Z:" << z << std::endl;
  }
}

Note that the coordinates are parsed directly into int s! 注意,将坐标直接解​​析为int

UPDATE : A bit more complicated parsing , according to your updated question: 更新 :根据您更新的问题, 解析起来有些复杂

#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>

#include <iostream>
#include <string>
#include <vector>
#include <boost/optional.hpp>
#include <boost/optional/optional_io.hpp>

int main()
{
  namespace qi = boost::spirit::qi;
  namespace ascii = boost::spirit::ascii;
  std::string input = "G0 X001 Z321";
  boost::optional<float> x, y, z;
  int cmd;
  using namespace qi;
  bool result = phrase_parse(input.begin(), input.end(), qi::lexeme[lit("G") >> int_] >> -(lit("X") >> float_) >> -(lit("Y") >> float_) >> -(lit("Z") >> float_) , ascii::space, cmd, x, y, z);
  if (result)
  {
      std::cout << "Command number:" << cmd << std::endl;
      std::cout << "X:" << x << std::endl;
      std::cout << "Y:" << y << std::endl;
      std::cout << "Z:" << z << std::endl;
  }
}

Using std::stringstream 使用std::stringstream

int x, y, z = -1;

std::stringstream ss("G0/G1 X123 Y456");
std::string str;
while (ss>>str) {
    if (str.at(0) == 'X') {
        std::stringstream(str.substr(1)) >> x;
    } else if (str.at(0) == 'Y') {
        std::stringstream(str.substr(1)) >> y;
    } else if (str.at(0) == 'Z') {
        std::stringstream(str.substr(1)) >> z;
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM