C++;使用sscanf解析输入的备选方案 假设我的程序期望形式>代码> [0.562,1.4E-2] (即,成对浮点数)的参数,我应该如何在没有正则表达式的情况下在C++中解析这个输入?我知道当涉及到用户输入时,有很多角落的情况需要考虑,但是让我们假设给定的输入与上面的格式(除了进一步的空白)非常匹配。

C++;使用sscanf解析输入的备选方案 假设我的程序期望形式>代码> [0.562,1.4E-2] (即,成对浮点数)的参数,我应该如何在没有正则表达式的情况下在C++中解析这个输入?我知道当涉及到用户输入时,有很多角落的情况需要考虑,但是让我们假设给定的输入与上面的格式(除了进一步的空白)非常匹配。,c++,parsing,scanf,C++,Parsing,Scanf,在C语言中,我可以执行类似于sscanf(字符串,[%g,%g]”,&f1,&f2)的操作提取两个浮点值,非常紧凑 在C++中,这是我迄今提出的: std::string s = "[ 0.562 , 1.4e-2 ]"; // example input float f1 = 0.0f, f2 = 0.0f; size_t leftBound = s.find('[', 0) + 1; size_t count = s.find(']', leftBound) - leftBound;

在C语言中,我可以执行类似于
sscanf(字符串,[%g,%g]”,&f1,&f2)的操作
提取两个浮点值,非常紧凑

在C++中,这是我迄今提出的:

std::string s = "[ 0.562 , 1.4e-2 ]"; // example input

float f1 = 0.0f, f2 = 0.0f;

size_t leftBound = s.find('[', 0) + 1;
size_t count = s.find(']', leftBound) - leftBound;

std::istringstream ss(s.substr(leftBound, count));
string garbage;

ss >> f1 >> garbage >> f2;

if(!ss)
  std::cout << "Error while parsing" << std::endl;
std::string s=“[0.562,1.4e-2]”;//示例输入
浮球f1=0.0f,f2=0.0f;
size_t leftBound=s.find('[',0)+1;
size_t count=s.find(']',leftBound)-leftBound;
std::istringstream ss(s.substr(leftBound,count));
字符串垃圾;
ss>>f1>>垃圾>>f2;
如果(!ss)

std::coutI你可以用boost,你可以用Spirit

  • 来自
    字符串(在c++03中):

  • 更新如果您真的试图从流中读取数据,这里有一种方法(实际上比较简单,并且与其他流读取活动集成得非常好):
    (c++03)

尽管这看起来更为冗长,但Spirit还是比
sscanf
更强大、更安全。它在流上运行

还要注意,
inf
-inf
nan
将按预期处理

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/qi_match.hpp>
#include <sstream>

namespace qi = boost::spirit::qi;

int main()
{
    std::istringstream ss("[ 0.562 , 1.4e-2 ]"); // example input
    ss.unsetf(std::ios::skipws); // we might **want** to handle whitespace in our grammar, not needed now

    float f1 = 0.0f, f2 = 0.0f;

    if (ss >> qi::phrase_match('[' >> qi::double_ >> ',' >> qi::double_ >> ']', qi::space, f1, f2))
    {
        std::cout << "Parsed: " << f1 << " and " << f2 << "\n"; // default formatting...
    } else
    {
        std::cout << "Error while parsing" << std::endl;
    }
}
#包括
#包括
#包括
名称空间qi=boost::spirit::qi;
int main()
{
std::istringstream ss(“[0.562,1.4e-2]”;//示例输入
unset(std::ios::skipws);//我们可能**想要**处理语法中的空白,现在不需要了
浮球f1=0.0f,f2=0.0f;
if(ss>>qi::phrase_match('['>>qi::double_>>','>>qi::double_>>']',qi::space,f1,f2))
{

std::cout除了正则表达式之外,Boost中可能还有一些东西你可以使用。但是如果你不能使用Boost,那么你可以定义一个
std::ctype
方面,通过将所有不必要的字符分类为空白来有效地忽略它们。你可以将这个方面安装到一个区域设置中,并将其嵌入到ob中以前的方法是创建一个简单的操纵器并使用它。例如,操纵器使用静态提供的
char
来确定下一个非空白字符是否是该字符,如果是,则提取它可能如下所示:

#include <iostream>
#include <sstream>

template <char C>
std::istream& expect(std::istream& in)
{
    if ((in >> std::ws).peek() == C) {
        in.ignore();
    }
    else {
        in.setstate(std::ios_base::failbit);
    }
    return in;
}
#包括
#包括
模板
std::istream&expect(std::istream&in)
{
if((在>>std::ws.peek()==C中){
in.ignore();
}
否则{
in.setstate(std::ios_base::failbit);
}
返回;
}
然后,可以使用“因此生成”操纵器提取字符:

int main(int ac, char *av[])
{
    std::string s(ac == 1? "[ 0.562 , 1.4e-2 ]": av[1]);
    float f1 = 0.0f, f2 = 0.0f;

    std::istringstream in(s);
    if (in >> expect<'['> >> f1 >> expect<','> >> f2 >> expect<']'>) {
        std::cout << "read f1=" << f1 << " f2=" << f2 << '\n';
    }
    else {
        std::cout << "ERROR: failed to read '" << s << "'\n";
    }
}
int main(int ac,char*av[])
{
std::字符串s(ac==1?[0.562,1.4e-2]”:av[1]);
浮球f1=0.0f,f2=0.0f;
std::istringstream(以秒为单位);
如果(在>>预期>>f1>>预期>>f2>>预期中){

std::cout为了回答您的问题,您可以通过使用
sscanf()
来改进代码那么,你应该说明原因。在这种情况下,这个问题以前被问过很多次,很不幸,C++比C更冗长。如果你有C++ 11编译器,你可能想研究一下。@ JoaHixiBr.g,我不认为应该用正则表达式来分析浮点数据。很好的回答,我不知道有多强大的精神。直到现在。不过,我将接受迪特玛·库尔的答案,因为我不能在这种特定情况下使用boost。但我会记住这一点,以备以后使用。不幸的是,该代码不再有效。编译器显示错误“使用重载运算符'>>'是含糊不清的”。你知道为什么吗?哦,还有,只有当我将f1和f2作为参数传递时才会出现此错误。如果没有它们,即
if(ss>>qi::phrase_match(“['>>qi::double_>>”,“>>qi::double_>>”,qi::space))
没有歧义错误。添加了一个到演示的链接。对你来说@AlanKałuża有什么不同?我认为你的所有代币不太可能像那样被很好地分隔开。