使用双栈实现输出逻辑表达式的真值表

目的:读入一个逻辑表达式,包含多个变量及各种逻辑运算,输出该逻辑表达式的真值表;

思路:

1.与计算多项式的思路一致,利用双栈存储从左到右遍历;

栈具有LIFO的特点,利用栈可以储存离当前操作符最近的符号与数据,从左到右遍历,直到最终得出表达式的值;

2.两个栈一个存储符号,一个存储数据,设置栈内栈外符号位的优先级;

相同符号栈内优先级大于栈外优先级;

左括号栈内优先级最高,栈外优先级紧大于‘#’;

右括号与左括号相反;

将‘#’优先级设为最低,放入栈底,方便比较并判断终止条件;

3.每次读入一位,若为数据入数据栈;若为操作符,进行优先级比较

当栈内运算符优先级大于栈外运算符优先级,执行运算;

当栈内运算符优先级等于栈外运算符优先级,必为左右括号,弹出左括号;

当栈内运算符优先级小于栈外运算符优先级,将该符号入栈;

代码实现:

#include <iostream>
#include <iomanip>
#include <stdio.h>
#include <stdlib.h>
#include <cstring>
#include <algorithm>
#include <stack>
#include <map>
#include <cmath>
using namespace std;
int num[10];//按位存储生成的二进制码
int letter_num;//全局变量存储表达式中变量数目
map<char,int> m;//用map将字符与数字绑定,方便对应
char letter[10];//储存所有字符变量
char relation[256];//储存关系表达式
int show[100];//记录变量是否出现
int in[]={3,3,3,3,4,1,5,0};//栈内优先级
int out[]={2,2,2,2,4,5,1,0};//栈外优先级
char symbol[]={'^','V','>','<','~','(',')','#'};//储存操作符
int get(char x);//返回操作符对应下标
void get_num(int x);//更新按位二进制表示
int get_letter_num(char *);//统计并储存变量
char com(char x1,char x2);//比较优先级
bool if_variable(char x);//判断当前字符是否为变量
void print_truth_table(char *);//打印真值表
int figure(int x1,int rel,int x2);//计算基本表达式值
int main()
{
    cin>>relation;
    print_truth_table(relation);
    return 0;
}


void print_truth_table(char* top)
{
    int sum;
    char* y;
    int x,x1,x2;
    char rel;
    stack<int> data;//存储数据
    stack<int> ope;//存储操作符
/*初始化*/
    memset(show,0,sizeof(show));
    memset(letter,0,sizeof(letter));
    memset(num,0,sizeof(num));

    ope.push(get('#'));
    y=top;
    x=get_letter_num(top);
    x=(int)pow(2,x);//对应于2^x数的真值表


/*打印表头*/
    for(int i=0;i<=letter_num;i++)
    {
        if(i==letter_num)
        {
            printf("%-10s\n",relation);
            for(int j=0;j<=letter_num;j++)
                cout<<"----------";
            cout<<endl;
            continue;
        }
        printf("%-10c",letter[i]);
    }


    while(x--)
    {
        top=y;//保存头指针,每次遍历完需重置
        get_num(x);//更新二进制表示
        int index=ope.top();
        while(*top||index!=7)
        {
            sum=0;
            if(*top=='-')
                top++;
            if(*top=='~')//取非将4压入操作栈
            {
                ope.push(4);
                top++;
            }
            if(*top=='<')//若为等价符另右移两位
            {
                ope.push(get(*top));
                top+=3;
            }
            if(if_variable(*top))//压入变量值
            {
                sum=m[*top];
                data.push(sum);
                top++;
            }
            else//符号操作
            {
                switch(com(symbol[ope.top()], *top))
                {
                case 1://'>'
                    if(ope.top()==4)//取反单独计算
                    {
                        x1=data.top();
                        data.pop();
                        x1=(x1+1)%2;
                        data.push(x1);
                        ope.pop();
                        break;
                    }
                    x1=data.top();
                    data.pop();
                    x2=data.top();
                    data.pop();
                    rel=ope.top();
                    ope.pop();
                    data.push(figure(x1,rel,x2));
                    break;
                case 2://'<'
                    ope.push(get(*top));
                    if(*top)
                        top++;
                    break;
                case 3://'='
                    ope.pop();
                    if(*top)
                        top++;
                    break;
                }
            }
            index=ope.top();
        }

/*打印结果*/
        for(int i=0;i<=letter_num;i++)
        {
            if(i==letter_num)
            {
                printf("%d\n",data.top());
                data.pop();
                continue;
            }
            printf("%-10d",num[i]);
        }
    }
    return ;
}


void get_num(int x)
{
    for(int i=letter_num-1;i>=0;i--)
    {
        num[i]=x%2;
        m.erase(letter[i]);
        m.insert(make_pair(letter[i],num[i]));
        x/=2;
    }
    return ;
}

int get(char x)
{
    switch(x)
    {
    case '^':
        return 0;
    case 'V':
        return 1;
    case '>':
        return 2;
    case '<':
        return 3;
    case '~':
        return 4;
    case '(':
        return 5;
    case ')':
        return 6;
    case '#':
        return 7;
    default:
        return 7;
    }
}

int get_letter_num(char *x)
{
    letter_num=0;
    while(*x)
    {
        switch(*x)
        {
        case '^':
        case 'V':
        case '>':
        case '<':
        case '(':
        case ')':
        case '#':
        case '-':
        case '~':
            x++;
            break;
        default:
            if(!show[(int)*x])
            {
                letter[letter_num]=*x;
                letter_num++;
                show[(int)*x]=1;
            }
            x++;
            break;
        }
    }
    return letter_num;
}

char com(char x1,char x2)
{
    int i1=get(x1);
    int i2=get(x2);

    if(in[i1] > out[i2])
        return 1;
    else if(in[i1] < out[i2])
        return 2;
    else
        return 3;
}

bool if_variable(char x)
{
    switch(x)
    {
    case '^':
    case 'V':
    case '>':
    case '<':
    case '(':
    case ')':
    case '#':
    case '\0':
        return false;
    default:
        return true;
    }
}

int figure(int x1,int rel,int x2)
{
    switch(rel)
    {
    case 0:
        return x1&&x2;//与
    case 1:
        return x1||x2;//或
    case 2:
        return x1||!x2;//蕴含
    case 3:
        return (!x1&&!x2)||(x1&&x2);//等价
    }
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值