我已经使用C++很长一段时间了但是scanf当我必须解析简单的文本文件时,我倾向于依赖它.例如,给定这样的配置(也假设字段的顺序可能不同):
foo: [3 4 5]
baz: 3.0
Run Code Online (Sandbox Code Playgroud)
我会写一些类似的东西:
char line[SOME_SIZE];
while (fgets(line, SOME_SIZE, file)) {
int x, y, z;
if (3 == sscanf(line, "foo: [%d %d %d]", &x, &y, &z)) {
continue;
}
float w;
if (1 == sscanf(line, "baz: %f", &w)) {
continue;
}
}
Run Code Online (Sandbox Code Playgroud)
在C++中实现这一目的最简洁的方法是什么?每当我尝试时,我最终会得到很多脚手架代码.
Nik*_*kko 29
这是一次只使用标准C++的尝试.
大多数时候我使用std :: istringstream和std :: getline(它可以分离单词)的组合来获得我想要的东西.如果我可以使我的配置文件看起来像:
FOO = 1,2,3,4
这让事情变得简单.
文本文件是这样的:
foo=1,2,3,4
bar=0
Run Code Online (Sandbox Code Playgroud)
你像这样解析它:
int main()
{
std::ifstream file( "sample.txt" );
std::string line;
while( std::getline( file, line ) )
{
std::istringstream iss( line );
std::string result;
if( std::getline( iss, result , '=') )
{
if( result == "foo" )
{
std::string token;
while( std::getline( iss, token, ',' ) )
{
std::cout << token << std::endl;
}
}
if( result == "bar" )
{
//...
}
}
Run Code Online (Sandbox Code Playgroud)
小智 19
在C++字符串工具箱库(StrTk)具有以下问题的解决方案:
#include <string>
#include <deque>
#include "strtk.hpp"
int main()
{
std::string file_name = "simple.txt";
strtk::for_each_line(file_name,
[](const std::string& line)
{
std::deque<std::string> token_list;
strtk::parse(line,"[]: ",token_list);
if (token_list.empty()) return;
const std::string& key = token_list[0];
if (key == "foo")
{
//do 'foo' related thing with token_list[1]
//and token_list[2]
return;
}
if (key == "bar")
{
//do 'bar' related thing with token_list[1]
return;
}
});
return 0;
}
Run Code Online (Sandbox Code Playgroud)
更多例子可以在这里找到
Boost.Spirit不保留解析复杂的结构.它在微分析方面也相当不错,几乎与C + scanf片段的紧凑性相匹配:
#include <boost/spirit/include/qi.hpp>
#include <string>
#include <sstream>
using namespace boost::spirit::qi;
int main()
{
std::string text = "foo: [3 4 5]\nbaz: 3.0";
std::istringstream iss(text);
std::string line;
while (std::getline(iss, line))
{
int x, y, z;
if(phrase_parse(line.begin(), line.end(), "foo: [">> int_ >> int_ >> int_ >> "]", space, x, y, z))
continue;
float w;
if(phrase_parse(line.begin(), line.end(), "baz: ">> float_, space , w))
continue;
}
}
Run Code Online (Sandbox Code Playgroud)
(为什么他们没有添加"容器"版本超出我的范围,如果我们可以写下来会更方便:
if(phrase_parse(line, "foo: [">> int_ >> int_ >> int_ >> "]", space, x, y, z))
continue;
Run Code Online (Sandbox Code Playgroud)
但确实如此:
所以最终,对于简单的解析,我像其他人一样使用scanf ......