使用C++解析带括号的字符串

4
我需要在C++中解析字符串以获取其内部的double变量。字符串的格式如下:[(a,b)-(c,d)],其中a、b、c和d都是double类型的变量。
我曾尝试使用stringstream,但它不接受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;

你需要额外的空间吗?你是否想检查输入的字符串? - Jarod42
3
为何不尝试使用正则表达式? - Andra
3
“现在你有两个问题了。” - Martin Bonner supports Monica
如果您被允许使用正则表达式,您可以像这样做(非常幼稚):https://regex101.com/r/k0pU5r/1 - Bas in het Veld
@BasinhetVeld,我尝试了你的正则表达式,但不幸的是它不能处理像[(11.0,2.132)-(31.12,421.30)]这样的字符串,请问你能告诉我如何修改吗? - Lisu
显示剩余6条评论
3个回答

7

使用输入流时,您需要将输入读入变量中。您可以使用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读取的逻辑或基于先前匹配结束位置的正则表达式循环,虽然这些会更加复杂。

2
老实说,在这种情况下,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

(演示现场)

IOStreams可以做到(如Fire Lancer所示),但是非常冗长,您可以自己实现它(如Ozzy所示),但是为什么要这么麻烦呢?

还有庞大的Boost.Spirit怪物可以用“现代”方式完成它,但收益微乎其微。

实际上,这是一个一行代码就能解决的问题。

最初的回答


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
        }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接