设计思路

首先用一个串来储存使用者所输入的命题表达式,依据人类的思维,会对输入的命题公式进行分析和计算,但计算机可不会,这时我们就要写入相关代码把使用者输入的命题表达式转换为计算机所能进行计算的后缀表达式,我们用计算机进行对数字相关运算时也是这个原理!首先用一个字符串来储存遍历命题表达式所遇到的命题变元,之后遇到操作符时就利用开发者根据C++运算符优先级自定义的操作符优先级函数对操作符的优先级比较来判断操作符是否要压入创建的字符栈,等这些工作都做完了,最终字符栈内储存的就是操作符,而字符串储存的都是变元,然后将字符栈内的操作符全部出栈,储存到字符串中。这样字符串里储存的就是命题公式的后缀表达式,之后要对后缀表达式进行计算!
例:
系统使用者输入的命题表达式为:!p&q|r
经过转化,后缀表达式为:pqr|&!
如果要想计算表达式,首先遍历后缀表达式,然后遇到操作符时,根据它是几元运算符,来对前面的变元进行逻辑运算,比如这里首先遍历到的是|,由于他是二元运算符,这时进行的运算是q|r,那么问题来了,如果把运算符直接出栈进行运算,这时进行的运算就是p|q,这时不符合运算要求的!
所以这时候我们根据栈先进后出的特性,再建造一个数字栈,首先进行储存的是各个变元的真值,这时候可以发现他就解决了前面逻辑运算遇到的问题,之后再根据遇到的操作符类型进行逻辑运算,边出栈边压栈,最终经过计算,数字栈储存的就剩一个数字,这个数字就是该命题公式的真值,最后根据命题表达式的真值和主析取范式用于判断真,主合取范式用于判断假的特性来对用数组对命题公式变元真值的各种情况进行储存,最后根据主范式特性来进行主范式的输出。

重要步骤

  • 操作符优先级的比较
  • 中缀表达式转后缀表达式
  • 字符栈内操作符的储存
  • 数字栈内真值情况的储存
  • 逻辑运算的进行
  • 主范式的输出

实现代码

