简体   繁体   English

C++ 从字符串中的每个轴获取 substring

[英]C++ get substring from each axis in a string

How can i acquire the value from each axis on a string?如何从字符串上的每个轴获取值?

#include <iostream>
#include <string>

using namespace std;

int main()
{
    string text = "X:-600.913 Y:100.54 Z:412.22";
    //do stuff
    string X; // must be -600.913
    string Y; // must be 100.54
    string Z; // must be 412.22
    //print individual values
    std::cout << X;
    std::cout << Y;
    std::cout << Z;
}

my previous attempt was我之前的尝试是

int main()
{
    string text = "X:-600.913 Y:100.54 Z:412.22";
    cin >> text;
    int Xsecond = text.find(" Y:");
    string X = text.substr(2, Xsecond - 4);
    int Yfirst = text.find("Y:");
    int Ysecond = text.find(" Z:");
    string Y = text.substr(Yfirst + 1, Ysecond-Yfirst - 1);
    cout << X;
}

which was too fuzzy and complicated and did not work at all.这太模糊和复杂,根本不起作用。 Any help would be appreciated!任何帮助,将不胜感激!

#include <iostream>
#include <string>
int main()
{
    std::string text="X:-600.913 Y:100.54 Z:412.22";
    size_t colon=text.find(":");
    size_t space=text.find(" ");
    std::string X=text.substr(colon+1,space-colon-1);
    colon=text.find(":",colon+1);
    space=text.find(" ",space+1);
    std::string Y=text.substr(colon+1,space-colon-1);
    colon=text.find(":",colon+1);
    space=text.find(" ",space+1);
    std::string Z=text.substr(colon+1,space-colon-1);
    std::cout<<X<<std::endl<<Y<<std::endl<<Z;
}

After the first find , consecutive calls begin searching from the previous hit.在第一次find之后,连续调用从上一次命中开始搜索。 We're subtracting 1 each time because we added it before and we need the distance.我们每次都减去 1,因为我们之前添加了它并且我们需要距离。 Simple math logic.简单的数学逻辑。

As mentioned in the comments, regular expressions work well for this kind of thing.正如评论中提到的,正则表达式适用于这种事情。 Use the module regex .使用模块正则表达式 Like so:像这样:

#include <iostream>
#include <cstdlib>
#include <regex>

int main()
{
    const std::string s = "X:-600.913 Y:100.54 Z:412.22"; 
    std::smatch m;
    std::regex e(R"(X:(-?\d+\.\d+)\sY:(-?\d+\.\d+)\sZ:(-?\d+\.\d+))");
 
    if (std::regex_search(s, m, e))
        std::cout << "X:" << m[1] << " Y:" << m[2] << " Z:" << m[3] << std::endl;
}
X:-600.913 Y:100.54 Z:412.22

You can use regex.您可以使用正则表达式。 For example ([XYZ]):(-?[0-9]+(\.[0-9]+)?)例如([XYZ]):(-?[0-9]+(\.[0-9]+)?)

[XYZ] matches X , Y or Z [XYZ]匹配XYZ

: matches : :匹配:

-? matches - or empty string匹配-或空字符串

[0-9]+ matches one or more characters from 0 - 9 range [0-9]+匹配0 - 9范围内的一个或多个字符

(\.[0-9]+)? matches dot followed by [0-9]+ or empty匹配点后跟[0-9]+或为空

There are additional parentheses to make capture groups (we can access them with std::smatch[x] ).还有额外的括号来创建捕获组(我们可以使用std::smatch[x]访问它们)。

std::string text = "X:-600.913 Y:100.54 Z:412.22";
 
std::regex regex("([XYZ]):(-?[0-9]+(\.[0-9]+)?)");

auto begin = std::sregex_iterator(text.begin(), text.end(), regex);
auto end = std::sregex_iterator();

for (std::sregex_iterator it = begin; it != end; it++)
{
    const std::smatch &match = *it;
    std::cout << match[1] << " is " << match[2] << std::endl;
}

The code above will simply output:上面的代码将只是 output:

X is -600.913
Y is 100.54
Z is 412.22

find returns the index of the first char matching the string. find返回匹配字符串的第一个字符的索引。 Given the indices of the start of a substing iStart and the index past the end of the substing iEnd you can get the substing using value.substr(iStart, iEnd - iStart) .给定 substing iStart开始的索引和 substing iEnd结束后的索引,您可以使用value.substr(iStart, iEnd - iStart)获得 substing。

Applying this to your strings (and hardcoding some of the lengths of the search strings) you could use the following code:将此应用于您的字符串(并对搜索字符串的一些长度进行硬编码),您可以使用以下代码:

int main()
{
    std::string text = "X:-600.913 Y:100.54 Z:412.22";

    const size_t xStart = 0;
    const size_t yStart = text.find(" Y:");
    const size_t zStart = text.find(" Z:");

    std::string X = text.substr(2, yStart - 2);
    std::string Y = text.substr(yStart + 3, zStart - (yStart + 3));
    std::string Z = text.substr(zStart + 3); // assuming here there are no chars after the end of the last number

    std::cout << X << ", " << Y << ", " << Z;

    return 0;

}

As @snoopy mentioned in the comments, this problem is a good fit for regular expressions.正如评论中提到的@snoopy,这个问题非常适合正则表达式。

You could use one regular expression for X, one regular expression for Y, and one regular expression for Z, and use regex_search to search the input string for each one independently.您可以对 X 使用一个正则表达式,对 Y 使用一个正则表达式,对 Z 使用一个正则表达式,并使用regex_search独立搜索每个输入字符串。

Or, you could combine X, Y, and Z into a single regular expression, use regex_match to match it against the whole input string at once, and then extract the parts from there .或者,您可以将 X、Y 和 Z 组合成一个正则表达式,使用regex_match一次将其与整个输入字符串进行匹配,然后从中提取部分

@alex_noname's answer gives a specific implementation. @alex_noname 的回答给出了一个具体的实现。


Alternatively, you could parse your input with more ad-hoc methods, like using .find() to split the string on colon ( : ) and space (或者,您可以使用更多临时方法解析您的输入,例如使用.find()在冒号 ( : ) 和空格 ( ) characters. ) 人物。

A disadvantage to these approaches is that you generally have to be more careful about handling wrongly-formatted input.这些方法的一个缺点是您通常必须更加小心处理格式错误的输入。

For example:例如:

X: -600.913 Y: 100.54 Z: 412.22

This input has extra spaces, and may break a naive .find() -based parser in unintuitive ways, like apparently "succeeding" but reporting empty strings as the output.此输入有额外的空格,并且可能会以不直观的方式破坏基于.find()的解析器,例如显然“成功”但将空字符串报告为 output。

On the other hand, regular expressions naturally tend to be stricter.另一方面,正则表达式自然倾向于更严格。 If your input was formatted unexpectedly, regex_match() will helpfully return false , and you can handle the error accordingly.如果您的输入被意外格式化, regex_match()将有助于返回false ,您可以相应地处理错误。

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

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