第一次写博客,新鲜又紧张,写的不好,大犇轻喷。
实现功能 从文本中读取复合命题,并在文本文件中打印真值表
[如果不清楚文本读取,可以先浏览这个博客](https://www.cnblogs.com/uniqueliu/archive/2011/08/03/2126545.html)
简单来说就是用ifstream和ofstream实例化一个对象,并将其与你要操作的文本文件绑定;
ifstream用于从文本里读取数据,它重载了>>;
ofstream用于创建一个文本文件,并将数据输入到改文本里,它重载了<<。
[这里还用到了栈和后缀表达式,不太清楚的可以参考这个博客](https://blog.csdn.net/PaRzVaL/article/details/105360855?tdsourcetag=s_pctim_aiomsg)
#整体思路
由于这里需要对数据进行频繁的随机访问,而且只需要在容器的尾端进行删除和添加的操作,所以这里可以直接使用vector或者指针,
下面的代码是以vector为例实现的
这里支持的逻辑连接词包括析取,合取,否定,蕴含和等价连接词
|表示析取,&表示合取,!表示取反,>表示蕴含,=表示等价
#代码
#include<bits/stdc++.h>
using namespace std;
class Pro
{
private:
vector<char> book_1; //储存子命题
vector<bool> ans; //储存后缀表达式
vector<char> pro_2,pro; //堆栈储存复合命题
bool book_2[20]; //储存子命题对应的布尔变量
string pro_1;
bool contain(bool a,bool b); //自定义蕴含运算
bool equ(bool a,bool b); //自定义等价运算
void star(); //文本处理工作
void add(); //统计子命题及其个数
void put_out(); //对后缀表达式进行运算
void mind(); //对用户指令进行判断
public:
void slove()
{
star();
add();
put_out();
}
};
void Pro::mind()
{
char op;
cin>>op;
if(op=='Y')
{
cin>>pro_1;
}
else if(op=='N')
{
ifstream infile("复合命题.txt");
getline(infile,pro_1);
}
else
{
cout<<"指令错误,请重新输入指令"<<endl;
mind();
}
}
void Pro::star()
{
//此处规定 子命题为小写字母 !为非 &为合取 |为析取 >为蕴含 =为等价
ofstream outfile("复合命题.txt");
outfile<<"!(q|p)>!r&m" ;
outfile.close();
cout<<"!注意 ! 此处规定 自命题为小写字母 !为非 &为合取 |为析取 >为蕴含 =为等价 " <<endl<<endl;
cout<<"目前计算的是: p|!q>r|((!p&!r>q)>r&(q|p&!r)>p|!q>r|)(!p&!r>q)>r&(q|p&!r) 的真值表"<<endl;
cout<<"如果你要自己输入一个复合命题打表 请输入Y 否则输入N"<<endl;
mind(); //判断选择
pro_2.push_back('0');
int i,j,w;
vector<int> a;
for(i=0;i<pro_1.size();i++)
{
//遇到子命题输出 注意运算符的优先级
if(pro_1[i]>='a'&&pro_1[i]<='z')
pro.push_back(pro_1[i]);
else if(pro_1[i]==')')
{
while(1)
{
if(pro_2.back()=='(')
{
a.pop_back();
pro_2.pop_back();
break;
}
pro.push_back(pro_2.back());
pro_2.pop_back();
a.pop_back();
}
}
else if(pro_1[i]=='('||pro_1[i]=='!'||pro_1[i]=='&'||pro_1[i]=='|'||pro_1[i]=='>'||pro_1[i]=='=')
{
switch(pro_1[i])
{
case '(': j=6; break;
case '!': j=5; break;
case '&': j=4; break;
case '|': j=3; break;
case '>': j=2; break;
case '=': j=1; break;
}
//识别到的运算符合栈顶运算符比较优先级
//小于或等于栈顶符号优先级的话,把栈顶运算符输入,再次比较新栈顶运算符
if(a.size())
{
while(j<=a.back()&&a.back()!=6)
{
pro.push_back(pro_2.back());
pro_2.pop_back();
a.pop_back();
if(!a.size())
break;
}
}
a.push_back(j);
pro_2.push_back(pro_1[i]);
}
}
//把所有运算符出栈
while(pro_2.size()&&pro_2.back()!='0')
pro.push_back(pro_2[pro_2.size()-1]),pro_2.pop_back();
}
bool Pro::contain(bool a,bool b)
{
if(a==1&&b==0)
return 0;
else
return 1;
}
bool Pro::equ(bool a,bool b)
{
if((a==1&&b==1)||(a==0&&b==0))
return 1;
else
return 0;
}
void Pro::add()
{
int i,j,k;
bool o=0;
//此处遍历是为了记录共有几个子命题,为赋值做准备
for(i=0;i<pro.size();i++)
{
if(pro[i]>='a'&&pro[i]<='z')
{
for(j=0;j<book_1.size();j++)
{
if(pro[i]==book_1[j])
{
o=1;
break;
}
}
if(o==1)
{
o=0;
continue;
}
else
book_1.push_back(pro[i]);
}
}
}
void Pro::put_out()
{
int i,j,k,l,sum;
bool a,b;
int di,dv;
ofstream myfile("answer.txt");
//此处依次为子命题赋值,并遍历每一种情况
for(sum=0;sum<pow(2,book_1.size());sum++)
{
if(sum==0)
{
for(i=0;i<book_1.size();i++)
{
myfile<<book_1[i]<<" ";
cout<<book_1[i]<<" ";
}
myfile<<"answer"<<endl;
cout<<"answer"<<endl;
}
di=sum;
for(i=0;i<book_1.size();i++)
{
dv=di%2;
di/=2;
if(dv)
book_2[i]=1;
else
book_2[i]=0;
cout<<book_2[i]<<" ";
myfile<<book_2[i]<<" ";
}
//开始计算
for(k=0;k<pro.size();k++)
{
//子命题入栈
if(pro[k]>='a'&&pro[k]<='z')
{
for(l=0;l<book_1.size();l++)
{
if(book_1[l]==pro[k])
{
ans.push_back(book_2[l]);
break;
}
}
}
//运算符出栈
if(pro[k]=='&'||pro[k]=='|'||pro[k]=='>'||pro[k]=='=')
{
a=ans.back();
ans.pop_back();
b=ans.back();
ans.pop_back();
switch(pro[k])
{
case '&': ans.push_back(a&b); break;
case '|': ans.push_back(a|b); break;
case '>': ans.push_back(contain(b,a)); break;
case '=': ans.push_back(equ(b,a)); break;
}
}
if(pro[k]=='!')
{
a=ans.back();
ans.pop_back();
ans.push_back(!a);
}
}
cout<<" "<<ans.back()<<endl;
myfile<<" "<<ans.back()<<endl;
ans.pop_back();
}
cout<<"完成打表";
myfile.close();
}
int main()
{
Pro test_1;
test_1.slove();
return 0;
}
结果