在C ++中替代sscanf_s

时间:2018-10-11 23:30:41

标签: c++ regex scanf

result = sscanf_s(line.c_str(), "data (%d,%d)", &a, &b);

在上面的代码中,我正在使用 sscanf_s 从给定的字符串 line 中提取两个整数值。在C ++ 11中还有另一种方法,更面向对象吗? (std :: stringstream和/或正则表达式?)

编辑:我尝试了两种解决方案,第一种无效,第二种有效

// solution one (doesn't work)
// let line = "data (3,4)"
std::regex re("data (.*,.*)");
std::smatch m;

if (std::regex_search(line, m, re) )
   cout << m[0] << " "<< m[1]; // I get the string "data (3,4) (3,4)"

// solution two (works but is somewhat ugly)
std::string name;
char openParenthesis;
char comma;
char closeParenthesis;
int x = 0, y = 0;

std::istringstream stream(line);
stream >> name >> openParenthesis >> a >> comma >> b >> closeParenthesis;

if( name=="data" && openParenthesis == '(' && comma == ',' && closeParenthesis == ')' )
{ 
    a = x;
    b = y;
}

编辑2:在肖恩(Shawn)的输入下,以下内容可以完美工作:

    std::regex re(R"(data \(\s*(\d+),\s*(\d+)\))");
    std::smatch m;

    if (std::regex_search(line, m, re) )
    {
        a = std::stoi(m[1]);
        b = std::stoi(m[2]);
    }

1 个答案:

答案 0 :(得分:1)

如果不必本身是正则表达式,则可以使用Boost.Spirit。以下是对this example的略微修改,并为您提供了向量中任意数量的逗号分隔的整数。 (这不完全是您所要求的,而是展示了其他可能的方式,而且我也不想花更多的精力来更改示例)。

这适用于迭代器,即字符串和流。它也可以轻松地扩展到更复杂的语法,并且您可以创建独立的语法 objects ,您可以重复使用它们,或者将其组合成更加复杂的语法。 (此处未演示。)

#include "boost/spirit/include/qi.hpp"
#include "boost/spirit/include/phoenix_core.hpp"
#include "boost/spirit/include/phoenix_operator.hpp"
#include "boost/spirit/include/phoenix_stl.hpp"

#include <iostream>
#include <string>
#include <vector>

namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
namespace phoenix = boost::phoenix;

template < typename Iterator >
bool parse_data( Iterator first, Iterator last, std::vector< int > & v )
{
        bool r = qi::phrase_parse( first, last,
                // Begin grammar
                (
                        qi::lit( "data" ) >> '('
                        >> qi::int_[ phoenix::push_back( phoenix::ref( v ), qi::_1 ) ]
                        >> *( ',' >> qi::int_[ phoenix::push_back( phoenix::ref( v ), qi::_1 ) ] )
                        >> ')'
                ),
                // End grammar
                ascii::space );

        if ( first != last ) // fail if we did not get a full match
        {
                return false;
        }

        return r;
}

int main()
{
        std::string input = "data (38,4)";
        std::vector< int > v;
        if ( parse_data( input.begin(), input.end(), v ) )
        {
                std::cout << "Read:\n";
                for ( auto i : v )
                {
                        std::cout << i << "\n";
                }
        }
        else
        {
                std::cout << "Failed.\n";
        }

        return 0;
}