#include<iostream>
#include<cctype>
#include<set>
#include<string>
#include<stack>
using namespace std;
#define Max 1000
int Array_one[Max][3]={0},Array_two[Max][3]={0},Counter_one=0,Counter_two=0;//储存各个变元的真值,计数器
string s;//串s,储存命题公式
stack<char> Stack;//创建字符栈
stack<int> Num;//创建数字栈
char save[Max],c;//用于储存后缀表达式和临时字符
int follow=0;//计数器
int p,q,r;//用于储存真值
int Amp();//操作符优先级比较函数
void Transform();//中缀表达式转后缀表达式
void fei();//非运算
void yu();//与运算
void huo();//或运算
void tiaojian();//条件运算
void Shuangtiaojian();//双条件运算
void Truenum();//真值运算
void Output_xiqu();//输出主析取式
void Output_hequ();//输出主合取式
int main()
{cout<<"------------------------------------------------欢迎您进入三元逻辑运算系统---------------------------------------------"<<endl;cout<<"变元为p,q,r"<<endl;cout<<"! 非运算,& 与运算,| 或运算,> 条件运算,$ 双条件运算,( 左括号,) 右括号"<<endl;cout<<"请输入命题公式!"<<endl;cin>>s;Transform();cout<<"\t\t\t**真值表**"<<endl;cout<<"p\t\t"<<"q\t\t"<<"r\t\t"<<s<<endl;Truenum();Output_hequ();Output_xiqu();cout<<endl;cout<<"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$第一小组制作$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$"<<endl;cout<<"小组成员:"<<endl;cout<<"$张凯袁$\t"<<"$郭子晗$\t"<<"$王政耀$\t"<<"$彭宪超$\t"<<"$蔺雨菲$\t"<<endl;cout<<"系统创造者————————————☆☆☆郭子晗☆☆☆"<<endl;return 0;
}
int Amp(char a) {switch(a){//由逻辑运算符优先级得到case '(':return 5;break;case '!':return 4;break;case '&':return 3;break;case '|':return 2;break;case '>':return 1;break;case '$':return 0;break;case ')':return -1;break;}
}
void Transform() {for(int i=0;i<s.length();i++) {//遍历命题公式c=s[i];//临时储存字符if(isalpha(c))//如果为字母,后缀表达式直接储存save[follow++]=c;if(c=='!'||c=='&'||c=='|'||c=='>'||c=='$'||c=='('||c==')') {//当为操作符时if(Stack.empty()) Stack.push(c);//字符栈为空,直接压入else if(c!=')') Stack.push(c);//当遍历未读取到右括号时,操作符直接入栈else if(c==')') {//当读取到右括号时while(!Stack.empty()&&Amp(Stack.top())>Amp(c))//当字符栈不为空且栈内操作符优先级大于站外优先级时{if(Stack.top()=='(') break;//读取到左括号时,直接跳出循环save[follow++]=Stack.top();//栈顶操作符储存到后缀表达式中Stack.pop();//操作符出栈}if(Stack.top()=='(') Stack.pop();//当栈顶操作符为左括号时,直接出栈}}}while(!Stack.empty())//输出全部栈内操作符存储到后缀表达式中{save[follow++]=Stack.top();Stack.pop();}
}
void Truenum() {for(p=0;p<=1;p++) {for(q=0;q<=1;q++) {for(r=0;r<=1;r++) {cout<<p<<"\t\t"<<q<<"\t\t"<<r<<"\t\t";for(int i=0;i<follow;i++) {c=save[i];//临时存储字符if(isalpha(c)) {//当为字母变元时,转换为对应的真值switch(c){//真值压入数字栈case 'p':Num.push(p); break;case 'q':Num.push(q); break;case 'r':Num.push(r); break;}}else if(c=='!') fei();else if(c=='&') yu();else if(c=='|') huo();else if(c=='>') tiaojian();else if(c=='$')   Shuangtiaojian();}cout<<Num.top()<<endl;if(Num.top()==1) {//由主析取范式特性进行判断Array_one[Counter_one][0]=p;Array_one[Counter_one][1]=q;Array_one[Counter_one++][2]=r;}else{//由主合取范式特性进行判断Array_two[Counter_two][0]=p;Array_two[Counter_two][1]=q;Array_two[Counter_two++][2]=r;}Num.pop();//最终的命题公式真值出栈}}}
}
void Output_xiqu() {cout<<"主析取式"<<endl;for(int i=0;i<Counter_one;i++) {cout<<"(";if(Array_one[i][0]==0) cout<<"(!p)";else {cout<<"p";}if(Array_one[i][1]==0) cout<<"&(!q)";else {cout<<"&q";}if(Array_one[i][2]==0) cout<<"&(!r)";else {cout<<"&r";}if(i==Counter_one-1) cout<<")";else {cout<<")|";}}cout<<endl;
}
void Output_hequ() {cout<<"主合取式"<<endl;for(int i=0;i<Counter_two;i++) {cout<<"(";if(Array_two[i][0]==0) cout<<"p";else {cout<<"(!p)";}if(Array_two[i][1]==0) cout<<"|q";else {cout<<"|(!q)";}if(Array_two[i][2]==0) cout<<"|r";else {cout<<"|(!r)";}if(i==Counter_two-1) cout<<")";else {cout<<")&";}}cout<<endl;
}
void fei() {//一元操作符,!exprint True=!Num.top(); Num.pop();//弹出一个真值,并出栈Num.push(True);//操作结果压栈
}
void yu() {//二元操作符,Expr&&exprint True_one=Num.top(); Num.pop();//弹出两个真值,并出栈int True_two=Num.top(); Num.pop();int True=True_one&&True_two;Num.push(True);//操作结果压栈
}
void huo() {//二元操作符,Expr||exprint True_one=Num.top(); Num.pop();int True_two=Num.top(); Num.pop();int True=True_one||True_two;Num.push(True);
}
void tiaojian() {//二元操作符,Expr->exprint True_one=Num.top(); Num.pop();int True_two=Num.top(); Num.pop();int True;if(True_one==0&&True_two==1) True=0;else True=1;Num.push(True);
}
void Shuangtiaojian() {//二元操作符,Expr<->exprint True_one=Num.top(); Num.pop();int True_two=Num.top(); Num.pop();int True;if(True_one==True_two) True=1;else True=0;Num.push(True);
}

运行测试

求命题公式的真值表及主范式(栈实现)相关推荐

  1. 离散数学 求命题公式的主析取范式和主合取范式

    Description 输入命题公式的合式公式,求出公式的真值表,并输出该公式的主合取范式和主析取范式. Input 命题公式的合式公式 Output 公式的主析取范式和主合取范式,输出形式为:&qu ...

  2. 离散数学实验报告三——真值表与主范式

    离散数学实验报告三--真值表与主范式 一.预习内容: 1.真值表:把变量的各种可能取值与想对应的函数值,用表格的形式一一列举出来,这种表格就叫做真值表 2.命题公式的析(合)取范式 ⑴文字:命题变元及 ...

  3. [离散数学]命题逻辑P_4:命题公式和真值表

    [离散数学]命题逻辑P_4:命题公式和真值表 前言 1. 命题变元 常值命题定义 例子 命题变量定义 注意 2. 命题公式 定义 关于命题公式的说明 例子 3. 公式的解释 定义 例子 注意 4. 真 ...

  4. 离散数学——用c/c++求命题公式的主范式

    本文借鉴了这篇文章https://blog.csdn.net/DaDaMr_X/article/details/51265230 离散数学又被称为计算机数学,本篇文章就介绍了如何用C++实现求离散数学 ...

  5. 使用C++求命题公式的主析取范式与主合取范式

    最近的离散数学的一个上机作业,要求任意输入一个命题公式,求它的真值表与主析取范式和主合取范式.其中的命题连接词都是用特殊符号来表示(怕麻烦--),并最终选择使用C++来编写程序. 先贴代码: // 五 ...

  6. 用c语言构造真值表,构造命题公式的真值表--biaobiao88

    对给出的任意一个命题公式(不超过四个命题变元),使学生会用c语言的程序编程表示出来,并且能够计算它在各组真值指派下所应有的真值,画出其真值表. #include using namespace std ...

  7. 利用真值表求命题公式A=(p→(q→r))↔︎(r→(q→p))的主析取范式和主合取范式.(10分)

  8. 命题公式的主合取范式C语言,程序设计题: 命题逻辑应用系统

    命题逻辑应用系统 1 问题描述 该系统要求实现命题逻辑中基本算法及其应用系统,包括真值表的计算.主析取和主合取范式的计算.通过此课题,熟练掌握命题公式的计算机表示.命题等价常见算法的实现,实现一个简单 ...

  9. C语言 命题公式真值表

    1.实验目的 掌握命题公式真值表的求解,并实现自动求解程序. 2.实验内容 输入:任意命题公式 输出:该命题公式的真值表 要求: 输入任意命题公式,要求用数据存储命题公式的所有赋值及对应真值,并输出该 ...

最新文章

  1. 这个AI能帮你女朋友自拍:从照片生成3D视频,总有个角度让她满意
  2. oracle if=,oracle中if/else的三种实现方式详解
  3. python是用什么语言开发的-python是什么语言?哪些人适合学习Python?
  4. container_of(ptr, type, member)宏定义解析
  5. DevExpress的TreeList怎样给树节点设置图标
  6. 为什么Docker容器将占领世界
  7. sql表格模型获取记录内容_SQL Server和BI –如何使用Reporting Services 2016记录表格模型
  8. 检测到JSON.NET错误类型的自引用循环
  9. RHEL6.3基本网络配置(4) 其它常用网络配置文件
  10. 新手用手机学黑客编程一秒变黑客
  11. Windows下使用Git+rsync构建文件同步工具
  12. 【美学集】色彩之冷暖色
  13. Hyper-V安装Server 2019虚拟机
  14. 百度输入法android+4.8,百度输入法Android v7.6来了 翻译功能上线助力跨国沟通
  15. 电子设计硬件知识要点(1) 电阻、电容、电感、二极管、三极管
  16. dpi和ppi换算_dpi换算(dpi换算网站)
  17. moviepy截取视频片段的两种方法
  18. arcgis如何打开tif_ArcGIS的目录、内容列表的布局
  19. [WIP] Keystone Federation (by quqi99)
  20. AMD主板解决SATA硬盘识别为可移除硬盘的方式

热门文章

  1. 基于Huffman算法实现文件压缩解压缩(C语言)
  2. MATLAB 将txt文本转化为tif图片格式
  3. 第527篇-Prism学习系列3_Modularity
  4. VR产品为什么没有火起来
  5. 前端开发之字体大小px,em,rem,pt
  6. LeetCode 643 题解
  7. 1、NVIDIA Quadro P600 Linux显卡驱动安装
  8. 贷款买房,利息怎么算?等额本金与等额本息
  9. Thinkadmin v6爆高危漏洞!
  10. 英文和数字组合 正则 密码验证