C++sscanf_s的替代品

Alternative to sscanf_s in C++

本文关键字:替代品 C++sscanf      更新时间:2023-10-16
result = sscanf_s(line.c_str(), "data (%d,%d)", &a, &b);

在上面的代码中,我使用sscanf_s从给定的字符串中提取两个整数值。在 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]);
}

如果它本身不是正则表达式,你可以使用 Boost.Spirit。下面是对此示例的轻微修改,并在向量中为您提供任意数量的逗号分隔整数。(这不完全是你要求的,但炫耀一些其他可能的东西,而且我不想花更多的精力来改变这个例子(。

这适用于迭代器,即字符串和流。它也可以简单地扩展到更复杂的语法,您可以创建可以重用的独立语法对象,或组合成更复杂的语法。(此处未演示。

#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;
}