湖南大学离散数学实验——代码(一)

目录

实验代码

合法检测

#include"string.h"
#include"stdio.h"
void rule1(char a[],int i) {
	//如果是单个字符为合法表达式则为1
	if((a[i]>='a')&&(a[i]<='z')) {
		a[i]='1';
	}
	//若为常量则为合法表达式则返回1
	else if(a[i]=='0') {
		a[i]='1';
	}
}
int rule2(char a[],int i) {
	int n=strlen(a);
	int _result=0;
	//printf("in rule2:%s\n",a);
	//如果当前位置起形如"!1"则换成"1"
	if((i+1<n)&&(a[i]=='!')&&(a[i+1]=='1')) {
		a[i]='1';
		i++;
		while(a[i+1]!='\0') {
			a[i]=a[i+1];
			//后面的字符往前移一格
			i++;
		}
		a[i]='\0';
		_result=1;
	}
	//如果当前位置起形如"(1)"则换成"1"
	else if((i+2<n)&&(a[i]=='(')&&(a[i+1]=='1')&&(a[i+2]==')')) {
		a[i]='1';
		i++;
		while(a[i+2]!='\0') {
			a[i]=a[i+2];
			//后面的字符往前移2格
			i++;
		}
		a[i]='\0';
		_result=1;
	}
	//printf("in rule2-end:%s\n",a);
	return _result;
}
int rule3Con(char a[],int i) {
	//1+1,1*1,1-1,1=1均换成1
	int _result=0;
	int n=strlen(a);
	if((i+2<n)&&(a[i]=='1')&&(a[i+1]=='*')&&(a[i+2]=='1')) {
		a[i]='1';
		//后面的字符往前移2格
		i++;
		while(a[i+2]!='\0') {
			a[i]=a[i+2];
			i++;
		}
		a[i]='\0';
		_result=1;
	}
	return _result;
}
int rule3BiCond(char a[],int i) {
	//1+1,1*1,1-1,1=1均换成1
	int _result=0;
	int n=strlen(a);
	if((i+2<n)&&(a[i]=='1')&&(a[i+1]=='=')&&(a[i+2]=='1')) {
		a[i]='1';
		//后面的字符往前移2格
		i++;
		while(a[i+2]!='\0') {
			a[i]=a[i+2];
			i++;
		}
		a[i]='\0';
		_result=1;
	}
	return _result;
}
int rule3Cond(char a[],int i) {
	//1+1,1*1,1-1,1=1均换成1
	int _result=0;
	int n=strlen(a);
	if((i+2<n)&&(a[i]=='1')&&(a[i+1]=='-')&&(a[i+2]=='1')) {
		a[i]='1';
		//后面的字符往前移2格
		i++;
		while(a[i+2]!='\0') {
			a[i]=a[i+2];
			i++;
		}
		a[i]='\0';
		_result=1;
	}
	return _result;
}

int rule3DisConj(char a[],int i) {
	//1+1,1*1,1-1,1=1均换成1
	int _result=0;
	int n=strlen(a);
	if((i+2<n)&&(a[i]=='1')&&(a[i+1]=='+')&&(a[i+2]=='1')) {
		a[i]='1';
		//后面的字符往前移2格
		i++;
		while(a[i+2]!='\0') {
			a[i]=a[i+2];
			i++;
		}
		a[i]='\0';
		_result=1;
	}
	return _result;
}
int rule3(char a[],int i) {
	//1+1,1*1,1-1,1=1均换成1
	int _result=0;
	int n=strlen(a);
	if((i+2<n)&&(a[i]=='1')&&((a[i+1]=='+')||(a[i+1]=='*')||(a[i+1]=='-')||(a[i+1]=='='))&&(a[i+2]=='1')) {
		a[i]='1';
		//后面的字符往前移2格
		i++;
		while(a[i+2]!='\0') {
			a[i]=a[i+2];
			i++;
		}
		a[i]='\0';
		_result=1;
	}
	return _result;
}
int main(int argc, char *argv[]) {
	while(1) {
	char pstate[120],pstate0[120];
	int i=0,nold=0,nnew=0;
	printf("请输入公式(析+,合*,条-,双=,否定!,01):\n");
	gets(pstate0);
	fflush(stdin);
	nold=strlen(pstate0)+1;
	nnew=strlen(pstate0);
	for(i=0; i<nnew; i++) {
		pstate[i]=pstate0[i];
	}
	pstate[i]='\0';
	i=0;
	while(i<strlen(pstate)) {
		rule1(pstate,i);
		i++;
	}
	printf("规则1后:%s\n",pstate);
	//nold=strlen(pstate0)+1;
	//nnew=strlen(pstate);
	while(nnew<nold) {
		nold=strlen(pstate);
		//使用规则2对字串进行处理,会改变长度
		i=0;
		while(i<strlen(pstate)) {
			if(rule2(pstate,i)==0) { //没有修改任何字符串,则往下走
				i++;
			}
		}
		printf("规则2后:%s\n",pstate);
		i=0;
		while(i<strlen(pstate)) {
			if(rule3(pstate,i)==0) { //合取
				//没有修改任何字符串则往下走,否则从当前位置判断
				i++;
			}
		}
		printf("规则3后:%s\n",pstate);

		nnew=strlen(pstate);
	}
	if((pstate[0]=='1')&&(strlen(pstate)==1)) {
		printf("% s is valid\n",pstate0);
	} else {
		printf("% s is invalid\n",pstate0);
	}
}
	return 0;
}

真值表

#include <string.h>
#include <stdio.h>
int getalpha( char a[],char b[])
{

    char tmpc=' ';
    int n=strlen(a),i=0,j=0,k=0;
    for (i=0; i<n; i++)   //是字母
    {
        if(((a[i]>='a') && (a[i]<='z'))||((a[i]>='A') && (a[i]<='Z')))
        {
            for (k=0; k<j; k++)
            {
                if (b[k]==a[i])
                {
                    break;
                }
            }
            if (k>=j)
            {
                b[j]=a[i];
                j++;
            }
        }
    }
    //从低到高排序
    for(i=0; i<j-1; i++)
    {
        for (k=0; k<j-i-1; k++)
        {
            if (b[k] >b[k+1])
            {
                tmpc =b[k];
                b[k]=b[k+1];
                b[k+1]=tmpc;
            }
        }
    }
    b[j]='\0';//加上结束标志
    return j;//小写字的个数
}

void fillValue( char a[],char varchar[],int nvar,char valchar[],char resultchar[])     //a 是原始公式,varchar是变元列表如pqrs,
{
    // valchar是变元的某次取值
    int nLen=strlen(a),i=0,j=0,k=0;
    for (i=0; i<nLen; i++)
    {
        resultchar[i]=a[i];//复制一个原施公式
    }
    resultchar[i]='\0';
    for (i=0; i<nLen; i++)
    {
        //原公式中的每个字符
        for ( j=0; j<nvar; j++)
        {
            //公式中的字符是第几个变元
            if (resultchar[i]==varchar[j])
            {
                //是第j変元,其値換成第j个値
                resultchar[i]=valchar[j];
                break;
            }
        }
    }
}

void negatecal(char a[])
{
    int _result=0,i=0,j=0;
    while(i < strlen(a))
    {
        //如果当前位置起形如"! 1"則換成"0"
        j=i;
        _result =0;
        if ((j+1<strlen(a)) && (a[j]=='!' )&&(a[j+1]=='1'))
        {
            a[j]='0';
            _result =1;
        }
        else if((j+1<strlen(a)) &&(a[j]=='!') &&(a[j+1]=='0'))
        {
            a[j]='1';
            _result=1;
        }
        if (_result==1)   //如果有這算則后面的往前移
        {
            j++;
            while(a[j+1]!='\0')   //后面的字符往前移1格
            {
                a[j]=a[j+1];
                j++;
            }
            a[j]='\0';
        }
        else     //没有! 0或! 1則看下一个指针
        {
            i++;
        }
    }
}

void kuanhao( char a[])
{

    int _result =0,i=0,j=0;
    while (i <strlen(a))
    {
        j=i;
        _result=0;
        if((j+2<strlen(a)) && (a[j]=='(' )&&(a[j+1]=='1')&&(a[j+2] ==')'))
        {

            a[j]='1';
            _result=1;
        }
        else if((j+2<strlen(a))&&(a[j]=='(')&&(a[j+1]=='0')&&(a[j+2]==')'))
        {
            a[j]='0';
            _result=1;
        }
        if(_result==1)
        {
            j++;
            while(a[j+2]!='\0')   //后面的字符往前移2格
            {
                a[j]=a[j+2];
                j++;
            }
            a[j]='\0';
        }
        else
        {
            //没有!0或!1则看下一个指针
            i++;
        }
    }
}

void conYsh(char a[])
{
    int _result=0,i=0,j=0;
    while(i<strlen(a))
    {

        j=i;
        _result=0;
        if((j+2<strlen(a))&&(a[j]=='0')&&(a[j+1]=='*')&&(a[j+2]=='0'))
        {
            a[j]='0';
            _result=1;
        }
        else if((j+2<strlen(a))&&(a[j]=='0')&&(a[j+1]=='*')&&(a[j+2]=='1'))
        {
            a[j]='0';
            _result=1;
        }
        else if((j+2<strlen(a))&&(a[j]=='1')&&(a[j+1]=='*')&&(a[j+2]=='0'))
        {
            a[j]='0';
            _result=1;
        }
        else if((j+2<strlen(a))&&(a[j]=='1')&&(a[j+1]=='*')&&(a[j+2]=='1'))
        {
            a[j]='1';
            _result=1;
        }
        if(_result==1)
        {
            j++;//后面的字符往前移2格
            while(a[j+2]!='\0')
            {
                a[j]=a[j+2];
                j++;
            }
            a[j]='\0';
        }
        else
        {
            //没有!0或!1则看下一个指针
            i++;
        }
    }
}

void biCondYsh(char a[])
{
    int _result=0,i=0,j=0;
    while(i<strlen(a))
    {
        j=i;
        _result=0;
        if((j+2<strlen(a))&&(a[j]=='0')&&(a[j+1]=='=')&&(a[j+2]=='0'))
        {
            a[j]='1';
            _result=1;
        }
        else if((j+2<strlen(a))&&(a[j]=='0')&&(a[j+1]=='=')&&(a[j+2]=='1'))
        {
            a[j]='0';
            _result=1;
        }
        else if((j+2<strlen(a))&&(a[j]=='1')&&(a[j+1]=='=')&&(a[j+2]=='0'))
        {
            a[j]='0';
            _result=1;
        }
        else if((j+2<strlen(a))&&(a[j]=='1')&&(a[j+1]=='=')&&(a[j+2]=='1'))
        {
            a[j]='1';
            _result=1;
        }
        if(_result==1)
        {
            j++;
            while(a[j+2]!='\0')
            {
                a[j]=a[j+2];
                j++;
            }
            a[j]='\0';
        }
        else
        {
            i++;
        }
    }
}

int condYsh(char a[])
{
    int _result=0,i=0,j=0;
    while(i<strlen(a))
    {
        j=i;
        _result=0;
        if((j+2<strlen(a))&&(a[j]=='0')&&(a[j+1]=='-')&&(a[j+2]=='0'))
        {
            a[j]='1';
            _result=1;
        }
        else if ((j+2<strlen(a))&&(a[j]=='0')&&(a[j+1]=='-')&&(a[j+2]=='1'))
        {
            a[j]='1';
            _result=1;
        }
        else if ((j+2<strlen(a))&&(a[j]=='1')&&(a[j+1]=='-')&&(a[j+2]=='0'))
        {
            a[j]='0';
            _result=1;
        }
        else if ((j+2<strlen(a))&&(a[j]=='1')&&(a[j+1]=='-')&&(a[j+2]=='1'))
        {
            a[j]='1';
            _result=1;
        }
        if(_result==1)
        {
            j++;
            while(a[j+2]!='\0')
            {
                a[j]=a[j+2];
                j++;
            }
            a[j]='\0';
        }
        else
        {
            i++;
        }
    }
}

int disConjYsh(char a[])
{
    int _result=0,i=0,j=0;
    while(i<strlen(a))
    {
        j=i;
        _result=0;
        if((j+2<strlen(a))&&(a[j]=='0')&&(a[j+1]=='+')&&(a[j+2]=='0'))
        {
            a[j]='0';
            _result=1;
        }
        else if((j+2<strlen(a))&&(a[j]=='0')&&(a[j+1]=='+')&&(a[j+2]=='1'))
        {
            a[j]='1';
            _result=1;
        }
        else if((j+2<strlen(a))&&(a[j]=='1')&&(a[j+1]=='+')&&(a[j+2]=='0'))
        {
            a[j]='1';
            _result=1;
        }
        else if((j+2<strlen(a))&&(a[j]=='1')&&(a[j+1]=='+')&&(a[j+2]=='1'))
        {
            a[j]='1';
            _result=1;
        }
        if(_result==1)
        {
            //如果修改成功则后面的往前移
            j++;
            while(a[j+2]!='\0')
            {
                a[j]=a[j+2];
                j++;
            }
            a[j]='\0';
        }
        else
        {
            i++;
        }
    }
}

int main(int argc,char * argv[])
{
    char pstate[120],pstate0[120],charList[120],charVal[120];
    char minItem[1024][52],truetable[1024];//最多10个变量
    int i=0,nold=0,nnew=0,nvar=1,nRow=1,j=0,flagsum=1,iMinItem=0;
    printf("请输入公式(析+,合*,条-,双=,否定!,01):\n");
    gets(pstate0);
    fflush(stdin);

    nold=strlen(pstate0)+1;
    nnew=strlen(pstate0);
    for(i=0; i<nnew; i++)
    {
        pstate[i]=pstate0[i];
    }
    pstate[i]='\0';
    nvar=getalpha(pstate,charList);
    //真值表各个变元的值
    nRow=1;
    for(i=0; i<nvar; i++)
    {
        charVal[i]='0';
        nRow=nRow*2;
    }
    charVal[i]='\0';
    //真值表的首行
    printf("\n");
    for(i=0; i<nvar; i++)
    {
        printf("%4c",charList[i]);
    }
    printf("% 15c% s\n",' ',pstate);

    for(i=0; i<nvar; i++)
    {
        printf("% 4c",'-');
    }
    printf("|");
    for(i=0; i<60; i++)
    {
        printf("%c",'-');
    }
    printf("\n");

    for(i=0; i<nRow; i++)
    {
        //真偵表的各行
        for (j=0; j <nvar; j++)
        {
            printf("% 4c",charVal[j]);
        }
//將値填人公式中
        pstate[0]='\0';

        fillValue( pstate0, charList, nvar, charVal, pstate);
//汁算公式的値
        nold=strlen(pstate0) +1;
        nnew=strlen(pstate);
        while(nnew<nold)
        {
            nold=strlen(pstate);
            negatecal(pstate);//否定
            kuanhao(pstate);//(A)
            conYsh(pstate);
            biCondYsh(pstate);
            condYsh(pstate);
            disConjYsh(pstate);
            nnew=strlen(pstate);
        }
        if (strlen(pstate)==1)
        {

            if (pstate[0]=='1')
            {

                for (j=0; j<nvar; j++)
                {
                    minItem[iMinItem][j]=charVal[j];
                }

                minItem [iMinItem][j]='\0';
                iMinItem++;
            }
            truetable[i]=pstate[0];
        }
        printf("% 20c% s",' ',pstate);
        printf("\n");
//値加1
        flagsum=1;
        for (j=nvar -1; j>=0; j--)
        {

            if (charVal[j]=='1')
            {

                if (flagsum==1)   //1 +1 =10//迸位
                {
                    charVal[j] ='0';
                    flagsum=1;
                }
                else     //1 +0=1不変I
                {
                    break;
                }
            }
            else if(charVal[j]=='0')
            {

                if  (flagsum==1)//0+1=1//没有进位

                {
                    charVal[j]='1' ;
                    flagsum=0;
                    break;
                }
                else   //0+0结束
                {
                    break;
                }

            }
        }
    }

    for (i=0; i<iMinItem; i++)
    {
        if(i==0)
        {
            printf(" m% s",minItem[i]);
        }
        else
        {
            printf(" +m% s",minItem[i]);
        }
    }
    printf("\n");
    for (i=0; i< iMinItem; i++)
    {
        if (i==0)
        {
            printf("(");
            for(j=0; j <nvar; j++)
            {
                if(j==0)
                {
                    if (minItem[i][j]=='1')
                    {
                        printf("% c",charList[j]);
                    }
                    else
                    {
                        printf("!% c",charList[j]);
                    }
                }
                else
                {
                    if (minItem[i][j]=='1')
                    {
                        printf("*% c",charList[j]);
                    }
                    else
                    {
                        printf("*!% c",charList[j]);
                    }
                }
            }
            printf(")");
        }
        else
        {
            printf("+(");
            for(j=0; j <nvar; j++)
            {
                if(j==0)
                {
                    if (minItem[i][j]=='1')
                    {
                        printf("% c",charList[j]);
                    }
                    else
                    {
                        printf("!% c",charList[j]);
                    }
                }
                else
                {
                    if (minItem[i][j]=='1')
                    {
                        printf("*% c",charList[j]);
                    }
                    else
                    {
                        printf("*!% c",charList[j]);
                    }
                }
            }
            printf(")");
        }
    }
    printf("\n");
}

自然推理系统

#include <bits/stdc++.h>//修改点1:万能头文件
using namespace std;
struct tmd{
    char gs[120],gslast[120],reason[120];
    int nletter,nused,isletter,iscond;
};
 
void nonoop2(char aa[])
{
 
    int i=0,j=0;
    while(i<strlen(aa)-2)
    {
        if(i+1<strlen(aa)&&aa[i]=='!'&&aa[i+1]=='!')
        {
            j=i;
            while(j<strlen(aa)-2)
            {
                aa[j]=aa[j+2];
                j++;
            }
            aa[j]='\0';
            break;
        }
        else
           i++;
    }
}
 
void print(tmd tmrec[],int np)
{
    int i=0;
    for(i=0;i<np;++i)
    {
        if(tmrec[i].isletter==1)
            printf("(%d)\t%s为真\t\t\t%s---文字\n",i+1,tmrec[i].gs,tmrec[i].reason);
        else if(tmrec[i].iscond==1)
            printf("(%d)\t%s-%s为真\t\t\t%s---条件式\n",i+1,tmrec[i].gs,tmrec[i].gslast,tmrec[i].reason);
        else
            printf("(%d)\t%s为真\t\t\t%s\n",i+1,tmrec[i].gs,tmrec[i].reason);
    }
}
 
int setreason(tmd tmrec[],int np,string r0,int j0,int j1,int nused0,int iscond0,int isletter0)
{
    char stmpj0[20],stmpj1[20];
    int nlen1=0,j=0,nlenj0=0,nlenj1=0;
    nlen1=r0.length();
    itoa(j0+1,stmpj0,10);
    nlenj0=strlen(stmpj0);
    itoa(j1+1,stmpj1,10);
    nlenj1=strlen(stmpj1);
    if(j0==-1)//输出“前提条件”
    {
        for(j=0;j<nlen1;++j)
            tmrec[np].reason[j]=r0[j];
        tmrec[np].reason[j]='\0';
    }
    else if(j1==-1)
    {
        tmrec[np].reason[0]='(';
        for(j=0;j<nlenj0;++j)
            tmrec[np].reason[j+1]=stmpj0[j];
        tmrec[np].reason[j+1]=')';
 
        for(j=0;j<nlen1;++j)
            tmrec[np].reason[j+2+nlenj0]=r0[j];
        tmrec[np].reason[j+2+nlenj0]='\0';
    }
    else
    {
        tmrec[np].reason[0]='(';
        for(j=0;j<nlenj0;++j)
            tmrec[np].reason[j+1]=stmpj0[j];
        tmrec[np].reason[j+1]=')';
 
        tmrec[np].reason[nlenj0+2]='(';
        for(j=0;j<nlenj1;++j)
            tmrec[np].reason[nlenj0+3+j]=stmpj1[j];
        tmrec[np].reason[nlenj0+3+j]=')';
 
        for(j=0;j<nlen1;++j)
            tmrec[np].reason[nlenj0+nlenj1+4+j]=r0[j];
        tmrec[np].reason[nlenj0+nlenj1+4+j]='\0';
    }
    tmrec[np].nused=nused0;
    tmrec[np].iscond=iscond0;
    tmrec[np].isletter=isletter0;
}
 
int inputprimary(tmd gs0[])//修改点3:调换了inputprimary函数与setreason函数的位置
{
    tmd tmp;
    char pstate[120];
    string r0="前提条件";
    string r1="原命题的逆否命题";
    string r2="双条件导出的条件式";
    string r3="析取式转换为条件式";
    //修改点4:解决警告
    int i=0,j=0,nlen=0,k=0;
    int i0=0;
    printf("输完一个前提条件请按回车,不输直接回车则结束\n析+,合-,条-,双=,否定!\n前提中只能为双条件、单条件、析取式,\n若为两个个条件的合取,请输入两个前提,文字请在最前面输入:\n");
    while(1)
    {
        gets(pstate);
        nlen=strlen(pstate);
        if(nlen==0)
            break;
        if(nlen==1)
        {
            gs0[i].nletter=strlen(pstate);
            gs0[i].gs[0]=pstate[0];
            gs0[i].gs[1]='\0';
            gs0[i].gslast[0]='\0';
            setreason(gs0,i,r0,-1,-1,0,0,1);
        }
        else if(nlen==2&&pstate[0]=='!')
        {
            gs0[i].nletter=strlen(pstate);
            gs0[i].gs[0]=pstate[0];
            gs0[i].gs[1]=pstate[1];
            gs0[i].gs[2]='\0';
            gs0[i].gslast[0]='\0';
            setreason(gs0,i,r0,-1,-1,0,0,1);
        }
        else
        {
            for(j=0;j<nlen;++j)
            {
                if(pstate[j]=='-')
                {
                    gs0[i].nletter=strlen(pstate);
                    for(k=0;k<j;++k)
                        gs0[i].gs[k]=pstate[k];
                    gs0[i].gs[k]='\0';
                    for(k=j+1;k<nlen;++k)
                        gs0[i].gslast[k-j-1]=pstate[k];
                    gs0[i].gslast[k-j-1]='\0';
                    setreason(gs0,i,r0,-1,-1,0,1,0);
                    i++;
                    gs0[i].nletter=gs0[i-1].nletter;
                    gs0[i].gslast[0]='!';
                    for(k=0;k<j;++k)
                        gs0[i].gslast[k+1]=pstate[k];
                    gs0[i].gslast[k+1]='\0';
                    nonoop2(gs0[i].gslast);
 
                    gs0[i].gs[0]='!';
                    for(k=j+1;k<nlen;++k)
                        gs0[i].gs[k-j-1+1]=pstate[k];//>??????
                    gs0[i].gs[k-j-1+1]='\0';
                    nonoop2(gs0[i].gs);
                    setreason(gs0,i,r1,i-1,-1,0,1,0);
                    break;
                }
                else if(pstate[j]=='=')
                {
                    gs0[i].nletter=strlen(pstate);
                    for(k=0;k<strlen(pstate);++k)
                        gs0[i].gs[k]=pstate[k];
                    gs0[i].gs[k]='\0';
                    gs0[i].gslast[0]='\0';
                    setreason(gs0,i,r0,-1,-1,0,0,0);
                    i++;
                    gs0[i].nletter=strlen(pstate);
                    for(k=0;k<j;++k)
                        gs0[i].gslast[k-j-1]=pstate[k];
                    gs0[i].gslast[k-j-1]='\0';
                    setreason(gs0,i,r2,i-1,-1,0,1,0);
                    i++;
                    gs0[i].nletter=gs0[i-1].nletter;
                    for(k=0;k<j;++k)
                        gs0[i].gslast[k]=pstate[k];
                    gs0[i].gs[k-j-1]='\0';
                    setreason(gs0,i,r2,i-2,-1,0,1,0);
                    break;
                }
                else if(pstate[j]=='+')
                {
                    gs0[i].nletter=strlen(pstate);
                    for(k=0;k<strlen(pstate);++k)
                        gs0[i].gs[k]=pstate[k];
                    gs0[i].gs[k]='\0';
                    gs0[i].gslast[0]='\0';
                    setreason(gs0,i,r0,-1,-1,0,0,0);
                    i++;
                    gs0[i].nletter=strlen(pstate);
                    gs0[i].gs[0]='!';
                    for(k=0;k<j;++k)
                        gs0[i].gs[k+1]=pstate[k];
                    gs0[i].gs[k+1]='\0';
                    for(k=j+1;k<nlen;++k)
                        gs0[i].gslast[k-j-1]=pstate[k];
                    gs0[i].gslast[k-j-1]='\0';
                    setreason(gs0,i,r3,i-1,-1,0,1,0);
                    nonoop2(gs0[i].gs);
                    i++;
                    gs0[i].nletter=strlen(pstate);
                    for(k=0;k<j;++k)
                        gs0[i].gslast[k]=pstate[k];
                    gs0[i].gslast[k]='\0';
                    gs0[i].gs[0]='!';
                    for(k=j+1;k<nlen;++k)
                        gs0[i].gs[k-j-1+1]=pstate[k];
                    gs0[i].gs[k-j-1+1]='\0';
                    setreason(gs0,i,r3,i-2,-1,0,1,0);
                    nonoop2(gs0[i].gs);
                    break;
                }
            }
            if(j>=nlen)
            {
                gs0[i].nletter=strlen(pstate);
                for(k=0;k<nlen;++k)
                    gs0[i].gs[k]=pstate[k];
                gs0[i].gs[k]='\0';
                gs0[i].gslast[0]='\0';
                setreason(gs0,i,r0,-1,-1,0,0,0);
            }
        }
        i++;
    }
    nlen=i;
    for(i=0;i<nlen-1;++i)
    {
        k=i;
        for(j=i+1;j<nlen;j++)//修改点5:将nlen-1改为nlen,否则最后一个元素无法排序
            if(gs0[k].nletter>gs0[j].nletter)
                k=j;
        if(k>i) swap(gs0[i],gs0[k]);//修改点6:用swap替代中间元
    }
    return nlen;
}
 
 
int main()
{
    while(1)//改进点7:连续输入
    {
        tmd gs0[100];
	char result0[128];
	tmd tmrec[1024];
	char stmp[128];
	char lastreason[128]="";
	string r01="假言推理";
	int i=0,j=0,k=0;
	int np=1,np0=0,is0k=0;
	int i0=0,nposletter=0,nposcond=0;
 
	np0=inputprimary(gs0);
	printf("输入要推理的结论,结论只能是文字,\n若是条件式、析取式请先手工转换为条件,将前件作为附加前提:\n");
    gets(result0);
    fflush(stdin);
 
    for(i=0;i<np0;++i)
        tmrec[i]=gs0[i];
 
    np=i;
    nposletter=0;
    nposcond=0;
    is0k=0;
    i0=-1;
    while(1)
    {
        i=i0+1;
        while(i<np&&tmrec[i].isletter!=1)
            i++;
        if(i>=np)
            break;
        i0=i;
        nposletter=i;
        strcpy(stmp,tmrec[i].gs);
        np0=np-1;
        while(np>np0)
        {
            np0=np;
            for(i=0;i<np;++i)
                if(tmrec[i].iscond==1&&tmrec[i].nused==0)
                    break;
            if(i==np)
                break;
            while(i<np)
            {
                if(tmrec[i].iscond==1)
                    if((strcmp(lastreason,tmrec[i].reason)!=0)||
                       (strcmp(lastreason,tmrec[i].reason)==0&&tmrec[i].reason[0]!='('))
                        if(strcmp(tmrec[i].gs,stmp)==0)
                        {
                            strcpy(lastreason,tmrec[i].reason);
                            tmrec[nposletter].nused++;
                            tmrec[i].nused++;
                            strcpy(stmp,tmrec[i].gslast);
                            strcpy(tmrec[np].gs,stmp);
                            tmrec[np].gslast[0]='\0';
                            setreason(tmrec,np,r01,nposletter,i,0,0,1);
                            nposletter=np;
                            np++;
                            if(strcmp(result0,stmp)==0)
                            {
                                is0k=1;
                                break;
                            }
                        }
                i++;
            }
        }
        if(is0k==1)
            break;
    }
    if(is0k==1)
        printf("推理成立,推理过程如下:\n");
    else
        printf("推理不成立,推理过程如下:\n");
    print(tmrec,np);
    printf("\n\n");
    }
 
	return 0;
}

消解推理系统

#include <bits/stdc++.h>//修改点1:万能头文件
using namespace std;
 
struct tmd
{
	char gs[120], gsLast[120], niyou[120];//前件与后件及理由
	int nLitter, nUsed, isLitter, isCond;
};
 
void nonoop2( char aa[] )
{
	//!!p=p
	int i = 0, j = 0;
	while (i < strlen( aa ) - 2)
	{
		//至少还有两个字符
		if (((i + 1) < strlen( aa )) && (aa[i] == '!') && (aa[i + 1] == '!'))
		{
			j = i;
			while (j < strlen( aa ) - 2)
			{
				aa[j] = aa[j + 2];
				j++;
			}
			aa[j] = '\0';
			break;
		}
		else
			i++;
	}
}
 
void printYsh( struct tmd tmdrec[], int np )
{
	int i = 0;
	for (i = 0; i < np; i++)
	{
		if (tmdrec[i].isLitter == 1)
			printf( "(%d)\t%s为真\t\t\t%s---文字\n", i + 1, tmdrec[i].gs, tmdrec[i].niyou );
		else if (tmdrec[i].isCond == 1)
			printf( "(%d)\t%s+%s为真\t\t\t%s---析取式\n", i + 1, tmdrec[i].gs, tmdrec[i].gsLast, tmdrec[i].niyou );
		else
			printf( "(%d)\t%s为真\t\t\t%s\n", i + 1, tmdrec[i].gs, tmdrec[i].niyou );
	}
}
 
