- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
使用 Boost Spirit 2 开发,我正在尝试关注 example为了在我的 pgn 解析器中获得进展(稍后将添加语义操作)(另请参见 related previous question)。但我无法设法避免编译错误:cpp
#include "pgn_games_extractor.h"
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <tuple>
#include <iostream>
BOOST_FUSION_ADAPT_STRUCT(loloof64::pgn_tag, key, value)
BOOST_FUSION_ADAPT_STRUCT(loloof64::game_move, move_number, white_move, black_move, result)
BOOST_FUSION_ADAPT_STRUCT(loloof64::pgn_game, header, moves)
namespace loloof64 {
namespace qi = boost::spirit::qi;
typedef std::tuple<std::size_t, game_move> move_t;
typedef std::tuple<std::vector<pgn_tag>, std::vector<move_t>> game_t;
typedef std::tuple<std::size_t, std::vector<game_t>> pgn_t;
template <typename Iterator> struct pgn_parser : qi::grammar<Iterator, std::vector<pgn_game>, qi::space_type> {
pgn_parser() : pgn_parser::base_type(games) {
using namespace qi;
CurrentPos<Iterator> filepos;
const std::string no_move;
result.add
("1-0", result_t::white_won)
("0-1", result_t::black_won)
("1/2-1/2", result_t::draw)
("*", result_t::undecided);
quoted_string = '"' >> *~char_('"') >> '"';
tag = '[' >> +alnum >> quoted_string >> ']';
header = +tag;
regular_move = lit("O-O-O") | "O-O" | (+char_("a-hNBRQK") >> +char_("a-h1-8x=NBRQK") >> -lit("e.p."));
single_move = raw [ regular_move >> -char_("+#") ];
full_move = filepos.current_pos >> uint_
>> (lexeme["..." >> attr(no_move)] | "." >> single_move)
>> (single_move | attr(no_move))
>> -result;
game_description = +full_move;
single_game = -header >> game_description;
games = filepos.save_start_pos >> *single_game;
BOOST_SPIRIT_DEBUG_NODES(
(tag)(header)(quoted_string)(regular_move)(single_move)
(full_move)(game_description)(single_game)(games)
)
}
private:
qi::rule<Iterator, pgn_tag(), qi::space_type> tag;
qi::rule<Iterator, std::vector<pgn_tag>, qi::space_type> header;
qi::rule<Iterator, move_t(), qi::space_type> full_move;
qi::rule<Iterator, std::vector<move_t>, qi::space_type> game_description;
qi::rule<Iterator, game_t(), qi::space_type> single_game;
qi::rule<Iterator, pgn_t(), qi::space_type> games;
// lexemes
qi::symbols<char, result_t> result;
qi::rule<Iterator, std::string()> quoted_string;
qi::rule<Iterator> regular_move;
qi::rule<Iterator, std::string()> single_move;
};
}
loloof64::PgnGamesExtractor::PgnGamesExtractor(std::string inputFilePath) {
std::ifstream inputFile(inputFilePath);
parseInput(inputFile);
}
loloof64::PgnGamesExtractor::PgnGamesExtractor(std::istream &inputFile) { parseInput(inputFile); }
loloof64::PgnGamesExtractor::~PgnGamesExtractor() {
// dtor
}
void loloof64::PgnGamesExtractor::parseInput(std::istream &inputFile) {
if (inputFile.fail() || inputFile.bad())
throw new InputFileException("Could not read the input file !");
typedef boost::spirit::istream_iterator It;
loloof64::pgn_parser<It> parser;
std::vector<loloof64::pgn_game> temp_games;
It iter(inputFile >> std::noskipws), end;
//////////////////////////////////
std::cout << "About to parse the file" << std::endl;
//////////////////////////////////
bool success = boost::spirit::qi::phrase_parse(iter, end, parser, boost::spirit::qi::space, temp_games);
//////////////////////////////////
std::cout << "Finished to parse the file" << std::endl;
//////////////////////////////////
if (success && iter == end) {
games.swap(temp_games);
} else {
std::string error_fragment(iter, end);
throw PgnParsingException("Failed to parse the input at :'" + error_fragment + "' !");
}
}
和头文件:header .
#ifndef PGNGAMESEXTRACTOR_HPP
#define PGNGAMESEXTRACTOR_HPP
#include <string>
#include <vector>
#include <fstream>
#include <stdexcept>
#include <boost/fusion/adapted/std_tuple.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/repository/include/qi_iter_pos.hpp>
namespace loloof64 {
namespace phx = boost::phoenix;
namespace qi = boost::spirit::qi;
/*
* This class has been taken from http://marko-editor.com/articles/position_tracking/
*/
template<typename Iterator>
struct CurrentPos {
CurrentPos() {
save_start_pos = qi::omit[boost::spirit::repository::qi::iter_pos[
phx::bind(&CurrentPos::setStartPos, this, qi::_1)]];
current_pos = boost::spirit::repository::qi::iter_pos[
qi::_val = phx::bind(&CurrentPos::getCurrentPos, this, qi::_1)];
}
qi::rule<Iterator> save_start_pos;
qi::rule<Iterator, std::size_t()> current_pos;
private:
void setStartPos(const Iterator &iterator) {
start_pos_ = iterator;
}
std::size_t getCurrentPos(const Iterator &iterator) {
return std::distance(start_pos_, iterator);
}
Iterator start_pos_;
};
enum result_t { white_won, black_won, draw, undecided };
struct pgn_tag {
std::string key;
std::string value;
};
struct game_move {
unsigned move_number;
std::string white_move;
std::string black_move;
result_t result;
};
struct pgn_game {
std::vector<pgn_tag> header;
std::vector<game_move> moves;
};
class PgnGamesExtractor {
public:
PgnGamesExtractor(std::string inputFilePath);
PgnGamesExtractor(std::istream &inputFile);
/*
Both constructos may throw PgnParsingException (if bad pgn format) and InputFileException (if missing file)
*/
std::vector<pgn_game> getGames() const { return games; }
virtual ~PgnGamesExtractor();
protected:
private:
std::vector<pgn_game> games;
void parseInput(std::istream &inputFile);
};
class PgnParsingException : public virtual std::runtime_error {
public:
PgnParsingException(std::string message) : std::runtime_error(message) {}
};
class InputFileException : public virtual std::runtime_error {
public:
InputFileException(std::string message) : std::runtime_error(message) {}
};
}
#endif // PGNGAMESEXTRACTOR_HPP
我没有发布编译错误,因为编译错误太多了,而且文件很容易测试。
最佳答案
当然,它不会很好地与流媒体界面一起工作。您可以保留开始迭代器,但是
您不会提前知道流长度(除非您在带外获取它)
每次都计算当前位置(与起始迭代器的距离)效率极低。
由于您在评论中提到您正在解析文件,因此您应该考虑使用内存映射(例如 boost::iostream::mapped_file_source
或 mmap
)。这样,距离计算是瞬时的,在随机访问迭代器上使用指针算法。
这是一个工作示例,具有以下更改/注释:
omit[]
在save_start_pos
没用(没有声明的属性) getCurrentPos
效率极低(在某种程度上,仅在 omit[current_pos]
规则中使用 full_move
会使解析速度降低几个数量级。
This is because
boost::spirit::istream_iterator
holds on to all previously read state in a deque and traversing them doesn't come for free when doingstd::distance
你的 CurrentPos<Iterator> filepos;
实例在构造后超出范围!这意味着调用 save_start_pos
/current_pos
是 Undefined Behaviour ¹。将其移出构造函数。
您更改了某些规则的类型以包含位置信息以及 AST 类型。这既不必要又有缺陷:AST 类型与 tuple<size_t, T>
不兼容。规则的版本。
此外,例如games
规则甚至没有暴露位置,因为 save_start_pos
合成 unused_type
(无属性)。
所以,放弃整个元组业务,只处理 filepos
的状态语义 Action 中的成员:
full_move %=
omit[filepos.current_pos [ reportProgress(_1) ]] >>
uint_
>> (lexeme["..." >> attr(no_move)] | "." >> single_move)
>> (single_move | attr(no_move))
>> -result;
最后,作为如何报告严格增加的进度指示²的演示,我包括了一个简单的凤凰 Actor :
struct reportProgress_f {
size_t total_;
mutable double pct = 0.0;
reportProgress_f(size_t total) : total_(total) {}
template<typename T>
void operator()(T pos) const {
double newpct = pos * 100.0 / total_;
if ((newpct - pct) > 10) {
//sleep(1); // because it's way too fast otherwise...
pct = newpct;
std::cerr << "\rProgress " << std::fixed << std::setprecision(1) << pct << std::flush;
};
}
};
phx::function<reportProgress_f> reportProgress;
Note
reportProgress
needs to be constructed with knowledge about start and end iterators, see the constructor forpgn_parser
¹ 在 the recorded live stream 中你可以看到我在第一次阅读时发现了错误,然后在我编译之后忘记了。程序崩溃了,尽职尽责:)然后我想起来了。
² 即使面对回溯
3(不是严格要求,但我想目标不是简单地让它变得如此缓慢,以至于您实际上需要进度指示器?)
#ifndef PGNGAMESEXTRACTOR_HPP
#define PGNGAMESEXTRACTOR_HPP
#include <string>
#include <vector>
#include <fstream>
#include <stdexcept>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/spirit/repository/include/qi_iter_pos.hpp>
namespace loloof64 {
namespace phx = boost::phoenix;
namespace qi = boost::spirit::qi;
namespace qr = boost::spirit::repository::qi;
/*
* This class has been taken from http://marko-editor.com/articles/position_tracking/
*/
template<typename Iterator>
struct CurrentPos {
CurrentPos() {
save_start_pos = qr::iter_pos [phx::bind(&CurrentPos::setStartPos, this, qi::_1)] >> qi::eps;
current_pos = qr::iter_pos [qi::_val = phx::bind(&CurrentPos::getCurrentPos, this, qi::_1)] >> qi::eps;
}
qi::rule<Iterator> save_start_pos;
qi::rule<Iterator, std::size_t()> current_pos;
private:
void setStartPos(const Iterator &iterator) {
start_pos_ = iterator;
}
std::size_t getCurrentPos(const Iterator &iterator) {
return std::distance(start_pos_, iterator);
}
Iterator start_pos_;
};
enum result_t { white_won, black_won, draw, undecided };
struct pgn_tag {
std::string key;
std::string value;
};
struct game_move {
unsigned move_number;
std::string white_move;
std::string black_move;
result_t result;
};
struct pgn_game {
std::vector<pgn_tag> header;
std::vector<game_move> moves;
};
class PgnGamesExtractor {
public:
PgnGamesExtractor(std::string const& inputFilePath);
/*
Both constructos may throw PgnParsingException (if bad pgn format) and InputFileException (if missing file)
*/
std::vector<pgn_game> getGames() const { return games; }
virtual ~PgnGamesExtractor();
protected:
private:
std::vector<pgn_game> games;
void parseInput(std::string const&);
};
class PgnParsingException : public virtual std::runtime_error {
public:
PgnParsingException(std::string message) : std::runtime_error(message) {}
};
class InputFileException : public virtual std::runtime_error {
public:
InputFileException(std::string message) : std::runtime_error(message) {}
};
}
#endif // PGNGAMESEXTRACTOR_HPP
//#include "pgn_games_extractor.h"
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <iostream>
#include <iomanip>
BOOST_FUSION_ADAPT_STRUCT(loloof64::pgn_tag, key, value)
BOOST_FUSION_ADAPT_STRUCT(loloof64::game_move, move_number, white_move, black_move, result)
BOOST_FUSION_ADAPT_STRUCT(loloof64::pgn_game, header, moves)
namespace loloof64 {
namespace qi = boost::spirit::qi;
template <typename Iterator> struct pgn_parser : qi::grammar<Iterator, std::vector<pgn_game>(), qi::space_type> {
pgn_parser(Iterator start, Iterator end)
: pgn_parser::base_type(games),
reportProgress(std::distance(start, end))
{
using namespace qi;
const std::string no_move;
result.add
("1-0", result_t::white_won)
("0-1", result_t::black_won)
("1/2-1/2", result_t::draw)
("*", result_t::undecided);
quoted_string = '"' >> *~char_('"') >> '"';
tag = '[' >> +alnum >> quoted_string >> ']';
header = +tag;
regular_move = lit("O-O-O") | "O-O" | (+char_("a-hNBRQK") >> +char_("a-h1-8x=NBRQK") >> -lit("e.p."));
single_move = raw [ regular_move >> -char_("+#") ];
full_move %=
omit[filepos.current_pos [ reportProgress(_1) ]] >>
uint_
>> (lexeme["..." >> attr(no_move)] | "." >> single_move)
>> (single_move | attr(no_move))
>> -result;
game_description = +full_move;
single_game = -header >> game_description;
games = filepos.save_start_pos >> *single_game;
BOOST_SPIRIT_DEBUG_NODES(
(tag)(header)(quoted_string)(regular_move)(single_move)
(full_move)(game_description)(single_game)(games)
)
}
private:
struct reportProgress_f {
size_t total_;
mutable double pct = 0.0;
reportProgress_f(size_t total) : total_(total) {}
template<typename T>
void operator()(T pos) const {
double newpct = pos * 100.0 / total_;
if ((newpct - pct) > 10) {
//sleep(1); // because it's way too fast otherwise...
pct = newpct;
std::cerr << "\rProgress " << std::fixed << std::setprecision(1) << pct << " " << std::flush;
};
}
};
phx::function<reportProgress_f> reportProgress;
CurrentPos<Iterator> filepos;
qi::rule<Iterator, pgn_tag(), qi::space_type> tag;
qi::rule<Iterator, std::vector<pgn_tag>, qi::space_type> header;
qi::rule<Iterator, game_move(), qi::space_type> full_move;
qi::rule<Iterator, std::vector<game_move>, qi::space_type> game_description;
qi::rule<Iterator, pgn_game(), qi::space_type> single_game;
qi::rule<Iterator, std::vector<pgn_game>(), qi::space_type> games;
// lexemes
qi::symbols<char, result_t> result;
qi::rule<Iterator, std::string()> quoted_string;
qi::rule<Iterator> regular_move;
qi::rule<Iterator, std::string()> single_move;
};
}
#include <boost/iostreams/device/mapped_file.hpp>
loloof64::PgnGamesExtractor::~PgnGamesExtractor() {
// dtor
}
loloof64::PgnGamesExtractor::PgnGamesExtractor(std::string const& inputFilePath) {
parseInput(inputFilePath);
}
void loloof64::PgnGamesExtractor::parseInput(std::string const& inputFilePath) {
boost::iostreams::mapped_file_source mf(inputFilePath);
//if (inputFile.fail() || inputFile.bad())
//throw new InputFileException("Could not read the input file !");
typedef char const* It;
std::vector<loloof64::pgn_game> temp_games;
/* It iter(inputFile >> std::noskipws), end; */
auto iter = mf.begin();
auto end = mf.end();
loloof64::pgn_parser<It> parser(iter, end);
//////////////////////////////////
//std::cout << "About to parse the file" << std::endl;
//////////////////////////////////
bool success = boost::spirit::qi::phrase_parse(iter, end, parser, boost::spirit::qi::space, temp_games);
//////////////////////////////////
//std::cout << "Finished to parse the file" << std::endl;
//////////////////////////////////
if (success && iter == end) {
games.swap(temp_games);
} else {
std::string error_fragment(iter, end);
throw PgnParsingException("Failed to parse the input at :'" + error_fragment + "' !");
}
}
int main() {
loloof64::PgnGamesExtractor pge("ScotchGambit.pgn");
std::cout << "Parsed " << pge.getGames().size() << " games\n";
for (auto& g : pge.getGames())
for (auto& m : g.moves)
std::cout << m.move_number << ".\t" << m.white_move << "\t" << m.black_move << "\n";
}
带有示例输出
Progress 32.6
Progress 44.5
Progress 55.5
Progress 67.2
Progress 77.2
Progress 89.1
Progress 100.0Parsed 1 games
1. e4 e5
2. Nf3 Nc6
3. d4 exd4
4. Bc4 Qf6
5. O-O d6
6. Ng5 Nh6
7. f4 Be7
8. e5 Qg6
9. exd6 cxd6
10. c3 dxc3
11. Nxc3 O-O
12. Nd5 Bd7
13. Rf3 Bg4
14. Bd3 Bxf3
15. Qxf3 f5
16. Bc4 Kh8
17. Nxe7 Nxe7
18. Qxb7 Qf6
19. Be3 Rfb8
20. Qd7 Rd8
21. Qb7 d5
22. Bb3 Nc6
23. Bxd5 Nd4
24. Rd1 Ne2+
25. Kf1 Rab8
26. Qxa7 Rxb2
27. Ne6 Qxe6
28. Bxe6 Rxd1+
29. Kf2
Note that on a terminal, the progress indication will self-update using a carriage-return instead of printing separate lines
关于c++ - boost spirit 2:在 qi::parser 上跟随进度百分比。我的代码有什么问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34249652/
我正在开发一个在 gridview 中显示数据表内容的网页。而且,还有一个名为“发送到 Excel”的按钮。如果用户单击此按钮,该程序将开始生成报告(将数据表内容写入 excel 文件)。完成后,会出
理论:我在开始时做出了大约 100 个 promise ,然后使用 Promise.all() 解决它们。 这 100 个 promise 中的每一个依次进行一些异步 REST 调用,其响应可能主要不
在将文件添加到 python 中的 tar 存档时,是否有任何库可以显示进度,或者可以扩展 tarfile 模块的功能来执行此操作? 在理想情况下,我想展示 tar 创建的总体进度以及关于何时完成的预
有没有办法在 Xcode 中更改进度 View 栏的高度? 我正在使用 Xcode 4.3 并且需要一个垂直进度条。我旋转了栏,但现在无法更改高度并且显示为一个圆圈。 还有一种更有效的旋转进度条的方法
您好,我想在栏按钮项上制作未确定的进度 View 。完成后我想让它隐藏,但 hidden() 方法没有像 disabled(Bool) 这样的参数。任务完成后如何隐藏进度 View ? 这就是我要的
我有一个管理员控制的功能(导入数据库)可能需要一些时间才能完成,所以我想在这段时间内向用户显示一些反馈 - 例如进度条,或者只是一些消息。即使在长时间的 Action 中分部分发送页面也足够了。 在
我是一个进步的菜鸟,实际上在基本 block 方面有问题。 下面的问题是在我的 if else 语句中。它在 if, then, else then 时工作正常,但是当我想将多个语句放入 if 部分时
我有一个来自 rsync 命令的日志文件,其中有进度。运行此进度时,会更新同一行上的显示信息。当我捕获此命令的输出时,我得到一个在终端上使用 cat 正常显示的文件(重播所有退格键和重新编辑)但我希望
我需要处理一些数据,每 5-10 秒显示一个进度(我以 % 显示进度,但我也更新了一些图表)。我想在没有多线程的情况下做到这一点。 循环可能相当大。它可以从数百万开始,可以高达数十亿。 我可以使用 G
我正在致力于使用 PHP、HTML 和 JavaScript 制作半直播互联网 channel 。 您可以在此处查看演示:http://mariocreative.host/chanelko/inde
我实际上正在使用图像为“点点点”进度设置动画。我想通过使用下面的代码来使用不透明度。 动画将持续 3 秒,有没有更简单的动画方法? 最佳答案 这是一个快速版本,它会在控
我写了这个程序,它返回用户插入的最大整数。现在,我希望程序返回第二大整数。我创建了一个新变量(称为“状态”),该变量应该在每次循环重复时增加 1 个单位。然后,在中断条件发生后,我将在状态变量中后退
我正在制作一个需要保存进度的java游戏。但我不想让外部文件保存进度(像《我的世界》这样的游戏有一个存储文件的“保存”目录)。所以基本上我希望它存储一些数据,当用户退出并再次返回时可以检索这些数据。比
我正在使用 forEach_root 方法在 Android 上计算图像。 RenderScript RS=RenderScript.create(context); Allocation inPix
我希望这个进度 View 在完成后基本上“重置”。 尝试将计数重置为 0,它确实重置了,但是对于每次重置,计时器只会变得越来越快。 .h @property (nonatomic, strong) N
我不确定这是否可能。当您单击“提交”按钮时,似乎有一种方法可以做到这一点。 private Button getButton(String id) { return new AjaxButto
我找不到关于如何在迭代循环时更新 UIProgressbar 进度的明确答案,例如: for (int i=0;i
我正在尝试在 Xcode 中翻转 UIProgressView 180,同时我正在尝试缩放进度 View 。在我添加翻转之前缩放效果很好,然后缩放不再起作用。有什么建议么?谢谢! [self.seco
我目前正在通过评估 prepareForSegue 中的 segue.identifier 动态加载新 View : - (void)prepareForSegue:(UIStoryboardSegu
当任意进程发生时,我需要在屏幕上为用户提供状态。我无法知道需要多长时间。我怎样才能永远增加 progressView (当它接近 1 时它会减慢)。 最佳答案 This如果您愿意更换进度 View ,
我是一名优秀的程序员,十分优秀!