C/C++实现对输入的命题条件表达式输出其所有成真赋值

整理东西发现早先用C/C++写的一份代码,用到了栈数据结构,想想应该可以贴出来。主要目的是输入命题,然后输出所有的成真赋

程序需要实现输入一个条件表达式,输出其所有成真赋值。
程序分为两个部分,一个是检查输入的表达式以及命题是否正确及匹配。一个是核心代码,用于求结果。根据命题个数得出不同赋值方式的的个数(认为是一组二进制数,因此以十进制保存,即若有三个命题则从 0 ~ 23 -1)再代入表达式,即以栈的数据结构对表达式求值。表达式求值规则为,数值全部入栈,符号优先级大于栈顶的入栈,反之出栈运算,将结果再入栈。最终结果若为0则将其标记。一个条件判定结束后,对下一个条件做相同的判定,已经被标记的赋值方式不再代入计算。当所有条件判定结束后,即可输出结果。

#include <iostream>
#include <stdlib.h>//   system("cls");函数所在的库 
#include <string> 
#include <stack>//STL
using namespace std;

class Check
//条件检测类,构造函数输入命题,SetCon(string s)输入条件
//Condition_Check()检测函数,正确返回true,错误返回false 
{
    string con;//条件 
    string pro;//命题 
public:
    Check(string s)//输入命题 
    {
        pro = s;    
    }

    void SetCon(string s)//输入条件 
    {
        con=s;
    }

    bool Word_Check()//判断命题是否为字母
    {
        for(int i=0;pro[i];i++)
            if(!(pro[i]>='a' && pro[i]<='z' || pro[i]>='A' && pro[i]<='Z'))
                return false;
        return true;
    }
    bool Pro_Check(char ch)//命题检测,ch是否为命题之一
    {
        for(int i=0;pro[i];i++)
            if(ch==pro[i])
                return true;
        return false;
    }
    bool Double_Sigh(char ch)
    {
        if(ch=='|' || ch=='&' || ch=='>' || ch=='=')
            return true;
        return false;
    }
    bool Condition_Check()//条件检测,判断是否符合条件
    {
        if(!Word_Check())//判断命题是否为字母
            return false;
        int left = 0,right = 0;
        for(int i=0;con[i];i++)
        {
            if( !Pro_Check(con[i]) && !Double_Sigh(con[i]) && con[i]!='!' && con[i]!='(' && con[i]!=')' )//是否为命题或符号 
                return false; 
            if(!Pro_Check(con[i]))//不是命题则进入 
            {
                if( i>0 && con[i]=='!' && ( Pro_Check(con[i-1]) || con[i-1]==')' ))//!之前不为 命题和 ) 
                    return false;
                if( con[i+1] && con[i]=='!' && ( Double_Sigh(con[i+1]) || con[i+1]== ')' ))// ! 之后不为 | & > = ) 
                    return false;
                if( i>0 && Double_Sigh(con[i]) && ( Double_Sigh(con[i-1]) || con[i-1]=='(' ))// | & > = 前不为 | & > = (
                    return false;
                if( con[i+1] && Double_Sigh(con[i]) && ( Double_Sigh(con[i+1]) || con[i+1]==')' ))// | & > = 后不为 | & > = )
                    return false; 
                if( i>0 && con[i]=='(' &&  (Pro_Check(con[i-1]) || con[i-1] == ')' ))//( 前不为 命题和)  之后的问题在上面已经判断 
                    return false;
                if( con[i+1] && con[i]==')' && Pro_Check(con[i+1]) )
                    return false;
                if(con[i]=='(')left++;
                if(con[i]==')')right++;
            }

        }
        if(left!=right)//左右括号个数的比较,括号进一步判配置于栈运算时 
            return false;
        return true;
    }
};

int Calculate(int a , char op , int b = 0)//计算函数,单目运算省略第三个参数 
{
    switch(op)
    {
        case '!':return !a;
        case '&':return a&&b;
        case '|':return a||b;
        case '>':return !a||b;
        case '=':return a==b;
    }
}

char Precede(char a, char b)//a为栈顶符号,b为待入栈符号 
{
    int i,j;  
    char pre[][8]={           
    /*运算符之间的优先级制作成一张表格*/  
        {'>','>','>','>','>','<','>','>'},      
        {'<','>','>','>','>','<','>','>'},  
        {'<','<','>','>','>','<','>','>'},  
        {'<','<','<','>','>','<','>','>'},  
        {'<','<','<','<','>','<','>','>'},  
        {'<','<','<','<','<','<','>','0'},
        {'>','>','>','>','>','0','>','>'}, 
        {'<','<','<','<','<','<','0','='}};  
    switch(a){  
        case '!': i=0; break;
        case '&': i=1; break;  
        case '|': i=2; break;  
        case '>': i=3; break;  
        case '=': i=4; break;  
        case '(': i=5; break;  
        case ')': i=6; break;  
        case '#': i=7; break;  
    }  
    switch(b){  
        case '!': j=0; break;
        case '&': j=1; break;  
        case '|': j=2; break;  
        case '>': j=3; break;  
        case '=': j=4; break;  
        case '(': j=5; break;  
        case ')': j=6; break;  
        case '#': j=7; break;  
    }  
    return pre[i][j];  
}  

int FindNum(char ch,string pro) //如果是命题就返回下标 否则返回-1 
{
    for(int i=0; pro[i] ; i++)
        if(pro[i] == ch)
            return i;
    return -1;
}

