逻辑表达式化为真值表

这个处理方法和多项式的处理方法一样。试着写了一下,发现自己对栈的应用能力还是不够,不过很感谢

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

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

/*程序设计类似与多项式的计算,用双栈来实现,完成<任意个>变量的表达式的运算*/
/*变量请统一用小写字母*/
/*目前支持的逻辑运算符有~(非),V(析取,用大写字母V),^(合取,用shitf + 6), 以及->(蕴含)。
没有添加<->(只是多添加一个操作符,优先级同->,同理,有兴趣的读者可以自己实现)*/
/*程序运行方式见main函数入口。*/


#include 
#include 
#include 
#include 
#include 
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 data;    //数据栈
    stack 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;
}



你可能感兴趣的:(未分类)