//修改1:调换函数位置,否则会出现调用未定义函数的情况
int setNiyou( struct tmd tmdrec[], int np, char ny0[], int j0, int j1, int nUsed0, int isCond0, int isLitter0 )
{
	//将字符串ny0与j0赋到推理意见中
	char stmdpj0[20], stmdpj1[20];
	int nLen1 = 0, j = 0, nLenj0 = 0, nLenj1 = 0;
	nLen1 = strlen( ny0 );
	itoa( j0 + 1, stmdpj0, 10 );
	nLenj0 = strlen( stmdpj0 );//前一个依据
	itoa( j1 + 1, stmdpj1, 10 );
	nLenj1 = strlen( stmdpj1 );//后一个依据
	if (j0 == -1)
	{
		//原始前提
		for (j = 0; j < nLen1; j++)
			tmdrec[np].niyou[j] = ny0[j];
		tmdrec[np].niyou[j] = '\0';
	}
	else if (j1 == -1)//由前一步推理所得结论
	{
		tmdrec[np].niyou[0] = '(';
		for (j = 0; j < nLenj0; j++)
			tmdrec[np].niyou[j + 1] = stmdpj0[j];
		tmdrec[np].niyou[j + 1] = ')';
 
		for (j = 0; j < nLen1; j++)
			tmdrec[np].niyou[j + 2 + nLenj0] = ny0[j];
		tmdrec[np].niyou[j + 2 + nLenj0] = '\0';
	}
	else
	{
		//由前二步推理所得
		tmdrec[np].niyou[0] = '(';
		for (j = 0; j < nLenj0; j++)
			tmdrec[np].niyou[j + 1] = stmdpj0[j];
		tmdrec[np].niyou[j + 1] = ')';
 
		tmdrec[np].niyou[nLenj0 + 2] = '(';
		for (j = 0; j < nLenj1; j++)
			tmdrec[np].niyou[nLenj0 + 3 + j] = stmdpj1[j];
		tmdrec[np].niyou[nLenj0 + 3 + j] = ')';
 
		for (j = 0; j < nLen1; j++)
			tmdrec[np].niyou[nLenj0 + nLenj1 + 4 + j] = ny0[j];
		tmdrec[np].niyou[nLenj0 + nLenj1 + 4 + j] = '\0';
	}
 
	tmdrec[np].nUsed = nUsed0;//附加前提从未使用过nUsed0,int isCond0,int isLitter0
	tmdrec[np].isCond = isCond0;//是条件式
	tmdrec[np].isLitter = isLitter0;//是文字
}
 
void swaptmd(tmd &a,tmd &b)
{
    tmd temp;
    temp=a;
    a=b;
    b=temp;
}
 
 
int inputPrimary( struct tmd gs0[] )
{
	struct tmd tmdp;
	char pstate[120];
	char ny00[]="前提条件";
	char *ny0=ny00;
	char ny11[]="条件式转为析取式";
	char *ny1=ny11;
	char ny22[]="双条件导出的析取式";
	char *ny2=ny22;
	int i = 0, j = 0, nLen = 0, k = 0;
	int i0 = 0;//原始条件
	printf( "输完一个前提条件请按回车,不输直接回车则结束\n析+,合*,条-,双=,否定!\n前提中只能为双条件、单条件、析取式,\n若为2个条件的合取,请输入2个前提,文字请在最前面输入:\n" );
	while (1)
	{
		gets( pstate );
		nLen = strlen( pstate );
		if (nLen == 0)
		{
			break;
		}//设置nUsed,isLitter,isCond,nLittle的值
		//判断是否为文字
		if (nLen == 1)//标注单个文字
		{
			gs0[i].nLitter = strlen( pstate );
			gs0[i].gs[0] = pstate[0];
			gs0[i].gs[1] = '\0';
			gs0[i].gsLast[0] = '\0';
			setNiyou( gs0, i, ny0, -1, -1, 0, 0, 1 );//前提类型,无,无,未使用,不是条件式,是文字
		}
		else if ((nLen == 2) && (pstate[0] == '!')) //标注!p
		{
			gs0[i].nLitter = strlen( pstate );
			gs0[i].gs[0] = pstate[0];
			gs0[i].gs[1] = pstate[1];
			gs0[i].gs[2] = '\0';
			gs0[i].gsLast[0] = '\0';
			setNiyou( gs0, i, ny0, -1, -1, 0, 0, 1 );//前提类型,无,无,未使用,不是条件式,是文字
		}
		else
		{
			for (j = 0; j < nLen; j++)
			{
				if (pstate[j] == '-')//标注条件式p-q
				{
					gs0[i].nLitter = strlen( pstate );
					for (k = 0; k < nLen; k++)
						gs0[i].gs[k] = pstate[k];//整个表达式进入gs
					gs0[i].gs[k] = '\0';
					gs0[i].gsLast[0] = '\0';
					setNiyou( gs0, i, ny0, -1, -1, 0, 0, 0 );//前提类型,无,无,未使用,不是析取式,不是文字
 
					i++;
					gs0[i].nLitter = gs0[i - 1].nLitter;
					gs0[i].gs[0] = '!';
					for (k = 0; k < j; k++)
						gs0[i].gs[k + 1] = pstate[k];
					gs0[i].gs[k + 1] = '\0';
					nonoop2( gs0[i].gs );
 
					for (k = j + 1; k < nLen; k++)
						gs0[i].gsLast[k - j - 1] = pstate[k];
					gs0[i].gsLast[k - j - 1] = '\0';
					setNiyou( gs0, i, ny1, i - 1, -1, 0, 1, 0 );//前提类型,无,无,未使用,是条件式,不是文字
					break;
				}
 
				else if (pstate[j] == '=')//标注双条件p=q
				{
					//先保存双条件
					gs0[i].nLitter = strlen( pstate );
					for (k = 0; k < strlen( pstate ); k++) { gs0[i].gs[k] = pstate[k]; }//双条件全部进gs
					gs0[i].gs[k] = '\0';
					gs0[i].gsLast[0] = '\0';
					setNiyou( gs0, i, ny0, -1, -1, 0, 0, 0 );//前提类型,无,无,未使用,是条件式,不是文字
															 //p-q即!p+q
					i++;
					gs0[i].nLitter = strlen( pstate );
					gs0[i].gs[0] = '!';
					for (k = 0; k < j; k++) { gs0[i].gs[k + 1] = pstate[k]; }//p进gs
					gs0[i].gs[k + 1] = '\0';
					for (k = j + 1; k < nLen; k++) { gs0[i].gsLast[k - j - 1] = pstate[k]; }//q进gsLast
					gs0[i].gsLast[k - j - 1] = '\0';
					setNiyou( gs0, i, ny2, i - 1, -1, 0, 1, 0 );//前提类型,无,无,未使用,是条件式,不是文字
					nonoop2( gs0[i].gs );//去掉可能存在的!!?
										 //q-p=p+!q
					i++;
					gs0[i].nLitter = gs0[i - 1].nLitter;
					for (k = 0; k < j; k++) { gs0[i].gs[k] = pstate[k]; }//条件前件p进gs
					gs0[i].gs[k] = '\0';
					gs0[i].gsLast[0] = '!';
					for (k = j + 1; k < nLen; k++) { gs0[i].gsLast[k - j - 1 + 1] = pstate[k]; }//条件后件!q进gsLast
					gs0[i].gsLast[k - j - 1 + 1] = '\0';
					setNiyou( gs0, i, ny2, i - 2, -1, 0, 1, 0 );//前提类型,无,无,未使用,是条件式,不是文字
					nonoop2( gs0[i].gsLast );//去掉可能存在的!!?
					break;
 
				}
 
				else if (pstate[j] == '+')//标注析取式p+q,也要分解到gs与gsLast中
				{
					gs0[i].nLitter = strlen( pstate );
					for (k = 0; k < j; k++)
						gs0[i].gs[k] = pstate[k];    //前件进gs
					gs0[i].gs[k] = '\0';
					for (k = j + 1; k < nLen; k++)
						gs0[i].gsLast[k - j - 1] = pstate[k];    //条件全部进gs
					gs0[i].gsLast[k - j - 1] = '\0';
					setNiyou( gs0, i, ny0, -1, -1, 0, 1, 0 );//前提类型,无,无,未使用,是条件式,不是文字
					break;
				}
			}
			if (j >= nLen)//不是条件式,也不是文字,则是普通的条件
			{
				gs0[i].nLitter = strlen( pstate );
				for (k = 0; k < nLen; k++)
					gs0[i].gs[k] = pstate[k];    //公式全进gs
				gs0[i].gs[k] = '\0';
				gs0[i].gsLast[0] = '\0'; //gsLast为空串
				setNiyou( gs0, i, ny0, -1, -1, 0, 0, 0 );//前提类型,无,无,未使用,不是条件式,不是文字
			}
		}
		i++;//当前公式处理完以后,指针i的值增1
	}
	nLen = i;//按字符串的长度排序
	for (i = 0; i < nLen - 1; i++)
	{
		k = i;
		//for (j = i + 1; j < nLen - 1; j++)
		for (j = i + 1; j < nLen; j++)//修改2:修改循环条件使得最后的元素可排序
			if (gs0[k].nLitter > gs0[j].nLitter)
				k = j;
		if (k > i)
		{
			swaptmd(gs0[i],gs0[k]);//修改3:使用自定义的swaptmd排序
//			tmdp = gs0[i];
//			gs0[i] = gs0[k];
//			gs0[k] = tmdp;
		}
	}
	return nLen;
}
 
