1

簡単にするために、質問全体を下品にします。

私は演算子ORとANDのみを使用してブール演算に取り組んでいます(今のところ)。

私のブール式は、変数と演算子( "a OR b"の場合は[a、||、b]など)を交互に使用するベクトルに格納されます。

私が書いたかのように私のベクトルを連鎖させることが可能かどうか知りたいです:

std::vector<xxx> v = {true, &&, (, false, ||, true, )};
// result = true && (false || true) = true
bool result = vector[0] vector[1] vector[2] vector[3] vector[4] vector[5] vector[6];

算術評価アルゴリズム(操車場など)が存在することは承知していますが、それらの使用を避け、代わりにc++エバリュエーターを使用したいと思います。単純な式を処理するために演算子をオーバーロードできると思いましたが、括弧が表示されるとすぐに行き詰まります。

この質問がすでに質問され、回答されている場合は、お詫び申し上げます。検索で使用するキーワードがわかりません。

事前にありがとう、手がかりだけでもいいでしょう:)

4

5 に答える 5

2

これを行うには、式テンプレートを使用できます。ブールリテラルの一部はbool_(true)、適切な演算子を使用してカスタムオブジェクトを作成するために、のようにする必要がありますが、それを除けば、実際にC++を使用したかのようになります。

もちろん、実行時にツリーをイントロスペクト/変更する必要がない限り、通常はラムダを使用するか、このための関数を作成する方が簡単です。

于 2013-03-06T15:04:27.947 に答える
1

vectorまず、生のC ++演算子や構文要素をどのタイプでも実際に格納することはできないため、(などは使用できません*

ただし、それらをリテラルとして保存できます。

std::vector<std::string> expression = { "2", "+", "3" };

ただし、そのために「c++エバリュエーター」を使用することはできません。C ++はコンパイルされた言語であるため、実行時に同じロジックを使用することはできません(技術的には、LLVMのようなもので可能ですが、間違いなくやり過ぎでしょう)。その場合は、カスタムエバリュエーターを使用することをお勧めします。

TMPを使用したコンパイル時でも可能かもしれませんが、それがあなたの望むものかどうかはわかりません。

于 2013-03-06T14:51:16.220 に答える
1

c ++ソースコードを使用してファイルを生成し、コンパイルして実行できます。このようなもの:

std::vector<xxx> v = {true, *, (, false, +, true, )};
std::ofstream src("temp.cpp");
src <<
    "#include <iostream>\n"
    "int main() {\n"
    "bool result = ";
for (auto i: v)
    src << i << ' ';
src <<
    ";\n"
    "std::cout << result;\n"
    "}\n";
src.close();
system("g++ temp.cpp -o temp");
system("temp");

権限、一時ファイル名、出力リダイレクトなどのさまざまな側面を無視しました。

于 2013-03-06T15:15:24.573 に答える
0

AxelOmegaが言ったように-あなたは使うことができますboost::spirit。文法は非常に単純です。

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/qi_bool.hpp>
#include <boost/spirit/include/phoenix.hpp>

namespace qi = boost::spirit::qi;

template <class Iterator>
struct bool_grammar : qi::grammar<Iterator, bool(), qi::space_type> {
        qi::rule<Iterator, bool(), qi::space_type> rGroup, rBool, rName, rOr, rAnd;

        bool_grammar() : bool_grammar::base_type(rOr) {
                rGroup  = '(' >> rOr >> ')';
                rBool   = qi::bool_ | rGroup;
                rAnd    = rBool[qi::_val = qi::_1] >>
                          *('&' >> rBool[qi::_val = qi::_val && qi::_1]);
                rOr     = rAnd[qi::_val = qi::_1] >>
                          *('|' >> rAnd[qi::_val = qi::_val || qi::_1]);
        }
};

パーサーを呼び出して結果を確認する関数も必要になります

bool parse(const std::string& value) {
        bool_grammar<std::string::const_iterator> g;
        std::string::const_iterator it  = value.begin();
        std::string::const_iterator end = value.end();

        bool s;
        if (qi::phrase_parse(it, end, g, qi::space, s) == false || it != end) {
                // error
        }

        return s;
}

そして今、vectorを1つにマージしてstring、解析関数を使用します。

parse("(true | false) & true | false") ;

bool結果に関心がなく、操作可能なツリーを作成したい場合は、合成された属性をカスタムクラスに変更することもできます。

于 2013-03-06T16:17:45.457 に答える
0

,1つの解決策は、オペレーターをオーバーロードすることです。しかし、これは括弧を扱うときに問題を引き起こします。通常、そのような式を線形解析しても正しい結果は見つかりません。

式を表す通常の方法は、ツリーとしてです。次に、ツリーを走査して最終値を計算します。トラバーサルは通常、再帰を使用して行われます。

つまり、2段階のプロセスです

1:ツリーを構築する

2:式ツリーを再帰的に評価します

グラフとして表示したい場合は、調べてくださいboost::graph

于 2013-03-06T14:48:33.940 に答える