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

问题描述 投票:3回答:3

我必须在C ++中解析字符串才能从中获取双精度数。字符串的格式类似于[(a,b) - (c,d)],其中a,b,c和d将是双变量。

我试图使用stringstrem,但它不接受const char参数,所以我现在不知道如何解决它。

我的代码现在看起来像:

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

但遗憾的是它不起作用:(

例如:[(1.2,3.4) - (6.5,7.4)]。而且我要:

  a=1.2;
  b=3.4;
  c=6.5;
  d=7.4;
c++
3个回答
6
投票

使用输入流,您需要读取变量的输入。你可以用char读入std::istream::read或字符串。理想情况下,你会检查字符实际上是按预期,捕获并可能拒绝说__1.2-3.4@#~6.5,7.8++

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

或者您可以将其作为字符串读取,然后您可以使用C ++ <regex>功能来匹配它,可能类似于:

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

这将为您提供4个成功捕获组,然后您可以将其转换为双打。如果允许使用额外的空格,小数点是可选的等等,则可以修改此值。

如果格式有任何变化,例如有时您会得到3个数字,例如[(1.2,3.4)-(6.5,7.4)+(1.5,2)]你需要做更多深度解析,而不是>>操作员可以直接支持。

可能是基于ss >> chr读取的逻辑,或者基于前一个匹配结束的位置循环正则表达式(而不是一次匹配整个字符串),尽管事情变得更加先进。


1
投票

它肯定不是解决它的最优雅的方式,但它是一种人类可以阅读和维护的方式,并可能在以后轻松扩展......我更喜欢这种方式而不是正则表达式:-)

        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
        }

1
投票

老实说,这是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可以做到这一点(正如Fire Lancer所展示的那样),但是在冗长的情况下,你可以自己滚动它(如Ozzy所示),但为什么要这样做呢?

还有巨大的Boost.Spirit怪物可以以“现代”的方式做到这一点,获得的收益很少。

真的,这是一个单行解决的问题。

© www.soinside.com 2019 - 2024. All rights reserved.