📄 ccj2.cpp
字号:
#include <string>#include <fstream>#include <iostream>using namespace std;const int H=15;//定义二维数组,用于存放决策表Sconst int L=15;void main(){ int row=0,len=0;//用于存放读入文件中数据的行数和列数 int hang,lie,i; char chr; string juecebiao[H][L];//定义一个二维的决策表S string juecebiao_bak[H][L];//定义一个二维的决策表S备份 string str,core,fbfun="";//fbfun用于存放分辨函数,core为核 void fenbian(int hs,string table[][L],int hsh,int lsh,string &fun);//申明分辨函数 void yuejian(int m,string core,string &fun);//申明约简函数 void delrongyu(string &fun);//申明消除冗余函数 void yuejiantable(string strs,string juece[][L],string juecetable[][L],int lieshu,int hangshu); //申明构建约简后的表S',并推导出规则式 ifstream infile("juece.txt");//打开输入文本文件 ifstream infile2("juece.txt"); infile>>noskipws;//不忽略空白,把每行最后那个'\n'也读进来 if(!infile)//文件打开出错检查 { cout<<"open file error!"<<endl; exit(0);//出错退出 } while(infile>>chr) //将输入文件读入到决策表S中,判断该表的行数和列数 //文件中每列数据以逗号分隔开 { switch(chr) { case '\n'://判断读入字符是否为换行符 ++row;//是换行符则行数+1 len=0;//是换行符则列数清零 break; case ','://判断读入字符是否为逗号 ++len;//则列数+1 break; default:; } }//判断完毕 infile.close();//关闭文本文件 row++;len++;//row,len中保存的值为从外部文件导入的决策表的行数和列数 if(!infile2)//文件打开出错检查 { cout<<"open file error!"<<endl; exit(0);//出错退出 } hang=0;lie=0;//行、列赋值为1。0行、0列存储其他值用 while(hang<row)//循环比较,以行数作为限制 { while(lie<len-1) { getline(infile2,str,',');//以逗号为分隔对象,进行数据读入 juecebiao[hang][lie]=str;//将逗号前的数据保存到相应的字符串数组中 lie++;//保存好数据后列数+1 } getline(infile2,str,'\n');//将回车符作为对象进行数据输入,以判断一行是否结束 juecebiao[hang][lie]=str;//将回车符前面的数据读入到相应的字符串数组中 lie=0;//列数赋值为1,准备下一行的判断 hang++;//行数+1 } infile2.close(); for(hang=0;hang<row;hang++)//由于决策表S后面有变动,所以先予以保存在juecebiao_bak中 for(lie=0;lie<len;lie++) juecebiao_bak[hang][lie]=juecebiao[hang][lie]; cout<<"引入的决策表为:\n"; cout<<"-------------------------------------------------------------------------------\n"; for (lie=0;lie<len;lie++) cout<<juecebiao[0][lie]<<"\t"; cout<<"\n-------------------------------------------------------------------------------\n"; for (hang=1;hang<row;hang++) { for (lie=0;lie<len;lie++) cout<<juecebiao[hang][lie]<<"\t"; cout<<"\n"; } cout<<"-------------------------------------------------------------------------------\n\n"; juecebiao[0][0]="U";//为方便运算,将属性列的值改变成a,b,c……等简单字母表示 chr='a'; for(i=1;i<len;i++) { juecebiao[0][i]=chr; chr+=1; } chr='1'; for(i=1;i<row;i++) { juecebiao[i][0]="U"; juecebiao[i][0]+=chr; chr+=1; } cout<<"生成的分辨矩阵为:\n-------------------------------------------------------------------------------\n "; for (lie=1;lie<row;lie++) { cout<<"\t"<<juecebiao[lie][0]; } cout<<"\n-------------------------------------------------------------------------------\n"; for (hang=1;hang<row;hang++) { cout<<juecebiao[hang][0]; fenbian(hang,juecebiao,row,len,fbfun);//调用分辨矩阵函数,显示构造分辨矩阵的一行元素 cout<<"\n"; } cout<<"-------------------------------------------------------------------------------\n"; cout<<"\n对应的分辨函数为:\n"; cout<<"△="<<fbfun<<endl;//输出显示分辨函数P for(lie=0;lie<fbfun.length();lie++)//寻找单独的一个元素,此元素为核。 //也可以先求约简,再求约简的交集,其元素也为核 { if(fbfun[lie]!=')')//先寻找右括号 continue; if(fbfun[lie-2]=='(')//判断右括号前二个元素是否为左括号,是则表示两括号间只有一个元素 core+=fbfun[lie-1];//把此元素存放到core中保存 }//求核完毕 for(i=0;i<core.length();i++)//将核元素依次传个约简函数,依次进行约简 yuejian(i,core,fbfun);//调用约简函数,将核元素、分辨函数作为参数传递过去得到约简后的函数 delrongyu(fbfun);//调用消除冗余函数,将上步得到的函数消去冗余值 cout<<"="<<fbfun; cout<<"\n\n所以该表达式的约简为:"; str=""; for(i=0;i<fbfun.length();i++)//显示根据分辨函数运算得来的几个约简 { while(fbfun[i]>='A'&&fbfun[i]<='z'&&i<fbfun.length()) { str+=fbfun[i]; i++; continue; } str="{"+str+"} "; i++; cout<<str; str=""; } cout<<endl; cout<<"\n约简的核为:"<<core<<"\n"; for(i=0;i<len;i++) juecebiao[i][0]=juecebiao[0][i];//将决策表S的属性列存放到表S的0列,以备后用 i=0; while(i<=fbfun.length())//将计算后得到的最终分辨函数,依次取其中的析取项,传入约简函数 //为和决策属性一起,求出规则 { if(fbfun[i]>='A'&&fbfun[i]<='z') { str+=fbfun[i]; i++; continue; } else { yuejiantable(str,juecebiao,juecebiao_bak,len,row);//取析取式中每组元素,调用构造约简表函数 str=""; i+=2;//跳过析取符号 continue; } } cout<<"-------------------------------------------------------------------------------\n"; cout<<"规则式已输出到文本文件result.txt中\n\n";}void fenbian(int hs,string table[][L],int hsh,int lsh,string &fun)//定义分辨矩阵,并输出显示分辨函数{ int m,flag,hangs;//flag是判断是否有左括号的标志位 string str; for(m=1;m<=hs;m++)//分辨矩阵是对称矩阵,本程序显示上三角部分,下三角部分以制表符跳过 cout<<"\t"; cout<<"\t";//a∈C:f(xi,a)=f(xj,a)时a=Ф。所以对角线上的元素为空,以制表符跳过 hangs=hs+1;//比较(xi,a)与(xj,b),i<j<n //从该行开始与其下方各行元素比较,上方元素因为对称性不用再作比较。所以hangs初始化为hs+1 while(hangs<hsh) { flag=0;//初始化标志位,0为无,1为有 str="";//将接收缓冲区清空,以便下面程序能够分辨出每组元素是否为空。为空则不输出显示括号 for(m=1;m<lsh-1;m++)//此时m为属性列计数,不用比较决策属性 { if((table[hs][m]==table[hangs][m])||(table[hs][lsh-1]==table[hangs][lsh-1])) continue;////a∈C:f(xi,a)≠f(xj,a) 当f(xi,D)≠f(xj,D)时,否则为空 str=table[0][m];//将该列属性元素存入str中 cout<<str; if(str!=""&&flag==0)//当缓冲区里有接收到的属性值,并且已经有左括号了,则执行 { if(fun[fun.length()-1]==')')//在准备输出显示左括号前先判断前一个字符是否为右括号 fun+="∧";//是有括号,则输出显示合取符号 fun+="(";//将左括号添加到分辨函数中 flag=1;//当输出显示左括号时,将flag标志位置1,表示已有左括号了 } if(fun[fun.length()-1]!='(')//若前面一个字符不是左括号,则一定是属性值,则输出显示析取符号 fun+="∨"; fun+=str;//将得到的属性值添加到分辨函数中 } hangs++;//行数+1,进行下一行的比较 if(flag==1)//判断是否有坐括号 fun+=")";//有左括号则将右括号添加到分辨函数中 cout<<"\t"; }}//构造完毕void yuejian(int m,string he,string &fun)//定义约简函数,对分辨函数进行约简{ int lkuohao=0,rkuohao=0,n,p;//lkuohao,rkuohao为左、右括号标志符 string str="",str2="";//str用来保存每组元素,str2用来保存比较后的元素 for(n=0;n<fun.length();)//对分辨函数进行一次从左到右的筛选,去处与核交集≠Ф的每组元素 //约简原则:根据吸收律,P∨(P∧Q)<=>P,P为核 { if(fun[n]=='(')//以左括号为判断每组元素开始的标记 { lkuohao=n;//将左括号的下标保存下来,与后面右括号下标一起构成括号内元素取得的标志 n++;//进行下一个元素的比较 continue; } if(fun[n]==')')//遇到右括号,则表示一组元素已经取得 { rkuohao=n;//将右括号的下标保存下来 for(p=0;p<str.length();)//对此组元素依次进行比较,是否与核相同 { if(str.length()==1)//若取得元素长度为1,则为核。不比较,保存下来
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -