编译原理实验三:算符优先分析算法的设计与实现

news2024/11/16 12:52:03

实验三 算符优先分析算法的设计与实现

一、 实验目的
根据算符优先分析法,对表达式进行语法分析,使其能够判断一个表达式是否正确。通过算符优先分析方法的实现,加深对自下而上语法分析方法的理解。

二、 实验要求
1、输入文法。可以是如下算术表达式的文法(你可以根据需要适当改变):

E→E+T|E-T|T
T→T*F|T/F|F
F→(E)|i

2、对给定表达式进行分析,输出表达式正确与否的判断。
程序输入/输出示例:

输入:1+2;
输出:正确
输入:(1+2)/3+4-(5+6/7);
输出:正确
输入:((1-2)/3+4
输出:错误
输入:1+2-3+(*4/5)
输出:错误

三、实验步骤
1、参考数据结构

char *VN=0,*VT=0;//非终结符和终结符数组
char firstvt[N][N],lastvt[N][N],table[N][N];
typedef struct   //符号对(P,a)
{
	char Vn;
	char Vt;
} VN_VT;
typedef struct  //栈
{
    VN_VT *top;
	     VN_VT *bottom;
	     int  size;
}stack;

2、根据文法求FIRSTVT集和LASTVT集
给定一个上下文无关文法,根据算法设计一个程序,求文法中每个非终结符的FirstVT 集和LastVT 集。
算符描述如下:

/*求 FirstVT 集的算法*/ 
PROCEDURE insert(P,a); 
IF not F[P,a] then   
begin  
        F[P,a] = true; //(P,a)进栈  
end;  
Procedure FirstVT; 
Begin 
for 对每个非终结符 P和终结符 a do 
   F[P,a] = false 
for 对每个形如 P		a…或 P→Qa…的产生式 do 
Insert(P,a) 
while stack  非空 
begin 
栈顶项出栈,记为(Q,a) 
for  对每条形如 P→Q…的产生式 do 
         insert(P,a) 
end; 
end.

同理,可构造计算LASTVT的算法。
3、构造算符优先分析表
依据文法和求出的相应FirstVT和 LastVT 集生成算符优先分析表。

算法描述如下:
for  每个形如 P->X1X2…Xn的产生式  do 
  for i =1 to n-1 do 
  begin 
        if Xi和Xi+1都是终结符 then  
           Xi   =   Xi+1 
        if i<= n-2, Xi和Xi+2 是终结符, 但Xi+1 为非终结符 then 
           Xi  = Xi+2 
        if Xi为终结符, Xi+1为非终结符 then   
             for FirstVT 中的每个元素 a do 
                  Xi  <  a ; 
        if Xi为非终结符, Xi+1为终结符 then 
             for LastVT 中的每个元素 a do 
                  a  >  Xi+1 ; 
  end

4、构造总控程序
算法描述如下:

  stack S;
   k = 1;  //符号栈S的使用深度
   S[k] = ‘#’
   REPEAT
       把下一个输入符号读进a中;
       If S[k]   VT   then  j = k  else  j = k-1;
       While S[j] > a  do
           Begin
           Repeat
               Q = S[j];
               if  S[j-1]   VT  then  j = j-1  else   j = j-2
           until  S[j] < Q;
           把S[j+1]…S[k]归约为某个N,并输出归约为哪个符号;
           K = j+1;
           S[k] = N;
           end of while
       if S[j] < a  or  S[j] = a  then
           begin  k = k+1; S[k] = a      end
        else  error //调用出错诊察程序
    until a = ‘#’

5、对给定的表达式,给出准确与否的分析过程
6、给出表达式的计算结果。(本步骤可选作)

代码

#include <bits/stdc++.h>
using namespace std;

//定义一个非终结符的结构体 
typedef struct{
	char left;//非终结符 
	int rcount;//右边式子数量 
	char right[200][200];//右边 
	int fvtcount;
	int lvtcount;
	char firstvt[200];//firstvt集合 
	char lastvt[200];//lastvt集合 
}grammar;
grammar gramSet[200];//产生式集 

//变量的定义 
int gramcount=0;//产生式数量初始化 
int tersymcount=0;//终结符数量初始化 
int nontercount=0;//非终结符数量初始化 


char terSymbol[200];//终结符号
char nonter[200];//非终结符号
char table[200][200];//分析表
char test[500];//要处理的字符串 

map<char, bool> isfvted;//该非终结符是否已经求过其firstvt集
map<char, bool> islvted;//是否求过lastvt集 

 
//函数的定义
void read();//读入数据 
bool judgesymbol(char ch);//判断终结符和非终结符
void symbolsort(char ch);//字符归类
void Firstvt(char sym);//求sym的first集 
void Addfvt(char sym, char ch);//firstvt(ch)并入firstvt(sym) 
void Lastvt(char sym);//求sym的lastvt集 
void Addlvt(char sym, char  ch);//lastvt(ch)并入lastvt(sym) 
void Table();//创建算符优先分析表 
void Show();//打印分析表 
void MainControl();//总控程序


int main(int argc, char** argv) {
	cout<<"输入文法: 以'#'结束"<<endl;
	read();
	cout<<"输入串(以'#'结束)为:"<<endl;
	cin>>test;
	for(int i=0;i<strlen(test);i++)//将输入的数字替换成i,便于分析 
	{
		if(test[i]>='0'&&test[i]<='9')
		   test[i]='i';
	}
	for(int i=0;i<gramcount;i++)
	{
		Firstvt(gramSet[i].left);
	}
	for(int i=0;i<gramcount;i++)
	{
		Lastvt(gramSet[i].left);
	}
	cout<<endl;
	cout<<"FirstVT集如下:"<<endl;
	for(int i=0;i<gramcount;i++)
	{
		cout<<"FirstVT("<<gramSet[i].left<<")"<<": ";
		for(int j=0;j<gramSet[i].fvtcount;j++)
	     	cout<<gramSet[i].firstvt[j]<<" ";
		cout<<endl;
	}
	cout<<endl;
	cout<<"LastVT集如下:"<<endl;
	for(int i=0;i<gramcount;i++)
	{
		cout<<"LastVT("<<gramSet[i].left<<")"<<": ";
		for(int j=0;j<gramSet[i].lvtcount;j++)
	     	cout<<gramSet[i].lastvt[j]<<" ";
		cout<<endl;
	}
	cout<<endl;
	cout<<"算符优先分析表如下:"<<endl;
	Table();
	Show();
	cout<<endl;
	cout<<"分析步骤如下:"<<endl;
	MainControl();

	return 0;
}

//读入数据 
void read()
{
	char str[100];
	while(1)
	{
		cin>>str;
		if(str[0]=='#')
		   break;
		gramSet[gramcount].left=str[0];
		symbolsort(str[0]);//处理左边 
		for(int i=3;i<strlen(str);i++)//右边从str[3]处开始;str的0-2位=‘E->’ 
		{
			int j=0;
			char ter[100];
			while(str[i]!='|'&&str[i]!='\0')
			{
				symbolsort(str[i]);//处理右边 
				 ter[j++]=str[i++];	
			}
			ter[j]='\0';
			strcpy(gramSet[gramcount].right[gramSet[gramcount].rcount],ter);
			gramSet[gramcount].rcount++;
		} 
		gramcount++;	
	}
}
//判断终结符和非终结符
bool judgesymbol(char ch)
{
	if(ch>='A'&&ch<='Z')
		return false;
    return true;
}
//字符归类
void symbolsort(char ch)
{
	if(!judgesymbol(ch))
	{
		int flag=0;
		for (int i= 0;i<nontercount; i++)
		{
			if (ch==nonter[i])
			{
				flag=1;
				break;//已在非终结符集中 
			}
		}
		if(flag==0)
		{
			nonter[nontercount++]=ch;
			isfvted.insert(pair<char, bool>(ch, false));
			islvted.insert(pair<char,bool>(ch, false));
		}
	}
	else
	{
		int flag=0;
		for (int i=0;i<tersymcount; i++)
		{
			if (ch==terSymbol[i])
			{
				flag = 1;
				break;//已在终结符集中 
			}
		}
		if (flag==0)
		{
			terSymbol[tersymcount++]=ch;
		}
	}
}
//求FirstVT集
void Firstvt(char sym)
{
	int i;
	for(i=0;i<gramcount;i++)
	{
		if(gramSet[i].left==sym)
		   break;//找到了该非终结符的位置 
	} 
	//处理每个产生式 
	for(int j=0;j<gramSet[i].rcount;j++)
	{	 
		char ch=gramSet[i].right[j][0];//获取右部第一个字符 
		
		//字符为终结符
		if(judgesymbol(ch))
		{
			int flag=0;
			for (int n=0; n<gramSet[i].fvtcount;n++)
			{
				if (gramSet[i].firstvt[n] == ch)
				{
					flag = 1;//已在firstvt集中 
					break;
				}
			}
			if(flag==0){
				gramSet[i].firstvt[gramSet[i].fvtcount++]=ch;//把终结符加进FIRSTVT集 
			}	
		}
		//字符ch为非终结符
		else 
		{
			if(ch!=sym)
			{
		    	//还没有求过ch的firstvt集 
			  if(!isfvted[ch])
				  Firstvt(ch);
		     //firstvt(ch)并入firstvt(sym) 
			Addfvt(sym,ch);	
			}
			
			//P->Qa的情况 
			char ch1=gramSet[i].right[j][1];
			if(judgesymbol(ch1))
			{
			    int flag=0;
			    for (int n=0; n<gramSet[i].fvtcount;n++)
			    {
				if (gramSet[i].firstvt[n] == ch1)
				   {
					flag = 1;//已在firstvt集中 
					break;
			    	}
		     	}
			   if(flag==0)
				gramSet[i].firstvt[gramSet[i].fvtcount++]=ch1;//把终结符加进FIRSTVT集 
			}
			   		
		}	
	
	}
	isfvted[sym]=true;
}
//firstvt(ch)并入firstvt(sym)  
void Addfvt(char sym,char ch)
{
	int s1,s2;
	int c1,c2;
	//找到sym的位置 
	for(s1=0;s1<gramcount;s1++)
	{
		if(gramSet[s1].left==sym)
		   break; 
	}
	//找到ch的位置 
	for(c1=0;c1<gramcount;c1++)
	{
		if(gramSet[c1].left==ch)
		   break; 
	}
	for(c2=0;c2<gramSet[c1].fvtcount;c2++)
	{
		int flag=0;
		for(s2=0;s2<gramSet[s1].fvtcount;s2++)
		{
			if(gramSet[s1].firstvt[s2]==gramSet[c1].firstvt[c2])
			{
				flag=1;
				break;//已存在 
		    } 	 
		}
		//firstvt(ch)并入firstvt(sym) 
		if(flag==0)
		{	
		gramSet[s1].firstvt[gramSet[s1].fvtcount++]=gramSet[c1].firstvt[c2];
		}
	
	}
}
//求sym的lastvt集
void Lastvt(char sym)
 {
 	int i;
 	for(i=0;i<gramcount;i++)
	 {
 		if(gramSet[i].left==sym)
 	       break;
	 }
	//处理每个产生式 
	for(int j=0;j<gramSet[i].rcount;j++)
	{	 
	    int length=strlen(gramSet[i].right[j]);
	    int last=length-1;
		char ch=gramSet[i].right[j][last];//获取右部最后一个字符 
		
		//字符为终结符
		if(judgesymbol(ch))
		{
			int flag=0;
			for (int n=0; n<gramSet[i].lvtcount;n++)
			{
				if (gramSet[i].lastvt[n] == ch)
				{
					flag = 1;//已在lastvt集中 
					break;
				}
			}
			if(flag==0){
				gramSet[i].lastvt[gramSet[i].lvtcount++]=ch;//把终结符加进FIRSTVT集 
			}	
		}
		//字符ch为非终结符
		else 
		{
			if(ch!=sym)
			{
			//还没有求过ch的lastvt集 
			if(!islvted[ch])
				Lastvt(ch);
		   //lastvt(ch)并入lastvt(sym) 
            Addlvt(sym, ch);	
			}
			//P->aQ的情况 
			if(last!=0)
			{
				char ch1=gramSet[i].right[j][last-1];//倒数第二位 
			    if(judgesymbol(ch1))
			   {
			      int flag=0;
			      for (int n=0; n<gramSet[i].lvtcount;n++)
			      {
				     if (gramSet[i].lastvt[n] == ch1)
				     {
					    flag = 1;//已在lastvt集中 
					    break;
			    	 }
		     	  }
			      if(flag==0)
				      gramSet[i].lastvt[gramSet[i].lvtcount++]=ch1;//把终结符加进LASTVT集 
		     	}
			}		   		
		}	
	}
	islvted[sym]=true;
 }
//lastvt(ch)并入lastvt(sym) 
void Addlvt(char sym, char  ch)
{
	int  s1,s2;
	int  c1,c2;
	for(s1=0;s1<gramcount;s1++)//找到sym的位置 
	{
		if(gramSet[s1].left==sym)
		   break;
	}
	for(c1=0;c1<gramcount;c1++)//找到ch的位置 
	{
		if(gramSet[c1].left==ch)
		   break;
	}
	for(c2=0;c2<gramSet[c1].lvtcount;c2++)
	{
		int flag=0;
		for(s2=0;s2<gramSet[s1].lvtcount;s2++)
		{
			if(gramSet[s1].lastvt[s2]==gramSet[c1].lastvt[c2])
			{
				flag=1;
				break;
			}
		}
		if(flag==0)
		   gramSet[s1].lastvt[gramSet[s1].lvtcount++]=gramSet[c1].lastvt[c2];
	
	}
}

//创建分析表 
void Table()
{
	int row=tersymcount+2;//优先表的行数和列数 
   
	//分析表初始化
	table[0][0]=' ';
	table[0][row-1]='#';
	table[row-1][0]='#';
	table[row-1][row-1]='=';
	//第0行 
	int j=1;
	for(int i=0;i<tersymcount;i++)
		 table[0][j++]=terSymbol[i];	
	//第0列 
	int k=1;
	for(int i=0;i<tersymcount;i++)
		 table[k++][0]=terSymbol[i];
	
	int p;	 

    //开始分析,填充表的内容
    //对#特殊处理
	for(int i=1;i<row;i++) //分析#所在的一行 
	{
		for(int j=0;j<gramSet[0].fvtcount;j++)
		{
			if(table[0][i]==gramSet[0].firstvt[j])
			{
				table[row-1][i]='<';
				break;
			}
		}
	}
	for(int i=1;i<row;i++) //分析#所在的一列 
	{
		for(int j=0;j<gramSet[0].lvtcount;j++)
		{
			if(table[i][0]==gramSet[0].lastvt[j])
			{
				table[i][row-1]='>';
				break;
			}
		}
	}
	
	 //遍历所有产生式 
    for(int g=0;g<gramcount;g++)
    {
    	//遍历一个非终结符的所有产生式 
    	for(int i=0;i<gramSet[g].rcount;i++)
    	{
    		int n=strlen(gramSet[g].right[i]);
    		for(int j=0;j<n-1;j++)
    		{
    			char xi=gramSet[g].right[i][j];
    			char xi1=gramSet[g].right[i][j+1];
    			
    			//Xi和Xi+1都是终结符 
				if(judgesymbol(xi)&&judgesymbol(xi1))
				{
					for(int r=1;r<row;r++)
					{
						if(table[r][0]==xi)
						{
							p=r;//找到xi的位置 
							break;
						}
					}
					for(int l=1;l<row;l++)
					{
						if(table[0][l]==xi1)//找到Xi+1的位置
						   {
						   	table[p][l]='='; 
						   	break;
						   }
					}
				}
				if(j<n-2)
				{
					char xi2=gramSet[g].right[i][j+2];
					if(!judgesymbol(xi1)&&judgesymbol(xi)&&judgesymbol(xi2))
					{
						  for(int r=1;r<row;r++)
				     	{
						   if(table[r][0]==xi)
						  {
							p=r;//找到xi的位置 
							break;
					    	}
					    }
					     for(int l=1;l<row;l++)
					    {
						   if(table[0][l]==xi2)//找到Xi+1的位置
						   {
						   	table[p][l]='='; 
						   	break;
						   }
					    }
					}
				}
				//Xi为终结符, Xi+1为非终结符
				if(!judgesymbol(xi1)&&judgesymbol(xi))
				{
					int pos;
					for(pos=0;pos<gramcount;pos++)
					{
						if(gramSet[pos].left==xi1)
						     break;
					}
				    for(int r=1;r<row;r++)
				    {
					    if(table[r][0]==xi)
						{
							p=r;//找到xi的位置 (第p行第0列) 
							break;
					   	}
				    }
					for(int x=0;x<gramSet[pos].fvtcount;x++)//对于firstvt中的每一个元素 
					{
						char a=gramSet[pos].firstvt[x];
						 
					     for(int l=1;l<row;l++)
					     {
						   if(table[0][l]==a)//找到a的位置(第0行第l列) 
						   {
						   	table[p][l]='<'; 
						   	break;
						   }
					     }
					}
				}
				//if Xi为非终结符, Xi+1为终结符
				if(!judgesymbol(xi)&&judgesymbol(xi1))
				{
					int pos;
					for(pos=0;pos<gramcount;pos++)
					{
						if(gramSet[pos].left==xi)
						     break;
					}
					for(int r=1;r<row;r++)
				   {
					   if(table[0][r]==xi1)
					    {
						   p=r;//找到xi1的位置(第0行,p列) 
					   	   break;
					   	}
					}
					for(int x=0;x<gramSet[pos].lvtcount;x++)//对于lastvt中的每一个元素 
					{
						char a=gramSet[pos].lastvt[x];
						  
					     for(int l=1;l<row;l++)
					     {
						   if(table[l][0]==a)//找到a的位置(第l行,第0列) 
						   {
						   	table[l][p]='>'; 
						   	break;
						   }
					     }
					}
				}
			}
		}
	}

 } 
 
//展示分析表
void Show()
  {
  	int row=tersymcount+2;//优先表的行数和列数 

	//打印表的内容
	for(int k=0;k<row*11;k++)
		    cout<<"-";
	cout<<endl;
  	for(int i=0;i<row;i++)
  	{
  		for(int j=0;j<row;j++)
  		{
  			cout<<table[i][j];
  			for(int k=0;k<9;k++)
  			     cout<<" ";
  		    cout<<"|";
		}
		cout<<endl;
		 for(int k=0;k<row*11;k++)
		     cout<<"-";
		cout<<endl;
	}
  }
  //比较s和a优先级的函数 
char prio(char s,char a)
{
	int row=tersymcount+2;
	int i;
	int j;
	for(i=1;i<row;i++)
	{
		if(table[i][0]==s)
		   break;
	}
	for(j=1;j<row;j++)
	{
		if(table[0][j]==a)
		   break;
	}
	if(table[i][j]=='>')
	    return '>';
	else if(table [i][j]=='<')
	    return '<';
	else if(table[i][j]=='=')
	    return '=';
	else
	    return 'e';
 } 
//总控程序
void MainControl()
{
	int flag=1;
	int row=tersymcount+2;
	int j;
	string str[100];//存储动作
	str[0]="预备"; 
    char s[100];//符号栈
    for(int i=0;i<100;i++)
        s[i]='\0';
	int k;//符号栈的使用深度 
	k=0;
	s[k] = '#';
	
	char a;//存放输入串当前分析符号 
	int pos=0;//定位a的位置 
	int step=0;//步骤序号 
	cout << endl;
	
	cout<<"步骤\t符号栈\t\t\t输入串\t\t\t\t动作"<<endl;
	while(flag==1)
	{
		cout<<step++<<"\t";//打印步骤序号
		
		cout<<s<<"\t\t\t";//打印当前符号栈 
		
		for(int i=pos;i<strlen(test);i++)//打印当前输入串 
			cout<<test[i];
		cout<<"\t\t\t\t";
		cout<<str[step-1]<<endl;

		a=test[pos];
		if(judgesymbol(s[k]))
			j=k;
		else 
		    j=k-1;
	
		if(prio(s[j],a)=='>')
		{
			string strkj;//要归约的式子 
			while(1)
			{
			   char q=s[j];
			   if(judgesymbol(s[j-1]))
			      j=j-1;
			   else
			      j=j-2;
		   	if(prio(s[j],q)=='<')
			   break;	
			}
			//把S[j+1]…S[k]归约为某个N,并输出归约为哪个符号;
			char N;
			int flag1=1;
			int flag2=1;
			int flag3;
			for(int K=j+1;K<=k;K++)
			    strkj+=s[K];
			int max=strkj.length();//要归约式子的长度 
			for(int g=gramcount-1;g>=0;g--)
			{
				for(int g1=0;g1<gramSet[g].rcount;g1++)//遍历某非终结符每个产生式 
				{
					string gram1=gramSet[g].right[g1];
					int m=gram1.length();//右部产生式的长度
			   //右部产生式gram1与strkj需要非终结符对非终结符,终结符对终结符且终结符相等才能归约 
					if(max==m)//首先判断长度是否相等 
					{
						//判断一一对应关系
						int p;
						for(p=0;p<max;p++)
						{
							if(judgesymbol(strkj[p]))//如果p位置是终结符,则需要相等 
							  {
							  	if(strkj[p]==gram1[p])
							  	    flag3=1;
							  	else 
							  	   flag3=0;
							   } 
							else//p位置是非终结符,则需要对应 
							{
								if(!judgesymbol(gram1[p]))
								    flag3=1;
								else 
								  flag3=0;
							}
							if(flag3==0)
							   break;
						 } 
					 if(flag3==1) //一一对应,则可以跳出循环 
						{
						N=gramSet[g].left;
						 flag1=0;
						 flag2=0;
						}	 
					}
					if(flag2==0)
					   break;		
				}
				if(flag1==0)
				  break;
			 } 
			if(flag1==0)//说明可归约 
			{
				for(int K=j+1;K<=k;K++)//将s[j+1]...s[k]移除 
				   s[K]='\0';
				k=j+1;
			   s[k]=N;
			   str[step]="归约"; 	
			}
			else
			  flag=-1;//说明不可归约,语法错误 
		}
	
	  else if(prio(s[j],a)=='<'||prio(s[j],a)=='=')
		{
			k++;
			s[k]=a;
			str[step]="移进"; 
			pos++;
		}
	  else
		  flag=-1;
		  	  
	  char start=gramSet[0].left;
	  if(a=='#'&&!judgesymbol(s[k])&&k==1)
	  {
	  	cout<<step++<<"\t";//打印最后步骤
		
		cout<<s<<"\t\t\t";//打印当前符号栈 
		
		for(int i=pos;i<strlen(test);i++)//打印当前输入串 
			cout<<test[i];
		cout<<"\t\t\t\t";
		cout<<str[step-1]<<endl;
		 flag=0;
	  }	
	   	
    } 
    if(flag==0)
        cout<<"success!表达式正确!"<<endl;
    else if(flag==-1)
       cout<<"error!表达式不正确!"<<endl;
}


结果

测试数据:
文法:

E->E+T|E-T|T
T->T*F|T/F|F
F->(E)|i
#

测试输入1:

i*i+i#

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/78488.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java 图片上传后为什么会自动旋转90度?

问题&#xff1a; 用户反馈上传后的图片方向不对&#xff0c;起初怀疑是本身图片方向有问题&#xff0c;但是用windows图片查看器打开图片方向是"正常"显示的? 分析&#xff1a; windows默认的图片查看器已经帮我们自动旋转展示了&#xff0c;我们在手机横拍或者扫…

【Vue核心】7.事件处理

事件处理的基本使用 绑定监听 v-on:xxx“fun” xxx“fun” xxx“fun(参数)” 默认事件形参: event 隐含属性对象: $event 绑定方法说明 使用v-on:xxx 或xxx绑定事件,其中xxx是事件名;事件的回调需要配置在methods对象中,最终公在vm上;methods中配置的函数,不要用箭头函…

python 调试IGH库

如何通过python来调试IGH的库呢&#xff1f; 可以使用如下的代码&#xff0c;测试请求主站&#xff0c;把主站变成激活状态。其他的函数也可以类似的一步一步调用。 结果如下&#xff1a; from ctypes import * ighCDLL("/home/cheni/lichuan_bujin/libethercat.so&quo…

开传奇大概需要什么条件

《热血传奇》是盛趣游戏2001年推出的一款大型多人在线角色扮演游戏&#xff08;MMORPG&#xff09;。 该游戏具有战士、魔法师和道士三种职业&#xff0c;所有情节的发生、经验值取得以及各种打猎、采矿等活动都是在网络上即时发生。 《热血传奇》包括白天、黑夜、贸易、物品等…

c++多模块化划分算法MMM(单链接、全链接、均链接)

文章目录题目1c代码一、实验目的二、实验描述3.1 题目13.1.1 单链接3.1.2 全链接3.1.3 均值链接3.1.4 划分结果统计&#xff1a;3.2 题目23.2.1 单链接3.2.2 全链接3.2.3 均值链接3.2.4 划分结果统计&#xff1a;题目2c代码github地址 代码地址 题目1c代码 #include<cstdi…

关于Servlet编程(2)

1.常用类的关键API介绍 Servlet中常见的类有三个.介绍过了HttpServlet类.我们再来看看另外两个. HttpServletRequest 这个类对应到发送的HTTP请求. 方法描述String getProtocol()返回请求协议的名称和版本String getMethod()返回请求的 HTTP 方法的名称 (GET,POST 或 PUT)S…

java计算机毕业设计ssm医院病人信息管理系统60k18(附源码、数据库)

java计算机毕业设计ssm医院病人信息管理系统60k18&#xff08;附源码、数据库&#xff09; 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#…

summernote富文本编辑器和jquery.validate冲突报错的解决方案

先看问题: 当我在富文本输入并移出鼠标焦点的时候, 控制台抛出错误Cannot read properties of undefined (reading replace), 而导致jquery.validate无法对其他表单组件进行校验 1.定位问题: jquery.validate的初始化是监听了表单$("#addOrEditForm").validate(),…

Nacos的服务注册之服务端

上节讲到了nacos的客户端,通过把实例信息封装成instance,调用服务端的接口:/instance,进行注册. 接下来,我们一起看看服务端是怎么处理客户端发来的请求的. 服务端 在nacos-naming这个模块中,在这个模块里边有一个InstanceController 其中在com.alibaba.nacos.naming.contro…

Netty_03_ByteBuf和网络中拆包粘包问题及其解决

文章目录一、前言二、ByteBuf&#xff08;Netty API中定义的数据类型&#xff09;2.1 ByteBuf2.1.1 ByteBuf创建的方法有两种2.1.2 ByteBuf的存储结构2.1.3 ByteBuf中常用的方法APIReader相关方法Write相关方法Write可能导致扩容2.2 ByteBuf代码(演示读写指针移动和扩容)2.2.1 …

RabbitMQ:基础概述

RabbitMQ 是一个消息中间件&#xff0c;它接收消息并且转发&#xff0c;是“消费-生产者模型”的一个典型的代表&#xff0c;一端往消息队列中不断的写入消息&#xff0c;而另一端则可以读取或者订阅队列中的消息。 RabbitMQ 于 2007 年发布&#xff0c;由 erlang 语言进行开源…

37_软件I2C通信实验

目录 I2C通信协议 多主机I2C总线系统结构 I2C协议 应答信号ACK 数据有效性 数据传输 I2C设备地址 I2C通讯整个过程 硬件连接 EEPROM(24C02) 24C02字节写时序 24C02字节读时序 实验源码 I2C通信协议 I2C(IIC,Inter-Integrated Circuit),两线式串行总线,由PHILIPS公…

ATtiny13与Proteus仿真-ADC仿真

ADC仿真 1、ADC介绍 ATtiny13的ADC有如下特点: 10位分辨率0.5 LSB 积分非线性 2 LSB 绝对精度13 - 260 μs 转换时间在最高分辨率下高达 15 kSPS四个多路复用单端输入通道ADC 结果读数的可选左调整0 - VCC ADC 输入电压范围可选择的 1.1V ADC 参考电压自由运行或单一转换模式…

[附源码]计算机毕业设计家庭医生签约服务管理系统Springboot程序

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

dmb ish osh

转自&#xff1a;原理和实战解析Linux中如何正确地使用内存屏障 圈里流传着一句话“珍爱生命&#xff0c;远离屏障”&#xff0c;这足以说明内存屏障是一个相当晦涩和难以准确把握的东西。使用过弱的屏障&#xff0c;会导致软件不稳定。使用过强的屏障&#xff0c;会引起性能问…

c语言篇(动态内存管理)

前言&#xff1a; 对于数据的存储我们可以静态存储&#xff0c;也可以动态存储&#xff0c;两种方式都有自己特有的好处&#xff0c;这篇文章教我们如和进行动态的数据存储&#xff01;&#xff01;&#xff01;&#xff01; &#x1f49e; &#x1f49e; 欢迎来到小马学习代码…

自动驾驶之单目3D目标检测TensorRT调研

目前在github上只能找到2个项目 TensorRT-CenterNet-3D tkDNN 两者都是使用CenterNet&#xff0c;但第1个基于TensorRT5,无法与当前最新的TensorRT6和TensorRT7兼容。经测试&#xff0c;第1个无法在XavierJetpack 4.3/4.4上部署&#xff0c;因此选择部署第二个tkDNN。 1. 基本…

Python学习基础笔记三十八——time模块

1、time模块&#xff1a;和时间有关系的&#xff0c;我们就用到了时间模块&#xff1a; import timeprint(time.time()) #获得当前时间戳 2、表示时间的三种方式&#xff1a; 在Python中&#xff0c;通常用三种方式来表示时间&#xff1a;时间戳、元组(struct_time)、格式…

LeetCode刷题复盘笔记—一文搞懂动态规划之337. 打家劫舍 III问题(动态规划系列第十九篇)

今日主要总结一下动态规划完全背包的一道题目&#xff0c;337. 打家劫舍 III 题目&#xff1a;337. 打家劫舍 III Leetcode题目地址 题目描述&#xff1a; 小偷又发现了一个新的可行窃的地区。这个地区只有一个入口&#xff0c;我们称之为 root 。 除了 root 之外&#xff0…