根據表達式求出真值表及主析取主合取——離散數學實訓

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#define N 1005
#define ll long long

char str[N];
char sta[N];
char a[N];

void houzhui()//數組模擬棧求後綴表達式
{
    int top = 0;
    while (top) top--;
    int len=strlen(str);
    int k=0;
//    printf("len = %d\n", len);
    int i;
    for(i = 0; i<len; i++)
    {
        if(str[i]>='a'&&str[i]<='z')
        {
            a[k++]=str[i];
//            printf("%c", a[k-1]);
        }
        else if(str[i]==')')
        {
            while (sta[top]!='(')
            {
                a[k++]=sta[top];
                top--;
            }
            top--;
        }
        else
        {
            if (str[i]=='-'&&str[i]!='>')
            {
                while (top&&sta[top]=='-')
                {
                    a[k++]=sta[top];
                    top--;;
                }
                sta[++top] = str[i];
                continue;
            }
            else if (str[i]=='<')
            {
                while (top&&sta[top]!='(')
                {
                    a[k++]=sta[top];
                    top--;;
                }
                sta[++top] = str[i];
                i+=2;
            }
            else if (str[i]=='-'&&str[i+1]=='>')
            {
                while (top&&sta[top]=='>'||sta[top]=='+'||sta[top]=='*'||sta[top]=='-')
                {
                    a[k++]=sta[top];
                    top--;;
                }
                sta[++top] = str[i + 1];
                i++;
            }
            else if (str[i]=='+')
            {
                while (top&&sta[top]=='+'||sta[top]=='*'||sta[top]=='-')
                {
                    a[k++]=sta[top];
                    top--;;
                }
                sta[++top] = str[i];
            }
            else if (str[i]=='*')
            {
                while (top&&sta[top]=='*'||sta[top]=='-')
                {
                    a[k++]=sta[top];
                    top--;;
                }
                sta[++top] = str[i];
            }
            else
                sta[++top] = str[i];
        }
    }
    while (top)
    {
        a[k++]=sta[top];
        top--;
    }
    a[k]='\0';
//    for(i=0;i<=k;i++)
//    {
//        printf("%c", a[i]);
//    }
//    printf("\n");
}

int ans[N];//真值表
char stkk[N];
int f[30];//記錄第幾個是哪一個字母
int h[30];//
int nt[30];//記錄第幾個字母是哪一個

int dfs(int now, int p, int top)//遞歸求各個子式真值
{
    if(now == top+1)
    {
        int num = 0;
		while(num) num--;
		int len = strlen(a);
        int i;
		for(i = 0; i<len; i++)
		{
			if (a[i] <= 'z' && a[i] >= 'a')
            {
				int x = a[i] - 'a';
				if(x + 'a' == 't') x=1;
				else if (x+'a'=='f') x=0;
				else x = (( p & (1 << (top-f[x]) )) !=0 );
//				printf("x = %d\n", (( p & (1 << (top - f[x]) ))!=0));
				stkk[++num] = x;
			}
			else if (a[i]=='-')
			{
				int x = (stkk[num]==0);
				num--;
				stkk[++num] = x;
			}
			else if (a[i]=='*')
            {
				int x = stkk[num];
                num--;
				x = (x==1&&stkk[num]==1);
                num--;
				stkk[++num] = x;
			}
			else if (a[i]=='+')
            {
				int x=stkk[num];
                num--;
				x=(x==1||stkk[num]==1);
				num--;
				stkk[++num] = x;
			}
			else if (a[i]=='>')
            {
				int x=stkk[num];
                num--;
				x=(!(x==0&&stkk[num]==1));
				num--;
				stkk[++num] = x;
			}
			else if (a[i]=='<'){
				int x=stkk[num];
				num--;
				x=(x==stkk[num]);
                num--;
				stkk[++num] = x;
			}
		}
		ans[p] = stkk[num];
		return stkk[num];
	}
	int a[2], i;
	for(i = 0; i<=1; i++)
    {
		a[i]= dfs(now+1,p*2+i,top);
	}
	if(a[0]==2 || a[1]==2) return 2;
	else if (a[1] != a[2]) return 2;
	else return a[1];
}
void work()
{
	memset(h, 0, sizeof(h));
	int len = strlen(str);
	int i;
	for(i=0; i<len; i++)
    {
		if (str[i] <= 'z'&& str[i] >= 'a') h[str[i]-'a'] = 1;
	}
	int tot = 0;
	for(i=0; i<=26; i++)
    {
		if (h[i] && i+'a' != 'f' && i+'a' != 't')
        {
			f[i] = ++tot;
			nt[tot] = i;
			printf("  %c  ", i+'a');
		}
	}
	printf("  ANS  \n");
	int hb = dfs(1,0,tot);
	for(i = 0; i<(1 << tot); i++)
    {
        int j;
		for (j=tot-1;j>=0;j--)
		{
			if (( i & (1<<j)) >0) printf("  1  ");
			else printf("  0  ");
		}
		printf("   %d\n",ans[i]);
	}//打印真值表
	if (hb==0||tot==0) printf("沒有主合取式\n");
	else
	{
		printf("主合取:");
		int flag = 0, j;
		for(i=0; i<(1 << tot); i++)
		{
			if(!ans[i]) continue;
			if(flag) printf("+");
			flag = 1;
			printf("(");
			for(j = tot-1; j>=0; j--)
			{
				if(j != tot-1) printf("*");
				if((i&(1<<j)) >0 ) printf("%c",nt[tot-j]+'a');
				else printf("-%c",nt[tot-j]+'a');
			}
			printf(")");
		}
		printf("\n");
	}
	if (hb==1||tot==0) printf("沒有主析取\n");
	else
    {
		printf("主析取:");
		int flag = 0, j;
		for(i=0; i<(1 << tot); i++)
		{
			if(ans[i]) continue;
			if(flag) printf("*");
			flag = 1;
			printf("(");
			for(j = tot-1; j>=0; j--)
			{
				if (j != tot-1) printf("+");
				if ((i&(1<<j))==0) printf("%c",nt[tot-j]+'a');
				else printf("-%c",nt[tot-j]+'a');
			}
			printf(")");
		}
		printf("\n");
	}
	return ;
}

int main()
{
    printf("+:合取\t*:析取\t-:非\n");
    printf("請輸入命題公式:");
    scanf("%s", str);
    houzhui();
    work();
    return 0;
}

//-((p+q)*p)
//p*q+r



//1.中綴表達式轉換爲後綴表達式便於計算
//2.DFS二進制枚舉每個狀態並用後綴表達式求值,得到真值表
//3.根據真值表打印主析取函數和主合取函數

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章