C++?Boost?Spirit進(jìn)階教程
一、行動(dòng)
到目前為止,本章中的示例只檢測(cè)到兩件事:解析器是否成功以及解析器在哪里結(jié)束。但是,解析器通常以某種方式處理數(shù)據(jù),正如您將在下一個(gè)示例中看到的那樣。
Example11.9.Linking actions with parsers
#include <boost/spirit/include/qi.hpp> #include <string> #include <iostream> using namespace boost::spirit; int main() { std::string s; std::getline(std::cin, s); auto it = s.begin(); bool match = qi::phrase_parse(it, s.end(), qi::int_[([](int i){ std::cout << i << '\n'; })], ascii::space); std::cout << std::boolalpha << match << '\n'; if (it != s.end()) std::cout << std::string{it, s.end()} << '\n'; }
示例 11.9 使用 boost::spirit::qi::int_ 解析一個(gè)整數(shù),然后將該整數(shù)寫(xiě)入標(biāo)準(zhǔn)輸出。這就是為什么一個(gè)動(dòng)作與 boost::spirit::qi::int_ 相關(guān)聯(lián)。動(dòng)作是應(yīng)用解析器時(shí)調(diào)用的函數(shù)或函數(shù)對(duì)象。鏈接是使用運(yùn)算符 operator[] 完成的,它被 boost::spirit::qi::int_ 和其他解析器重載。示例 11.9 使用 lambda 函數(shù)作為操作,該操作需要一個(gè) int 類型的唯一參數(shù)并將其寫(xiě)入標(biāo)準(zhǔn)輸出。
如果您啟動(dòng)示例 11.9 并輸入一個(gè)數(shù)字,則會(huì)顯示該數(shù)字。
傳遞給動(dòng)作的參數(shù)類型取決于解析器。例如, boost::spirit::qi::int_ 轉(zhuǎn)發(fā)一個(gè) int 值,而 boost::spirit::qi::float_ 傳遞一個(gè) float 值。
Example11.10.Boost.Spirit with Boost.Phoenix
#define BOOST_SPIRIT_USE_PHOENIX_V3 #include <boost/spirit/include/qi.hpp> #include <boost/phoenix/phoenix.hpp> #include <string> #include <iostream> using namespace boost::spirit; using boost::phoenix::ref; int main() { std::string s; std::getline(std::cin, s); auto it = s.begin(); int i; bool match = qi::phrase_parse(it, s.end(), qi::int_[ref(i) = qi::_1], ascii::space); std::cout << std::boolalpha << match << '\n'; if (match) std::cout << i << '\n'; if (it != s.end()) std::cout << std::string{it, s.end()} << '\n'; }
示例 11.10 使用 Boost.Phoenix 將使用 boost::spirit::qi::int_ 解析的 int 值存儲(chǔ)在 i 中。如果 boost::spirit::qi::phrase_parse() 返回 true,則將 i 寫(xiě)入標(biāo)準(zhǔn)輸出。
這個(gè)例子在包含來(lái)自 Boost.Spirit 的頭文件之前定義了宏 BOOST_SPIRIT_USE_PHOENIX_V3。此宏選擇 Boost.Phoenix 的第三個(gè)和當(dāng)前版本。這很重要,因?yàn)?Boost.Phoenix 是從 Boost.Spirit 派生的,而 Boost.Spirit 包含 Boost.Phoenix 的第二個(gè)版本。如果未定義 BOOST_SPIRIT_USE_PHOENIX_V3,則 Boost.Phoenix 的第二個(gè)版本將包含在 Boost.Spirit 頭文件中,第三個(gè)版本將包含在 boost/phoenix/phoenix.hpp 中。不同的版本會(huì)導(dǎo)致編譯器錯(cuò)誤。
請(qǐng)注意如何詳細(xì)定義 lambda 函數(shù)。 boost::phoenix::ref() 創(chuàng)建對(duì)變量 i 的引用。但是,占位符 _1 不是來(lái)自 Boost.Phoenix,而是來(lái)自 Boost.Spirit。這很重要,因?yàn)?boost::spirit::qi::_1 提供了對(duì)具有通常預(yù)期類型的??解析值的訪問(wèn)——示例 11.10 中的 int。如果 lambda 函數(shù)使用 boost::phoenix::placeholders::arg1,編譯器會(huì)報(bào)錯(cuò),因?yàn)?boost::phoenix::placeholders::arg1 不代表 int;它將基于 Boost.Spirit 中的另一種類型,并且需要提取 int 值。
二、屬性
操作是處理解析值的一種選擇。另一種選擇是將對(duì)象傳遞給 boost::spirit::qi::parse() 或 boost::spirit::qi::phrase_parse() 用于存儲(chǔ)解析值。這些對(duì)象稱為屬性。它們的類型必須與解析器的類型相匹配。
您已經(jīng)在上一節(jié)中使用過(guò)屬性。傳遞給動(dòng)作的參數(shù)也是屬性。每個(gè)解析器都有一個(gè)屬性。例如,解析器 boost::spirit::qi::int_ 具有 int 類型的屬性。在以下示例中,屬性不會(huì)作為參數(shù)傳遞給函數(shù)。相反,解析后的值存儲(chǔ)在屬性中,可以在 boost::spirit::qi::parse() 或 boost::spirit::qi::phrase_parse() 返回后處理。
Example11.11.Storing anint
value in an attribute
#include <boost/spirit/include/qi.hpp> #include <string> #include <iostream> using namespace boost::spirit; int main() { std::string s; std::getline(std::cin, s); auto it = s.begin(); int i; if (qi::phrase_parse(it, s.end(), qi::int_, ascii::space, i)) std::cout << i << '\n'; }
示例 11.11 使用解析器 boost::spirit::qi::int_。解析后的 int 值存儲(chǔ)在變量 i 中。 i 作為另一個(gè)參數(shù)傳遞給 boost::spirit::qi::phrase_parse(),因此成為解析器 boost::spirit::qi::int_ 的一個(gè)屬性。 如果您啟動(dòng)示例 11.11 并輸入一個(gè)數(shù)字,該數(shù)字將被寫(xiě)入標(biāo)準(zhǔn)輸出流。
Example11.12.Storing severalint
values in an attribute
#include <boost/spirit/include/qi.hpp> #include <string> #include <vector> #include <iterator> #include <algorithm> #include <iostream> using namespace boost::spirit; int main() { std::string s; std::getline(std::cin, s); auto it = s.begin(); std::vector<int> v; if (qi::phrase_parse(it, s.end(), qi::int_ % ',', ascii::space, v)) { std::ostream_iterator<int> out{std::cout, ";"}; std::copy(v.begin(), v.end(), out); } }
示例 11.12 使用了一個(gè)用 qi::int_ % ',' 定義的解析器。解析器接受由逗號(hào)分隔的任意數(shù)量的整數(shù)。像往常一樣忽略空格。
因?yàn)榻馕銎骺梢苑祷囟鄠€(gè) int 值,所以屬性的類型必須支持存儲(chǔ)多個(gè) int 值。該示例傳遞一個(gè)向量。如果您開(kāi)始該示例并輸入多個(gè)以逗號(hào)分隔的整數(shù),則這些整數(shù)將寫(xiě)入以分號(hào)分隔的標(biāo)準(zhǔn)輸出流。
除了向量,您還可以傳遞其他類型的容器,例如 std::list。Boost.Spirit 文檔描述了哪些屬性類型必須與哪些運(yùn)算符一起使用。
到此這篇關(guān)于C++ Boost Spirit進(jìn)階教程的文章就介紹到這了,更多相關(guān)C++ Boost Spirit內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++?解決求兩個(gè)鏈表的第一個(gè)公共結(jié)點(diǎn)問(wèn)題
本文主要介紹了利用C++實(shí)現(xiàn)輸入兩個(gè)無(wú)環(huán)的單向鏈表時(shí),找出它們的第一個(gè)公共結(jié)點(diǎn)的問(wèn)題。文章中的示例代碼簡(jiǎn)潔易懂,感興趣的同學(xué)可以和小編一起學(xué)習(xí)一下2021-12-12從匯編看c++的默認(rèn)析構(gòu)函數(shù)的使用詳解
本篇文章是對(duì)c++中默認(rèn)析構(gòu)函數(shù)的使用進(jìn)行了詳細(xì)的分析介紹。需要的朋友參考下2013-05-05Qt編寫(xiě)地圖之實(shí)現(xiàn)經(jīng)緯度坐標(biāo)糾偏
地圖應(yīng)用中都涉及到一個(gè)問(wèn)題就是坐標(biāo)糾偏的問(wèn)題,這個(gè)問(wèn)題的是因?yàn)楦鶕?jù)地方規(guī)則保密性要求不允許地圖廠商使用標(biāo)準(zhǔn)的GPS坐標(biāo),而是要用國(guó)家定義的偏移標(biāo)準(zhǔn)。本文將詳細(xì)講解如何在Qt中實(shí)現(xiàn)經(jīng)緯度坐標(biāo)糾偏,需要的可以參考一下2022-03-03基于opencv實(shí)現(xiàn)車道線檢測(cè)
這篇文章主要為大家詳細(xì)介紹了基于opencv實(shí)現(xiàn)車道線檢測(cè),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-02-02