简体   繁体   English

用括号解析C ++中的字符串

[英]Parsing string in C++ with brackets

I have to parse string in C++ to get doubles out of it. 我必须在C ++中解析字符串才能从中获取双精度数。 String is in format like [(a,b)-(c,d)], where a, b, c and d are going to be double variables. 字符串的格式类似于[(a,b) - (c,d)],其中a,b,c和d将是双变量。

I was trying to use stringstrem, but it doesn't accept const char argument, so I have no idea right now how to solve it. 我试图使用stringstrem,但它不接受const char参数,所以我现在不知道如何解决它。

My code right now looks like: 我的代码现在看起来像:

ss >> "[(" >> a >> "," >> b >> ")-(" >> c >> "," >> d >> ")]";

But sadly it doesnt work :( 但遗憾的是它不起作用:(

For example: [(1.2,3.4)-(6.5,7.4)]. 例如:[(1.2,3.4) - (6.5,7.4)]。 And I want: 而且我要:

  a=1.2;
  b=3.4;
  c=6.5;
  d=7.4;

With input streams, you need to read input to a variable. 使用输入流,您需要读取变量的输入。 You could read into a char or into a string with std::istream::read . 您可以使用std::istream::read读入char或字符串。 Ideally you would check the characters are actually as expected, to catch and probably reject say __1.2-3.4@#~6.5,7.8++ 理想情况下你会检查字符是否符合预期,捕获并可能拒绝说__1.2-3.4@#~6.5,7.8++

char chr;
ss >> chr >> chr >> a >> chr >> b >> chr >> chr >> chr >> c >> chr >> d >> chr >> chr;

Alternatively you might read it as a string, and then you can use the C++ <regex> functionality to match it, perhaps something like: 或者,您可以将其作为字符串读取,然后您可以使用C ++ <regex>功能来匹配它,可能类似于:

^\[\((\d+\.\d+),(\d+\.\d+)\)-\((\d+\.\d+),(\d+\.\d+)\)\]$

This will give you 4 capture groups on success, which you can then convert to doubles. 这将为您提供4个成功捕获组,然后您可以将其转换为双打。 You can modify this if for example extra spaces are allowed, the decimal point is optional, etc. 如果允许使用额外的空格,小数点是可选的等等,则可以修改此值。

If there is any variation in the format at all, for example sometimes you get 3 numbers, eg [(1.2,3.4)-(6.5,7.4)+(1.5,2)] you would need to do more in depth parsing than the >> operator can directly support. 如果格式有任何变化,例如有时你会得到3个数字,例如[(1.2,3.4)-(6.5,7.4)+(1.5,2)]你需要做更深入的解析而不是>>运营商可以直接支持。

Possibly with logic based on what ss >> chr read, or by looping on a regex based on where the previous match ended (instead of matching the entire string at once) although things get a lot more advanced. 可能是基于什么ss >> chr读取的逻辑,或者基于前一个匹配结束的位置循环正则表达式(而不是一次匹配整个字符串),尽管事情变得更加先进。

It is not the most elegant way to solve it for sure, but it is a way that humans can read and maintain and possibly extend easily later... I would prefer this over regular expressions :-) 它肯定不是解决它的最优雅的方式,但它是一种人类可以阅读和维护的方式,并可能在以后轻松扩展......我更喜欢这种方式而不是正则表达式:-)

        auto input = "[(1.0,2.0)-(3.0,444.555)]";
        std::string in(input);
        for (auto iter = in.begin(); iter < in.end(); iter++)
        {
          char c = *iter;
          // If c == '(' or ',' parse a double number (digits or '.')
          // and save it somewhere. 

          // else: stop parsing a number / continue
        }

Honestly, this is one of those times when the C library still has the best tool for the job: 老实说,这是C库仍然拥有最佳工具的时代之一:

#include <cstdio>
#include <string>
#include <iostream>

int main()
{
    const std::string input = "[(1.2,3.4)-(6.5,7.4)]";

    double a, b, c, d;
    if (std::sscanf(input.c_str(), "[(%lf,%lf)-(%lf,%lf)]", &a, &b, &c, &d) == 4)
    {
        std::cout << "a=" << a << '\n';
        std::cout << "b=" << b << '\n';
        std::cout << "c=" << c << '\n';
        std::cout << "d=" << d << '\n';
    }
    else
    {
        std::cout << "Did not parse!\n";
    }
}

// Output:
// 
//   a=1.2
//   b=3.4
//   c=6.5
//   d=7.4

( live demo ) 现场演示

IOStreams can do it (as Fire Lancer showed) but reeeeally verbosely, and you can roll it yourself (as Ozzy showed) but why go to that effort? IOStreams可以做到这一点(正如Fire Lancer所展示的那样),但是在冗长的情况下 ,你可以自己滚动它(如Ozzy所示),但为什么要这样做呢?

There are also vast Boost.Spirit monstrosities that can do it in a "modern" way for very little gain. 还有巨大的Boost.Spirit怪物可以以“现代”的方式做到这一点,获得的收益很少。

Really this is a one-line solved problem. 真的,这是一个单行解决的问题。

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

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