逻辑表达式化为真值表

来源:互联网 发布:御马脚垫 知乎 编辑:程序博客网 时间:2024/05/21 09:59
这个处理方法和多项式的处理方法一样。试着写了一下,发现自己对栈的应用能力还是不够,不过很感谢

supermary863的博客http://blog.csdn.net/supermary863/article/details/6363570。

然后模仿着把这个离散实验作业完成了。可能存在一些小问题,但是总体思路就是那样吧。

/*程序设计类似与多项式的计算,用双栈来实现,完成<任意个>变量的表达式的运算*//*变量请统一用小写字母*//*目前支持的逻辑运算符有~(非),V(析取,用大写字母V),^(合取,用shitf + 6), 以及->(蕴含)。没有添加<->(只是多添加一个操作符,优先级同->,同理,有兴趣的读者可以自己实现)*//*程序运行方式见main函数入口。*/#include <iostream>#include <string>#include <cstring>#include <cstdio>#include <stack>using namespace std;class TrueFalseTable{protected:    string read;    //限定表达式变量为小写字母。    char x[10];     //存储变量。    int x_num;      //变量数。    int value[10]; //下标对应变量的值0或1。    int Ans;    //每行真值表计算一个值。    /*打印开头部分*/    void printTitle()    {        for(int i = 0; i < x_num; i ++)        {            printf("%c\t", x[i]);        }        cout << read << endl;        printf("-------------------------------------------------\n");    }    /*检测是否穷举了所有的真值表*/    bool check_end()    {        for(int i = 0; i < x_num; i ++)        {            if(value[i] == 0)                return false;        }        return true;    }    /*获得字符对应的当前真值*/    int getValue(char c)    {        for(int i = 0; i < x_num; i ++)        {            if(x[i] == c)            {                return value[i];            }        }        return -1;    }public:    TrueFalseTable() {Ans = 0;}    /*允许用字符串直接初始化表达式*/    TrueFalseTable(string read)    {Ans = 0;        this->read = read;    }    /*初始化,主要是输入表达式,统计变量个数*/    void Init()    {        if(read == "")            cin >> read;        int tmp[27] = {0}, k = 0;        for (int i = 0; i < read.size(); i ++)        {            if(read[i] >= 'a' && read[i] <= 'z')            {                tmp[read[i]-'a'] ++;   //统计出现的字母,即变量个数。            }        }        for(int i = 0; i < 27; i ++)        {            if(tmp[i] != 0)            {                x[k++] = i + 'a'; //所有出现字母均保存了。            }        }        x_num = k;        memset(value, 0, sizeof(value));        printTitle();    }    /*产生下一组变量的真值*/    bool next_value()    {        if(check_end())            return 0;        value[x_num - 1] ++;        for(int i = x_num-1; i >= 0; i --)        {            if(value[i] > 1)            {                value[i] = 0;                value[i-1] ++;            }        }        return 1;    }    /*输出每一行真值表*/    void printValue()    {        for (int i = 0; i < x_num; i ++)        {            printf("%d\t", value[i]);        }        printf("%d\n", Ans);    }};/*因为再写到上面的类就太臃肿了,写一个<子类>  用于计算表达式的值(双栈)*/class Calculate : public TrueFalseTable{private:    stack<int> data;    //数据栈    stack<int> oper;    //符号栈public:    Calculate() {}    Calculate(string read)    {        this->read = read;    }    /*计算表达式的值*/    void calculate()    {char op[7] = {'~', '>', '^', 'V', '(',')','#'}; //运算符,其中->用>表示。#为栈底。int  in[7] = {5, 3, 3, 3, 1, 6, 0};            //栈内优先级;int  out[7] = {4, 2, 2, 2, 6, 1, 0};           //栈外优先级 < 栈内优先级;        int a, b, thera;        oper.push(getIndex('#'));int i = 0;        int index = oper.top();        while( i < read.size() || op[index] != '#')        {            //遇到表达式中的->, -不读取。            if(i < read.size() && read[i] == '-'){i++;                continue;}            if(i < read.size() && read[i] >= 'a' && read[i] <= 'z')            {                data.push(getValue(read[i]));i ++;            }            else            {                //遇到~,单独处理。if(oper.top() == 0){oper.pop();a = data.top();data.pop();a = !a;data.push(a);index = oper.top();continue;}//末尾没有符号来比较,那么直接计算。                int readIdx;if(i >= read.size()){readIdx = 5;}else{readIdx = getIndex(read[i]);}                switch(precede(oper.top(), readIdx))                {                case '>':                    a = data.top();                    data.pop();b = data.top();data.pop();                    thera = oper.top();oper.pop();                    data.push(fiture(b, thera, a));                    break;                case '<':                    oper.push(getIndex(read[i]));                    if(i < read.size() - 1)                    {                        i ++;                    }                    break;                case '=':                    oper.pop();                    if(i < read.size() - 1)                    {                        i ++;                    }                    break;                }            }//字符串最后为一个右括号,就结束。if(i == read.size() - 1 && oper.top() == 5){oper.pop();i ++;}            index = oper.top();        }Ans = data.top();data.pop();oper.pop();    }private:    /*获得运算符在数组中的下标*/    int getIndex(char c)    {        switch(c)        {        case '~':            return 0;        case '>':            return 1;        case '^':            return 2;        case 'V':            return 3;        case '(':            return 4;        case ')':            return 5;        case '#':            return 6;        default:            return -1;        }    }    /*比较栈内运算符和栈外运算符的优先级*/    char precede(int i1, int i2)    {//char op[7] = {'~', '>', '^', 'V', '(',')','#'}; //运算符,其中->用>表示。#为栈底。int  in[7] = {5, 3, 3, 3, 1, 6, 0};            //栈内优先级;int  out[7] = {4, 2, 2, 2, 6, 1, 0};           //栈外优先级 < 栈内优先级;        if(in[i1] > out[i2])        {            return '>';        }        else if(in[i1] < out[i2])        {            return '<';        }        else        {            return '=';        }    }    int fiture(int a, int ope, int b)    {        switch(ope)        {        case 0:            return !a;        case 1:            return !a || b;        case 2:            return a && b;        case 3:            return a || b;        }    }};int main(){    Calculate t("(p^~q)V(~p^q)");//   1、直接在定义类的时候就给表达式。//    Calculate t;                      //   2、通过控制台输入表达式。    t.Init();    do    {        t.calculate();        t.printValue();    }    while(t.next_value());    return 0;}



0 0
原创粉丝点击