所以我有一个方程((c +〜d)* b)*〜(d + a * e)我试图生成一个真值表,但是我不确定我该如何开始程序根据真值表计算变量是否应为true或false。有什么建议吗?预先谢谢你。
#include<iostream>
using namespace std;
bool checkBoolTF(int a){
bool TF;
if(a == 0){
TF = false;
}
else{
TF = true;
}
return TF;
}
int main()
{
int a,b,c,d,e;
bool aBool, bBool, cBool, dBool, eBool;
string equation = "(( c + ~d ) * b ) * ~( d + a * e )";
bool equationTF;
//LOOP TO TRUTH TABLE - FINAL VALUES
cout << "----------------------------------------------------------------------" << endl;
cout << "| a | b | c | d | e | " << equation << " |" << endl;
cout << "----------------------------------------------------------------------" << endl;
for(a=0;a<=1;a++){
checkBoolTF(a);
for(b=0;b<=1;b++){
checkBoolTF(b);
for(c=0;c<=1;c++){
checkBoolTF(c);
for(d=0;d<=1;d++){
checkBoolTF(d);
for(e=0;e<=1;e++){
checkBoolTF(e);
cout << "| " << a << " | " << b << " | " << c << " | " << d << " | " << e << " | " << equationTF << " |" << endl;
cout << "----------------------------------------------------------------------" << endl;
}
}
}
}
}
return 0;
}
答案 0 :(得分:2)
第1步:令牌化。
enum class TokenType {
bracket, binop, binaryop, var, literal
};
struct Token {
TokenType type;
char value;
};
将字符串转换为向量token
。
您尚未使用literal
:它是0或1的值。稍后将使用它。
写出漂亮的标记向量的写代码。
第2步:制作一棵简单的树。
struct Tree {
bool is_token=true;
Token token;
std::vector<Tree> tree;
};
更改您的第一个代码以生成包含令牌向量的树。
写出漂亮的代码。测试。
第3步:缩小树
第3a步:括号
现在执行还原步骤;走一棵树的矢量并生成一个。它将不是括号的所有内容都盲目地复制到输出中。如果看到(
,它会将所有内容复制到 matching )
(计数打开和关闭)直到一个子树,然后将该子树复制到输出中。 / p>
先将"a ( b c )"
放在子树中,然后使其a
然后b c
。
编写可以漂亮地打印子树的代码。测试。
第3b步:嵌套的括号
下一步,递归到您创建的子树上,这样它的嵌套括号也将放入子树中。
第3c步:运算符
接下来,对运算符进行操作。 ~
很简单:它吞没了向量中的下一棵树。当+
绑定失败者比*
时,对于每个+
都要建立两个子树。一个为之前的一切,一个为之后的一切。然后对*
进行一次dping操作。
这一切之后,您转身
a+(b+c)*~(d+e)
进入
+ (a , ( * (+ (b, c), ~(+(d,e))))
第4步:替代
映射将变量映射到值的std::map
。取一棵树的副本,然后遍历它,用等于其值的文字替换每个变量。
第5步:评估
对于每个运算符,请评估子树,然后应用该运算符。
结果应为0或1。
4和5可以通过直接使用文字表达式来独立完成。
答案 1 :(得分:1)
所以我有一个个人程序,该程序为带有格式的字符串实现此功能
"Ab|c(d|E)|fa"
我的完整源代码完全是一团糟,并且包含我尝试同时做的其他一些事情(无法通过绕过kmap和其他东西来简化表达式)
但是,如果有帮助,我可以逐步完成我所做的事情
它的设置对于我来说更容易解析,大写字母表示正负小写字母,表示否定/不是()表示子表达式,而[]表示否定的子表达式 因此输入字符串““ ABC(DEF)G(HI(KK)S [as] [ge])S”将转换为此.repr()结构
AND(
A
B
C
AND( D E F )
G
AND(
H
I
AND( K K )
S
NAND( !A !S )
NAND( !G !E )
)
S
)
"Ab|cb"
之类的是
OR(
AND( A !B )
AND( !C !B )
)
我有一个对象(称为表达式),该对象包含有关其类型的信息,存储在以下类似内容中
namespace xpr { //expression types
enum typ {
identity_,
negation_,
and_,
or_,
nand_,
nor_
};
}
class expression{
...
xpr::typ type = xpr::identity_;
char value = ' ';
std::vector<expression> sub_expressions;
...
};
以及作为其值的char或表达式的向量。 (和/或也不是nand表达式)
通过嵌套的构造函数将其解析为这种表达式形式,这些构造函数会不断传递字符串中的当前位置及其级别。
最后回答您的问题
std::vector<char> vars = trackUsed();
// equivalent to a set but more efficent to do the sort/unique at the end one time.
removeDuplicates(vars);
const auto truth_table_width = vars.size();
const auto truth_table_size = (size_t)std::pow((size_t)2, truth_table_width); // 2^width
expression::test_type test; // abc through !a!b!c
test.reserve(truth_table_width);
for ( const auto &v : vars ) {
// value_type is value: 6, sign: 2 so character has to fit in 6bits and sign in 2.
// minus 'A' to make A-Z 0-26
test.emplace_back(v - 'A', xpr::negative);
}
for ( size_t i = 0; i < truth_table_size; i++ ) {
for ( size_t j = 0; j < truth_table_width; j++ ) {
// converts 0 to negative and 1 to positive
test[j].sign = (xpr::sign_type)((i >> j) & 0x1);
}
bool valid = testValues(test);
if ( valid ) {
sum_of_products.push_back(test);
}
}
我通过提取所有用于删除重复项并对其进行排序的字符来设置真值表。制作vector
// given A true B true C true see if whole expression evaluates to true.
bool expression::testValues(const potion::test_type& values) const {
if ( this->is_simple() ) {
auto val = std::lower_bound(values.begin(), values.end(),
this->value,
[ ](potion::val_type lhs, char rhs) -> bool {return lhs < rhs; }
);
if ( type == xpr::identity_ ) return (*val).sign;
if ( type == xpr::negation_ ) return !(*val).sign;
}
if ( type == xpr::and_ || type == xpr::nand_ ) {
const bool is_and = type == xpr::and_; //used to combine and and nand expressions and return the oposite val for nand
for ( const auto& e : sub_expressions ) {
if ( e.testValues(values) == false ) return !is_and; // short circuit- if b is false then abc is false
}
return is_and;
}
if ( type == xpr::or_ || type == xpr::nor_ ) {
const bool is_or = type == xpr::or_; //used to combine or and nor and return the oposite val for nor
for ( const auto& e : sub_expressions ) {
if ( e.testValues(values) == true ) return is_or; // short circuit- if b is true then a|b|c is true
}
return !is_or;
}
throw std::runtime_error("Expression can't be simplified. Type not valid"); //should never happen
return false;
}
显然有很多样板代码/解析代码可能不是最好的。如果要使用“自定义语言”解析字符串,则要定义“((c +〜d)* b)*〜(d + a * e)” 那么解析代码显然会大不相同。
无论如何,我希望这对您的项目有帮助。 TLDR:可能比您最初想象的要难一些。尽管我所做的一切都是正常的,但是代码并不是最干净的,并且针对我的具体情况进行了繁重的设置-仅获取具有肯定意义的真值表条目并将其存储在可以进一步处理的总和中。>
答案 2 :(得分:0)
首先,您可以将checkBoolTF函数简化为:
bool checkBoolTF (int a)
{
return !(a==0);
}
第二,似乎在for循环中,此函数返回的值未分配给任何东西,因此丢失了。因此,您可能想定义一个aux变量:
bool auxA = checkBoolTF(a);
以此类推。
答案 3 :(得分:0)
我想展示另外一个已经存在的解决方案。它具有良好的结构和评论。它在github上发布。请参阅here
该程序的预期目的是计算MCDC测试对。但这当然也满足您的所有需求。我不建议您复制并粘贴,但是您可以阅读和学习如何执行。
此代码精确地读取您指定的字符串。它还创建一个真值表。但这只是整个功能的一小部分。
因此,您需要做的是将字符串编译为可以评估为布尔表达式的内容。
为此,我首先定义了输入字母和语言,并通过语法进行了描述。然后,我创建了一个编译器,由扫描器(词法分析器),解析器和代码生成器组成。实际上,我创建了2个具有相同前端和2个不同后端的编译器。因此,有2个不同的代码生成器。一种,对于可以对输入变量的任意组合评估布尔表达式的虚拟机。并且,第二个后端将创建一个抽象语法树,我将使用该语法树评估所有可能的MCDC测试对。
如上所述,第一个代码生成器为虚拟机创建Op代码。使用此机器,可以计算真值表以及所有最小项。然后使用Quine和McCluskey(2种不同的实现)来最小化布尔表达式。最后,采用Petricks方法的优化版本来解决统一覆盖问题并确定最小素数蕴涵集。
MCDC部分可能有点太复杂,无法在此处进行解释。
但是主要的信息是,您首先需要解析字符串并将其转换为可执行文件。
然后,您可以评估任何内容。