命题逻辑之合式公式的判断

如何用编程判断一个字符串是否是合适公式呢?以下提供两种思路:

PS:本文中 !否定,*合取,+析取,-条件,=双条件

一、老师的STL精简版本

简要步骤:

①把原子命题全部转换为字符1

②将特定字串(如(1)、!1、1+1等)转换为字符1

C++代码:

#include <iostream>
#include <cstring>
using namespace std;

int rps(string &str,string ss,string sd,int runum)
{
	int i=str.length(),p;

	while(p=str.find(ss)+1)
		str.replace(p-1, ss.length(), sd);

	if(str.length()!=i)
		cout<<"使用规则"<<runum<<"后:"<<str<<endl;

	return str.length()-i;
}

int main()
{
	string str,strtmp;
	cout<<"输入提示:"<<endl;

	while(cin>>str)
	{
		strtmp=str;

		for(int i=0; i<str.length(); i++)
			if((str[i]>='a'&&str[i]<='z')||str[i]=='0')
				str[i]='1';

		cout<<"使用规则1后:"<<str<<endl;

		while(rps(str,"!1","1",2)||rps(str,"(1)","1",2)||rps(str,"1+1","1",3)||rps(str,"1*1","1",3)||rps(str,"1-1","1",3)||rps(str,"1=1","1",3));

		if(str=="1")
			cout<<strtmp<<" is valid!"<<endl;
		else
			cout<<strtmp<<" is invalid!"<<endl;
	}
	
	return 0;
}

二、我自己的版本

步骤:

①处理括号,遇到括号则递归处理

②处理否定,把合法的!删除

③判断最后的字符串:即奇数位是原子命题,偶数位是联结词(除了!)

C++代码:

// !否定,*合取,+析取,-条件,=双条件
#include <iostream>
#include <cstring>
using namespace std;

bool isAtomic(char c)	//判断是否为原子命题
{
	if(isalpha(c)) return true;
	if(c == '0' || c == '1') return true;
	return false;
}

bool isConnect(char c)		//判断是否为联结词(!除外) 
{
	if(c == '*' || c == '+' || c == '-' || c == '=' ) return true;
	return false;
}

bool isLegal(string str)	//公式是否合法
{
	if(str.length() < 1) return false;				//没有字符为非法

	//【处理括号】
	int pLeft = 0,									// ( 的位置
	    pRight = 0,									// ) 的位置
	    pCount = 0;									//当前出现的(的个数 - 当前出现的)的个数

	for(size_t i = 0; i < str.length(); ++i)
	{
		if(str[i] == '(') pLeft = i;				//找到第一个(
		else continue;

		for(; i < str.length(); ++i)				//百度:string.length()的时间效率是O(1) 
		{
			if(str[i] == '(') ++pCount;
			else if(str[i] == ')')
			{
				--pCount;
				if(pCount == 0)						//若是对应的)
				{
					pRight = i;

					if(isLegal(str.substr(pLeft + 1, pRight - pLeft - 1)) == false)	//递归地对括号内的内容进行判断
						return false;
					else	//将(变为1,删除)和括号里的内容
					{
						str.at(pLeft) = '1';
						str.erase(str.begin() + pLeft + 1, str.begin() + pRight + 1);
						i = pLeft;			//i变为pLeft
						break;
					}
				}
			}
		}
		if(pCount != 0) return false;
	}

	//【处理否定】
	for(size_t i = 0; i < str.length(); ++i)
		if(str[i] == '!')
		{
			if(i == str.length() - 1) return false;	//!出现在最后一位

			if(!isConnect(str[i+1]))				//!后面不是联结词 
			{
				str.erase(str.begin() + i);			//删除!
				--i;
			}
			else return false;
		}

	//【判断其它联结词】
	for(size_t i = 0; i < str.length(); ++i)			//第奇数个字符是原子命题,第偶数个是联结词 
	{
		if(i&1 && !isConnect(str[i])) return false;
		if(!i&1 && !isAtomic(str[i])) return false;
	}

	return true;
}

int main()
{
	cout<<"请输入公式,!否定,*合取,+析取,-条件,=双条件:"<<endl;
	string input;
	while(cin>>input)		//循环输入+判断 
	{
		if(isLegal(input))
			cout<<input<<" is legal."<<endl;
		else cout<<input<<" is invalid."<<endl;
	}

	return 0;
}
注释比较详细,大家慢慢看喽~
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值