int main()
{
    string str,pro;
    int i,j,k,l,n,m,x,y;
    int START = 1; //循环标志位 以及 错误标志位 
    int *a;//存放命题的值 
    bool *flag;//结果
    char ch;
    string *name;
    stack <int> num;//数值栈(命题)
    stack <char> op;//符号栈 
    op.push('#');//符号栈预读# 
    do{
        cout<<"----------------------------离散数学实验一----------------------------"<<endl;
        cout<<"|                                                                     |"<<endl;
        cout<<"| 能够识别的运算符有 非! 且&  或|  蕴含>  等价=  请勿输入错误运算符  |"<<endl;
        cout<<"|                   命题范围为26个字母,支持大小写                    |"<<endl;    
        cout<<"|         本程序有表达式查错功能,但是请尽量输入正确的表达式          |"<<endl;       
        cout<<"|                         本程序使用DEV-C编写                         |"<<endl;             
        cout<<"|              尽量不要输入中文,编码不支持容易出现乱码               |"<<endl;      
        cout<<"|                                                                     |"<<endl;
        cout<<"----------------------------------------------------------------------"<<endl;
        cout<<"-问题描述:某科研所要从一些人中挑选一部分人出国进修。由于工作需要,仅选派符合条件的人。"<<endl;
        cout<<"-请输入简单命题个数: ";
        cin>>n;
        name = new string[n];//存放名字 
        a = new int[n];  //存放命题的值,下标对应命题下标 
        flag = new bool[1<<n]; //判断结果0 ~ (1<<n)-1      
        for(i=0;i<1<<n;i++)flag[i]=true;//初始化flag
        cout<<"-请输入命题,格式为 命题<空格>名字<回车>"<<endl;
        for(i=0;i<n;i++)            
            cin>>pro[i]>>name[i];//输入命题和名字              
        pro[i] = 0;//字符串最后0结束符 
        Check check(pro);
        cout<<"-请输入条件个数: ";
        cin>>m;
        for(i=1;i<=m;i++)// 处理每个条件
        {
            cin>>str;
            check.SetCon(str);//输入条件到检测对象中 
            if(check.Condition_Check())//检测条件是否符合规则 
            {
                for(j = 0 ; j < 1<<n ;j++)//循环判断出正确结果 
                {
                    while(!num.empty()) num.pop();//清空栈 
                    while(op.top()!='#')op.pop();//清空栈
                    //程序运行正常的情况下这两句不会运行 
                    l = j;
                    for(k=n-1;k>=0;k--)//把数值放入数组a中 
                    {
                        a[k]=l%2;
                        l/=2;
                    }
                    for(k = 0 ; str[k] ; k++)
                    {
                        x = FindNum(str[k],pro);
                        if( x != -1 ) //数值入栈 
                        {
                            num.push(a[x]);
                        }
                        else
                        {
                            ch = op.top();
                            if( str[k] == ')' )//如果是右括号则不进栈,持续出栈直到左括号
                            {
                                op.pop();
                                while(ch!='(')
                                {                       
                                    y = num.top();
                                    num.pop();
                                    if(ch == '!')
                                    {
                                        num.push( Calculate(y,ch) );
                                    }
                                    else
                                    {
                                        x = num.top();
                                        num.pop();
                                        num.push( Calculate(x,ch,y) );
                                    }                                   
                                    ch = op.top();
                                    op.pop();   
                                }
                            } 
                            else if( Precede(ch,str[k]) =='<' )//待入栈的优先级高于栈顶,就入栈 
                            {
                                op.push(str[k]);
                            }
                            else if( Precede(ch,str[k]) =='>' )//待入栈的优先级低于栈顶,就出栈 
                            {               
                                y = num.top();
                                num.pop();
                                if(ch == '!')
                                {
                                    num.push( Calculate(y,ch) );
                                }
                                else
                                {
                                    x = num.top();
                                    num.pop();
                                    num.push( Calculate(x,ch,y) );
                                }
                                op.pop();
                                op.push(str[k]);
                            }                       
                        }
                    }
                    ch = op.top();  
                    while(ch!='#')
                    {           
                        op.pop();           
                        y = num.top();
                        num.pop();
                        if(ch == '!')
                        {
                            num.push( Calculate(y,ch) );
                        }
                        else
                        {
                            x = num.top();
                            num.pop();
                            num.push( Calculate(x,ch,y) );
                        }                                   
                        ch = op.top(); 
                    }
                    if(num.top()==0)//结果不符合要求,标记为false 
                    {
                        flag[j] = false;
                    }
                    num.pop();                  
                }
            }
            else//错误条件结束本次实验 
            {
                START = 0; 
                break;
            }
        }
        if(START)
        {
            for(i=1,j = 0 ; j < 1<<n ; j++)
            {           
                if(flag[j])
                {
                    cout<<"Case"<<i<<":"<<endl; 
                    i++;
                    l = j;
                    for(k=n-1;k>=0;k--)//把数值放入数组a中 
                    {
                        a[k]=l%2;
                        l/=2;
                    }
                    for(k=0;k<n;k++)
                    {
                        if(a[k]==1)
                            cout<<name[k]<<" :去 ";
                        else  
                            cout<<name[k]<<" :不去 ";
                        cout<<endl;
                    }
                }
            }
            if(i==1)
                cout<<"------------NO CASE------------"<<endl;
        }
        else
            cout<<"-输入错误!"<<endl;
        delete []a;
        delete []flag;
        cout<<"-还要继续吗?输入1继续,输入0结束"<<endl; 
        cin>>START;
        system("cls");
        if(!START)
        {
            cout<<"-结束。。。"<<endl; 
        }
    }while(START);
    return 0;
} 

这里写图片描述

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值