int main()
{
	while(1){
	
	struct tmd gs0[100];//推理前提条件
	char result0[128]; //结论
	struct tmd tmdrec[1024];//最多1000步
 
	char stmdp[128];
	char lastNiYou[128] = " ";//上一个推理式的理由
		char ny001[]="消解";
	char *ny01=ny001;
	int i = 0, j = 0, k = 0;
	int np = 1, np0 = 0, isOk = 0;
	int i0 = 0, nPosLitter = 0, nPosCond = 0;//文字起始的位置,首个文字的位置,消解式的位置
	np0 = inputPrimary( gs0 );
	//输入结论
	printf( "输入要推理的结论,结论只能是文字,\n若是条件式,析取式请先手工转换为条件,将前件作为附加前提:" );
	gets( result0 );
	fflush( stdin );
	for (i = 0; i < np0; i++)
	{
		tmdrec[i] = gs0[i];//所有原始公式转抄到tmdrec中
	}
	np = i;//推理队列的尾部指针
	nPosLitter = 0;//文字的位置号
	nPosCond = 0;//条件的位置号
	isOk = 0;
	i0 = -1;
	while (1)
	{
		i = i0 + 1;//寻找下一个文字,i是起始位置,np是命令串的长度
		while ((i < np) && (tmdrec[i].isLitter != 1))
			i++;
		if (i >= np)
			break;//找不到文字我就没法推理了
		i0 = i;//记录从源头查询的首个文字的位置号,下次从此号往后寻找
		nPosLitter = i;//记录文字的位置
		strcpy( stmdp, tmdrec[i].gs );//保存当前文字的内容
		np0 = np - 1;
		while (np > np0) //从当前文字的下一个位置起寻找析取式,则一路往下走
		{
			np0 = np;
			for (i = 0; i < np; i++)//找到一个没有用过的戏曲式
				if ((tmdrec[i].isCond == 1) && (tmdrec[i].nUsed == 0))
					break;
			if (i == np)
				break;//没有找到则结束推理,所有条件式都用到了
			while (i < np)//若找到了这样的条件式
			{
				if ((tmdrec[i].isCond == 1))//若是条件式
				{
					//与上条命令的来源不同,或者但是同为前提条件也是可以的,即首个字符不是(
					if (((strcmp( lastNiYou, tmdrec[i].niyou ) != 0) || ((strcmp( lastNiYou, tmdrec[i].niyou ) == 0) && tmdrec[i].niyou[0] != '(')))
					{
 
						if ((tmdrec[i].gs[0] == '!') && (stmdp[0] != '!') && (strlen( tmdrec[i].gs ) - strlen( stmdp ) == 1))    // !p+q p cuo
						{
							//如果析取式的前件与stmdp即可消解,则将后件保存的stmdp中
							j = 0;
							while (j < strlen( stmdp ))//依次比较每个字符
							{
								if (tmdrec[i].gs[j + 1] != stmdp[j])
									break;//有一个不相等则结束比较
								j++;
							}
 
							if (j >= strlen( stmdp ))  //如果比到最后仍然相等,则这二个可消解
							{
								strcpy( lastNiYou, tmdrec[i].niyou );
								tmdrec[nPosLitter].nUsed++;  //这个文字用过一次了
								tmdrec[i].nUsed++;  //这个析取式用过一次了
 
								strcpy( stmdp, tmdrec[i].gsLast );  //将次消解结果保存到推导序列中
								strcpy( tmdrec[np].gs, stmdp );  //将当前推出来的结果保存起来
								tmdrec[np].gsLast[0] = '\0';  //后件清空,保存当前条件
								setNiyou( tmdrec, np, ny01, nPosLitter, i, 0, 0, 1 );  //前提类型,有,无,未使用,不是条件
								nPosLitter = np;  //记录当前文字的序号
								np++;
								if (strcmp( result0, stmdp ) == 0)
								{
									isOk = 1;    //推出结论同条原是调节的下一轮
									break;
								}
							}
						}
						else if ((tmdrec[i].gsLast[0] == '!') && (stmdp[0] != '!') && (strlen( tmdrec[i].gsLast ) - strlen( stmdp ) == 1))		//a+!b  b dui
						{
							//如果析取式的后件与stmdp即可消解,则将前件保存到stmdp中
							j = 0;
							while (j < strlen( stmdp ))  //依次比较每一个字符
							{
								if (tmdrec[i].gsLast[j + 1] != stmdp[j])
									break;    //有一个不相等则结束比较
								j++;
							}
							if (j >= strlen( stmdp ))  //如果比到最后仍然相等,则这两个可消解
							{
								strcpy( lastNiYou, tmdrec[i].niyou );
								tmdrec[nPosLitter].nUsed++;  //这个文字用过一次了
								tmdrec[i].nUsed++;  //这个析取式用过一次了
 
								strcpy( stmdp, tmdrec[i].gs );  //将次消解结果保存到推导序列中
								strcpy( tmdrec[np].gs, stmdp );  //将当前推出来的结果保存起来
								tmdrec[np].gsLast[0] = '\0';  //后件清空,保存当前条件
								setNiyou( tmdrec, np, ny01, nPosLitter, i, 0, 0, 1 );  //前提类型,有,无,未使用,不是条件
								nPosLitter = np;  //记录当前文字的序号
								np++;
								if (strcmp( result0, stmdp ) == 0)
								{
									isOk = 1;    //推出结论同条原是调节的下一轮
									break;
								}
							}
						}
						else if ((tmdrec[i].gs[0] != '!') && (stmdp[0] == '!') && (strlen( tmdrec[i].gs ) - strlen( stmdp ) == -1))		//	p+q !p
						{
							//如果析取式的后件与stmdp即可消解,则将前件保存到stmdp中
							j = 0;
							while (j < strlen( tmdrec[i].gs ))  //依次比较每一个字符
							{
								if (stmdp[j + 1] != tmdrec[i].gs[j])
									break;    //有一个不相等则结束比较
								j++;
							}
							if (j >= strlen( tmdrec[i].gs ))
							{
								strcpy( lastNiYou, tmdrec[i].niyou );
								tmdrec[nPosLitter].nUsed++;  //这个文字用过一次了
								tmdrec[i].nUsed++;  //这个析取式用过一次了
 
								strcpy( stmdp, tmdrec[i].gsLast );  //将次消解结果保存到推导序列中
								strcpy( tmdrec[np].gs, stmdp );  //将当前推出来的结果保存起来
								tmdrec[np].gsLast[0] = '\0';  //后件清空,保存当前条件
								setNiyou( tmdrec, np, ny01, nPosLitter, i, 0, 0, 1 );  //前提类型,有,无,未使用,不是条件
								nPosLitter = np;  //记录当前文字的序号
								np++;
								if (strcmp( result0, stmdp ) == 0)
								{
									isOk = 1;    //推出结论同条原是调节的下一轮
									break;
								}
							}
 
						}
						else if ((tmdrec[i].gsLast[0] != '!') && (stmdp[0] == '!') && (strlen( tmdrec[i].gsLast ) - strlen( stmdp ) == -1))		//p+q !q
						{
							//如果析取式的后件与stmdp即可消解,则将前件保存到stmdp中
							j = 0;
							while (j < strlen( tmdrec[i].gsLast ))//依次比较每一个字符
							{
								if (stmdp[j + 1] != tmdrec[i].gsLast[j])
									break;    //有一个不相等则结束比较
								j++;
							}
							if (j >= strlen( tmdrec[i].gsLast ))//如果比到最后仍然相等,则这两个可消解
							{
								strcpy( lastNiYou, tmdrec[i].niyou );
								tmdrec[nPosLitter].nUsed++;	//这个文字用过一次了
								tmdrec[i].nUsed++;			//这个条件用过一次了
 
								strcpy( stmdp, tmdrec[i].gs );	    //将此中间结果保存到推导序列中
								strcpy( tmdrec[np].gs, stmdp );		//将当前推出来的结果保存起来
								tmdrec[np].gsLast[0] = '\0';		//后件清空,保存当前条件
								setNiyou( tmdrec, np, ny01, nPosLitter, i, 0, 0, 1 );//前提类型,有,无,未使用,不是条件式
								nPosLitter = np;		            //记录当前文字的序号
								np++;
								if (strcmp( result0, stmdp ) == 0)
								{
									isOk = 1;    //推出结论同原始条件的下一轮
									break;
								}
							}
						}
					}
				}
				i++;//判断下一个表达式是否为条件,是否为可推理的条件式
			}
		}
		if (isOk == 1)
			break;    //我推出来了,不要再找下一个文字了
	}
	if (isOk == 1)
		printf( "我推出来了,推理过程如下:\n" );
	else
		printf( "我推不出来,推理过程如下:\n" );
	printYsh( tmdrec, np );
}
}

上一篇:ROS入门21讲笔记(总结自用)


下一篇:语音信号特征处理--Fbank\MFCC