FZU《C语言程序综合设计》

一年前的玩意。

老是有人找我要。。一年前写得这么搓都不敢拿出来。。。。

但是好多人要啊。。。。。直接发blog,省得下次还要发压缩文件。。

就不要吐槽我代码烂了,我也觉得很烂,至少现在看来确实很烂。。我又懒得改 - -||||||||||||||||||||||||

代码仅供参考。给学弟学妹们谋福利~


(一)

实验目的:

学习用指针构造链表,操作链表

实验内容:

    输入两个非降序列,转换成两个非升序列,合并成一个非升序列。

基本要求:

用链表实现。

完成解题报告。

分析(解题思路及流程图):

题目要求使用链表来解题,对于一些不熟练链表操作的同学可能会比较困难。在建立两个链表后,我进行了合并,然后对每一个进行比较大小,最后输出结果。个人认为此题挺简单的。

心得:做关于指针的题目,需要耐心和细心。本题对链表的熟悉度要求较高,熟悉链表后,这题就是一道水题了。


测试方案:输入两个非降序列,转换成两个非升序列,验证结果。


输入:5  8 7 6 5 4  
4 5 4 3 2
输出:8 7 6 5 5 4 4 3 2


输入:5 8 7 6 5 4 
5 6 5 4 3 2
输出:8 7 6 6 5 5 4 4 3 2


#include<Stdio.h>
#include<stdlib.h>
#define LEN sizeof(struct sequence)
struct sequence{
	int a;
	struct sequence *next;
};

struct sequence *creat(int m)
{
	struct sequence *head,*p1,*p2;
	int n=0;
	p1=p2=(struct sequence *)malloc (LEN);
	scanf("%d",&p1->a);
	head=NULL;
	while(n<m){         
		n++;
		if(n==1) head=p1;
		else p2->next=p1;
		p2=p1;
		p1=(struct sequence *)malloc (LEN);
		if(m==n)break;
		scanf("%d",&p1->a);
	}
	p2->next=NULL;
	return head;
	free (p1);free (p2);free (head);		
}

void print(struct sequence *head){    //输出结果
	struct sequence *p;
	p=head;
	while(p!=NULL){	
		printf("%d ",p->a);
		p=p->next;
	}
}

void compare(struct sequence *head)//比较大小
{
	struct sequence *i,*j,*max;//i指向下一个链表,j链接下一个的地址进行比较排序,flag进行标记j的地址,max最大值查找
	int temp;
	for(i=head;i!=NULL;i=i->next)
	{
		max=i;
		for(j=i->next;j!=NULL;j=j->next)
		{
			if((j->a)>(max->a))			
				max=j;			
		}
		if(max!=i) {
			temp=i->a;
			i->a=max->a;
			max->a=temp;
		}		
	}
	print (head);
}

void connect(struct sequence *heada,struct sequence *headb)//合并链表
{
	struct sequence *p;
	p=heada;
    while(p->next!=NULL){	
		p=p->next;
	}
	p->next=headb;
compare(heada);
}

void main()
{
	int n,m;
	struct sequence *heada,*headb;
	scanf("%d",&n);
	heada=creat(n);
    scanf("%d",&m);
	headb=creat(m);
	connect(heada,headb);	
}

(二)

 实验目的:

     学习数组的应用。

 实验内容:

     高精度四则运算(200位以内)

 基本要求:

     对于给定的大整数,做相关运算。

     必做+(加法) -(减法)  *(乘法)

     选做: /(除法)%  ( 求余 )  gcd(最大公约数) lcm(最小公倍数)

 完成解题报告。

分析(解题思路及流程图):

由于此题要求的是200位数,所以要用数组。

首先,我进行判断两个数的大小,由于我输入的是字符串,所以比较位数和用strcmp是很简单的一件事情。然后将大的数倒序存进数组a,小的数存进数组b。由于是倒着存的,直接实现了末位对齐。加法减法就十分容易实现了。

加法主要是一个大于10,下一位+1的操作。

减法则需要用到前面的比较大小的结果,如果输入的第一个数较小,则需要输出个“-”。然后进行减法操作。如果正在想减的两个数第二个数大的话,则需要让结果的下一位减一。同时也要考虑连续小于的情况,如1000-2.故需要用个循环,保证连续减。保证结果准确。

乘法我也觉得比较简单。需要个临时的数组进行乘完后相加操作。进行乘法时候,就像是进行打草稿计算一样,第二个数的每一个数分别乘以第一个数,然后相加即可。相乘后若一个数>=10,则需进行%10操作,下一位数则加上这位数/10操作

除法就比较坑爹了。在排除除数为0的情况后,也需要用到前面的比较大小的结果,如果输入的第一个数较小,商为0.余数为第二个数。排除掉这种情况后,开始进行除法。除法操作我是正序的引入新的数组。

毕竟用前面的ab数组时逆序的不好操作。

除法解决了之后,最大公约数和最小公倍数就迎刃而解了。

最大公约数直接调用除法函数使用辗转相除法很快就解决了。

最小公倍数直接用乘法的结果除以最大公约数即可。

同时最大公约数和最小公倍数都不讨论0的情况。


心得:做这种题目需要认真。。。。耐心。。有时候找个BUG要老半天的。大数的运算确实不易。我认为这题是一种锻炼编程技能的好题目。通过这题我也练习了函数调用,比如说输出加减乘都可以用同一函数,大大减少了代码量。上面的第三组数据在复制粘贴由于word换行问题,(我把换行去掉了)可能会不小心删掉一位数。。。。


测试方案:输入两个数(不含非法字符且除数不能为0)

2

100

输出:

两数之和为:102

两数之差为:-98

两数之积为:200

两数的商为0……100

最大公约数为:2

最小公倍数为:100

 

2输入

27216

15750

输出

两数之和为:42966

两数之差为:11466

两数之积为:428652000

两数之商为:1……11466

最大公约数为:126

最小公倍数为:3402000

 

3输入:

99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999

99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999

输出:

两数之和为:199999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999998

两数之差为:0

两数之积为:9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001

两数之商为:1……0

最大公约数为:99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999

最小公倍数为:99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999

 

4.输入:

12345

0

输出:

两数之和为:12345

两数之差为:12345

两数之积为:0

除数不能为0

在这里不讨论0的最大公约数和最小公倍数问题


#include <stdio.h>
#include <string.h> 
#define N 500
void add(int a[],int b[],int sum[],int lensum);                //定义加法运算函数
void minus(int a[],int b[],int diff[],int lena);               //定义减法运算函数
void print_result(int a[],int len);                             //输出加、减、乘
void chu(char a[],char b[],char result_chu[],char yu[]);       //除法
void add_cheng(int tempcheng[],int chengfa[],int j) ; 
void main() 
{ 
	int a[N]={0},b[N]={0},sum[N]={0},diff[N]={0},chengfa[N*2]={0},tempcheng[N]={0}; 
    char temp[N],temp2[N],yu[N],result_chu[N],result_gcd[N],gcd_yu[N],result_lcm[N]; 
    int i,j,lena,lenb,lensum,lendiff,flag=1,flagda=1,lencheng;	
    printf("请输入第一个数");                                  //输入数并且倒序存入数组
	gets(temp);
	printf("请输入第二个数");
	gets(temp2);	
	lena=strlen(temp);
	lenb=strlen(temp2);	
	int compare(char yu[],char b[]);
	if(compare(temp,temp2)!=-1)
	{	
		for(i=0;i<lena;i++)
			a[i]=temp[lena-1-i]-48;
		for(i=0;i<lenb;i++)
			b[i]=temp2[lenb-1-i]-48;
	}
	else{
		flagda=0;
		lena=strlen(temp2);
		for(i=0;i<lena;i++)
			a[i]=temp2[lena-1-i]-48;		
		lenb=strlen(temp);
		for(i=0;i<lenb;i++)
			b[i]=temp[lenb-1-i]-48;
	}	
	lendiff=lensum=lena;	
	add(a,b,sum,lensum);                                      //引用加法运算函数
	printf("两数之和为:");	
	print_result(sum,lensum);                                  //引用输出加法结果函数      	
	minus(a,b,diff,lena);                                     //引用减法运算函数
	printf("两数之差为:");
	if(!flagda) printf("-");
	print_result(diff,lendiff);  	                      //引用输出减法结果函 数		             
	for(i=0;i<lenb;i++)                                       //乘法
	{
		for(j=0;j<lena;j++)
		{
			tempcheng[j+i]+=b[i]*a[j];
			if(tempcheng[j+i]>=10) 
			{
				tempcheng[j+i+1]+=tempcheng[j+i]/10;
				tempcheng[j+i]=	tempcheng[j+i]%10; 
			}       
		}
		j+=i;
		if(temp[j+1]!=0)
			j+=1;     
			j++;
		add_cheng(tempcheng,chengfa,j);
		int k;	
		for(k=0;k<=j;k++)
			tempcheng[k]=0;                                                      //清空处理
	}			
	lencheng=j;
	printf("两数之积为:");
	print_result(chengfa,lencheng);                                               //输出乘法结果	
	if(!flagda)                                                                //除法
	{
		printf("两数的商为0……");
		i=lena;
		while(!a[i])
			i--;
		for(;i>=0;i--)
			printf("%d",a[i]);
		printf("\n");
	}
	else 
	{ 
		if(!strcmp(temp2,"0"))
			printf("除数不能为0\n");
		else
		{
			chu(temp,temp2,result_chu,yu);	
			printf("两数之商为:%s……%s\n",result_chu,yu);
		}
	}	 
	if(!strcmp(temp2,"0")||!strcmp(temp,"0"))
	{
		printf("在这里不讨论0的最大公约数和最小公倍数问题\n");
		return;
	}
	char gcd_xiangchu1[N],gcd_xiangchu2[N];	                                           //最大公约数
	if(compare(temp,temp2)==1)
	{
		strcpy(gcd_xiangchu1,temp);
		strcpy(gcd_xiangchu2,temp2);
	}
	else 
	{
		strcpy(gcd_xiangchu2,temp);
		strcpy(gcd_xiangchu1,temp2);
	}
				chu(gcd_xiangchu1,gcd_xiangchu2,result_gcd,gcd_yu);			
				while(gcd_yu[0]!=48)
				{					
					if(compare(gcd_xiangchu2,gcd_yu)==1)				
					{	
						strcpy(gcd_xiangchu1,gcd_xiangchu2);
						strcpy(gcd_xiangchu2,gcd_yu);
						chu(gcd_xiangchu1,gcd_xiangchu2,result_gcd,gcd_yu);							
					}
					else //if	(compare(gcd_xiangchu2,gcd_yu)==-1)		
					{
						strcpy(gcd_xiangchu1,gcd_yu);
						strcpy(gcd_xiangchu2,gcd_xiangchu2);
						chu(gcd_xiangchu1,gcd_xiangchu2,result_gcd,gcd_yu);	
					}		
				}				
				printf("最大公约数为:%s\n",gcd_xiangchu2);			
				char temp3[N*2];                                       	//最小公倍数
				for(i=lencheng-1,j=0;i>=0;i--,j++)
					temp3[j]=chengfa[i]+48;
				temp3[j]='\0';
				chu(temp3,gcd_xiangchu2,result_lcm,gcd_yu);	
				printf("最小公倍数为:%s\n",result_lcm);
} 
void del_zero(char a[])  //删除0
{
	int i,len=strlen(a);
	for(i=0;a[i];i++)
		if(a[i]!='0')
			break;
		if(i==len)
			strcpy(a,"0");
		else
			strcpy(a,&a[i]);		
}
int compare(char yu[],char b[])//比较大小
{
    int len1,len2;
	len1=strlen(yu);len2=strlen(b);
	if(len1>len2)
		return 1;
	else
		if(len1<len2)
			return -1;
		else
			return strcmp(yu,b);
}
void chu_sub(char yu[],char b[]){//除法里面的减法
	int i,j,k,lena,lenb;
	lena=strlen(yu);
	lenb=strlen(b);
	for(i=lena-1,k=lenb-1;i>=0&&k>=0;i--,k--)
	{	if(yu[i]-b[k]>=0)
	   yu[i]=yu[i]-b[k]+48;				
				else{
					j=1;
					yu[i]=yu[i]+10-b[k]+48;						
					yu[i-j]--;
					while(yu[i-j]==47)
					{						
						yu[i-j]+=10;
						j++;
						yu[i-j]--;
					}				
				} 
	} 
	del_zero(yu);
}
void chu(char a[],char b[],char result_chu[],char yu[]) // 除法
{
	int i,k,m,len1,len2;	
	len1=strlen(a);len2=strlen(b);
	strcpy(yu,a);
    yu[len2]='\0';
	m=0;
    for(i=len2-1;i<len1;){
		del_zero(yu);
		if(compare(yu,b)==-1)
		{    
			int len=strlen(yu);
			yu[len]=a[++i];
			yu[len+1]='\0';
			result_chu[m++]='0';
		}
		else{
			k=0;	
			while(compare(yu,b)>=0){	//把b和余数进行比较,如果余数不小于b就进入循环
				chu_sub(yu,b);	//数和b相减	
				k++;
			}
			int len=strlen(yu);
			yu[len]=a[++i];//取a的下一个值作为余数
			yu[len+1]='\0';
			result_chu[m++]=k+'0';
		}
	}
	result_chu[m]='\0';//商
	del_zero(result_chu);
	
}
void add_cheng(int tempcheng[],int chengfa[],int len) // 乘法相加运算
{
	int i;
	for(i=0;i<len;i++)
	{
		chengfa[i]+=tempcheng[i];
		if(chengfa[i]>=10)
		{
			chengfa[i]-=10;
			chengfa[i+1]++;
		}
	}
}
void print_result(int a[],int len)// 输出加法、减法、乘法结果
{
	int i,flag=1;
	while(!a[len]){
		len--;
		if(len<0) {printf("0");flag=0;break;}
	}  
	if(flag)
	{
		for(i=len;i>=0;i--)
			printf("%d",a[i]);
	}
	printf("\n");
}
void minus(int a[],int b[],int diff[],int lena)       //减法运算
{	
	int i,j;
	for(i=0;i<lena;i++)	
		diff[i]=a[i];	
	for(i=0;i<lena;i++)
	{	if(diff[i]-b[i]>=0)
	diff[i]-=b[i];				
				else{
					j=1;
					diff[i]=diff[i]+10-b[i];						
					diff[i+j]--;
					while(diff[i+j]==-1)
					{						
						diff[i+j]+=10;
						j++;
						diff[i+j]--;
					}				
				} 
	}
}
void add(int a[],int b[],int sum[],int lensum)              //加法运算
{
	int i;
	for(i=0;i<lensum;i++)
	{
		sum[i]+=a[i]+b[i];
		if(sum[i]>=10){
			sum[i]-=10;
			sum[i+1]++;
		}
	}
}



(三)

 实验目的:

学习递归的使用

 实验内容:

    8皇后问题(在一个8×8国际象棋盘上,有8个皇后,每个皇后占一格;要求皇后间不会出现相互“攻击”的现象,即不能有两个皇后处在同一行、同一列或同一对角线上。问共有多少种不同的方法。)

 基本要求:

     输入一个整数8,输出所有可行的解法。

     完成解题报告。


分析(解题思路及流程图):一开始看到这题就蒙了。后来参考资料,慢慢懂了。我们可以采用一个一维数组用site存放皇后的行数,把第column列的皇后放进第i行。在递归调用的时候判断行、列、对角线是否冲突。

心得:通过这题让我复习了函数的递归调用,也学会了怎么输出一个程序的运行时间。还有就是把n皇后的结果输进文件中速度快很多。原来15皇后直接在黑白框输出需要240多秒,现在输进文件只需要82秒。大大提高了效率。当然,测试的CPUcore i5 3210M,目测比学校机房速度快4倍左右。当然,我也知道,这个算法并不是最好的。还有待我学习提高进一步改进。


 测试方案:输入一个n,求解并在文件中输出结果

输入:
5
输出:
10


计算时间0秒
文件中输出结果为:
1,1   3,2   5,3   2,4   4,5   
1,1   4,2   2,3   5,4   3,5   
2,1   4,2   1,3   3,4   5,5   
2,1   5,2   3,3   1,4   4,5   
3,1   1,2   4,3   2,4   5,5   
3,1   5,2   2,3   4,4   1,5   
4,1   1,2   3,3   5,4   2,5   
4,1   2,2   5,3   3,4   1,5   
5,1   2,2   4,3   1,4   3,5   
5,1   3,2   1,3   4,4   2,5   

#include <stdio.h>
#include <time.h>
int n,num;
int site[16];
FILE*fin=fopen("result.txt","w");
void search(int column)
{
	if(column==n+1) 
	{
		num++;
		for(int x=1;x<=n;x++)
		{
			fprintf(fin,"%d,%d   ",site[x],x);
		}
			fprintf(fin,"\n");
	}
	else
	{		
		for(int i=1;i<=n;i++)
		{
			int flag=1;
			site[column]=i;           //把第column列的皇后放进第i行,site存放的是皇后的行数
			for(int k=1;k<column;k++)      
			{				
				if(i==site[k]  //同行   
					||column-k==i-site[k] //主对角线
					||column-k==site[k]-i //副对角线
					)               								
				{
                    flag = 0;
                    break;
                }
		
			}
			if(flag!=0)
                search(column+1);    // 如果合法,继续
        }
	}
}
void main()
{
	scanf("%d",&n);	
	if(fin==NULL)
				printf("文件打开失败\n");
	 time_t tm;
	 tm = time(0);
    search(1);
	printf("%d\n",num);
	fclose(fin);
	 printf("\n计算时间%d秒\n",  (int) (time(0) - tm));
}

(四)

 实验目的:

     学习文件的使用

 实验内容:

     解N元一次方程。

 基本要求:

     从文件读入整数 N,  然后读入N*( N+1)矩阵,得到解并输出到文件中。

     完成解题报告。


从文件中读入矩阵阶数和矩阵。

求解线性方程组,无非就是进行初等行变换,使其变成行阶梯型矩阵。然后计算方程的行列式|A||A|很简单,主对角元素直接相乘即可。如果|A|不为0,由于第N行可以直接读出结果,所以把第N行的结果带入n-1行,再把第n-1行的带入n-2行……如此即可求出全部的解。

如果|A|=0,那么需要判断是否有矛盾方程,有矛盾方程则无解,否则有无穷解。

心得:看来学好数学还是十分必要的。此题除了高斯消元法外,还有其他的方法,如《算法导论》中介绍的LUP分解法。但我还没有深入研究。


 测试方案:输入一个数N,在输入增广矩阵。

 1.文件中读入:
2
2 3 8
2 2.99999 8.00003


输出:
x[0]=8.500
x[1]=-3.000




2.文件中读入:
3
1 1 -1 -1         
2 -5 3 2
7 -7 3 1
输出:
方程无唯一解,即有无穷解




3.文件中读入:
3
1 1 1 0
1 1 1 3
1 1 1 0
输出:
方程无解

#include <stdio.h>
void main()
{
	FILE* fin;
	int n,i,j,k,flag,flag2;      
	double a[31][31],temp,x[31]={0};
	fin=fopen("question.txt","r");
	if(fin==NULL)
		printf("文件打开失败\n");
	else {
		fscanf(fin,"%d",&n); //读入矩阵阶数
		for(i=0;i<n;i++)      //输入n*(n+1)矩阵
		{
			for(j=0;j<n+1;j++)
			{
				fscanf(fin,"%lf",&a[i][j]);
			}
		}
		fclose(fin);
		fin=fopen("result.txt","w");
		for(i=0;i<n;i++)	                   //主对角线为0的情况先换行
		{		
			if(a[i][i]==0)
				for(k=i+1;k<n;k++)
				{
					if(a[k][i]) 
					{
						for(j=0;j<n+1;j++)
						{
							temp=a[k][j];
							a[k][j]=a[i][j];
							a[i][j]=temp;
						}
						break;
					}
				}
		}		
		for(i=0;i<n;i++)	                   //进行初等行变换
		{		
			for(j=i+1;j<n;j++)
			{
				temp=a[j][i]/a[i][i];			
				for(k=0;k<n+1;k++)
				{
					a[j][k]-=temp*a[i][k];
				}
			}
		}		
/*				for(i=0;i<n;i++)                 //输出初等变换后结果
		{
		for(j=0;j<n+1;j++)
		{
		printf("%lf\t ",a[i][j]);
		if(j==n) printf("\n");
		}
		}
*/		
		for(i=0,temp=1;i<n;i++)                //计算行列式|A|
			temp*=a[i][i];
		//	printf("|A|=%lf\n",temp);
		if(temp!=0)
		{
			flag=1;                             //求解根
			x[n-1]=a[n-1][n]/a[n-1][n-1];	
			for(i=n-2;i>=0;i--)
			{
				for(j=0,temp=0;j<n;j++)
				{
					temp=temp+a[i][j]*x[j];				
				}
				x[i]=(a[i][n]-temp)/a[i][i];
			}
			for(i=0;i<n;i++)                       //输出根
				fprintf(fin,"x[%d]=%.3lf\n",i,x[i]);
		}
		else 
		{
			flag=1;
			flag2=1;
			for(i=0;i<n;i++)                      //判断是否有解
			{				
				if(a[i][n]!=0)
				{				
					for(j=0;j<n;j++)
					{
						if(a[i][j]!=0)
						{
							flag=1;
							break;
						}
						else flag=0;
					}
					if(flag==0){ flag2=0;break;}
				}					
			}
			if(temp==0&&flag2==0)
				fprintf(fin,"方程无解\n"); //判断无穷解或无解情况
			else if(temp==0&&flag2==1)
			fprintf(fin,"方程无唯一解,即有无穷解\n"); 	
				fclose(fin);
		}
	}
}

 

(五)

实验目的:

     综合练习

 实验内容:

     判断C语言算术表达式的合法性。

 基本要求:

     从文件读入整数 N,  后跟2*N行字符串,两行一组。

每组第一行是预定义的变量(可以多个)。第二行字符串为一个预期的C语言算术表达式。

程序分别判断每个字符串,如果是正确的C语言算术表达式,输出OK;否则,输出其错误类型。如果一个表达式有多个错误,输出一个即可。

用N-S流程图表示处理逻辑(算法)。

设计10个测试数据。

     完成解题报告。

分析(解题思路及流程图):

再输入字符串数据之后,我首先进行了删除变量定义的类型操作,便于今后的判断。但需要主要 abintc这种类型的变量不能删除int

1之后我进行搜索变量括号的合法性。(括号不配对的判断方法:总数一样,右边的括号数目总是小于左边的,右括号左边不与运算符直接相连,左括号的右边不与运算符直接相连,左括号左边不能直接a,括号为空的情况)括号判断完毕后,我进行去括号操作。

2接下来进行符号的搜索和查询。(数组开头不能为运算符号,除数不能为0** // ++ --错误 ,非法符号判断,数组结束不能为运算符号)

3 判断是否定义(我是讲第一个数列封装进一个二维数组,然后把第二个数中每个数轮流装进一个数组,进行比较。)

4.其他BUG修正主要是数字不能与变量相连接。因为我定义时候没有判断合法性,所以我这个程序就认为定义时候只能存字母、数字,但不能有下划线。但不能以数字开头

心得:这道题说简单也简单,说难也难。简单的是逻辑思维很简单,难的是要考虑的东西较多。这道题我怎么觉得是在写一个编译器。如果要做一个完美的编译器,现在还不能够做到。

括号的判断也可以用堆栈的方式进行判断。一开始我就设定定义时只能有一个字符,这样就简单了。后来,由于我做完作业较早,大概第4周把。就闲着没事做,开始弄支持一长串变量类型名的。但是由于偷懒,一位一位判断,导致BUG层出不穷,导致后来我重写,采用现在的方法。就没有BUG了。我从中体会到,作为一个程序员,不能闲麻烦,要做就要做最好。



 测试方案:输入两行字符串,并检查结果是否符合预期

int a;char b,float c;double doublec;
a/(10+134)+c*b+(doublec)
OK


int a;char b,float c;double doublec;
a/(10+134)+c*b+doublec+double
有变量名未定义


double afintc,charfloat;
afintc/charfloat
OK


int a,b,c;
a+b*(-c)
左括号的右边不能与运算符直接相连


double aintc,charfloat;
afintc/charfloat
有变量名未定义


int a,b;
a+(b
括号不成对


int a,b,c;
a~b+c
有非法符号出现


int chara,bfloat;
1chara+bfloat
数字不能与变量直接相连


float charc,af;
charc/0+af
除数不能为0


int chara,bfloat;
chara**bfloat;
运算符不能连续出现

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void shift(char first[],char temp[],int x,int n)//移位操作 X代表第几位开始而N代表偏移几位
{
	for(int i=x;first[i+n]!='\0';i++)
	{
		temp[i]=first[i+n];
	}
	temp[i]='\0';
	for(i=x;temp[i]!='\0';i++)
	{
		first[i]=temp[i];
	}
	first[i]='\0';	
}
void DelType(char first[],char temp[]) //删除int char float double类型方便判断
{
    int i;
	for(i=0;first[i]!='\0';i++)
	{
		if(first[i]=='i'&&first[i+1]=='n'&&first[i+2]=='t'&&first[i+3]==' ')//int
		{
			if(i)
			{
				if(first[i-1]==' '||first[i-1]==';')
					shift(first,temp,i,3);						
			}
			else shift(first,temp,i,3);
		}
		if(first[i]=='c'&&first[i+1]=='h'&&first[i+2]=='a'&&first[i+3]=='r'&&first[i+4]==' ')//char
		{
			if(i)
			{
				if(first[i-1]==' '||first[i-1]==';')
					shift(first,temp,i,4);						
			}
			else 	shift(first,temp,i,4);
		}
		if(first[i]=='f'&&first[i+1]=='l'&&first[i+2]=='o'&&first[i+3]=='a'&&first[i+4]=='t'&&first[i+5]==' ')//float
		{		
			if(i)
			{
				if(first[i-1]==' '||first[i-1]==';')
					shift(first,temp,i,5);						
			}
			else 		shift(first,temp,i,5);
		}
		if(first[i]=='d'&&first[i+1]=='o'&&first[i+2]=='u'&&first[i+3]=='b'&&first[i+4]=='l'&&first[i+5]=='e'&&first[i+6]==' ')//double
		{			
			if(i)
			{
				if(first[i-1]==' '||first[i-1]==';')
					shift(first,temp,i,6);						
			}
			else 	shift(first,temp,i,6);
		}		
	}
	for(i=0;first[i]!='\0';i++)                     //用空格代替分号逗号
	{
		if(first[i]==','||first[i]==';')
			first[i]=' ';
	}
	if(	first[i-1]==' ')
		first[i-1]='\0';	
}
int SearchDefine(char first[],char second[])
{
	char cmp[50][100],cmp2[100];
	int j,num,k,flag,flag2=0;
	for(j=0,num=0;first[j]!='\0';j++)
	{	
		if(first[j]>='a'&&first[j]<='z'||first[j]>='A'&&first[j]<='Z')
		{		
			
				for(k=0;first[j]!=' '&&first[j]!='\0';j++,k++)
				{	
					cmp[num][k]=first[j];						
				}
				cmp[num][k]='\0';
				num++;
			
		}
	}
	//  	for(j=0;j<num;j++)		
	//  		printf("%s\n\n",cmp[j]);
	// 	printf("******************\n");
	int len=strlen(second);
	for(j=0,flag=1;j<len;j++)
	{
		
		if(second[j]>='a'&&second[j]<='z'||second[j]>='A'&&second[j]<='Z')
		{	
			if(j>0)
				if(second[j-1]=='+'||second[j-1]=='-'||second[j-1]=='*'||second[j-1]=='/')
					flag=1;
				else flag=0;
				if(flag)
				{
					for(k=0;second[j]!='+'&&second[j]!='-'&&second[j]!='*'&&second[j]!='/'&&second[j]!='\0';j++,k++)
					{	
						cmp2[k]=second[j];						
					}
					cmp2[k]='\0';
					//				printf("!!!!!\n%s\n!!!\n",cmp2);
					for(k=0,flag2=0;k<=num;k++)
					{     
						if(strcmp(cmp[k],cmp2)==0) 
						{	
							flag2=1;
							break; 
						}
						else flag2=0;
					}
					//            printf("#############\n%d\n#########\n",flag2);
					if(flag2==0) {return 0;}
					
				}
		}
	}
	return 1;	
}
int searchBracket(char a[])
{	
	int left=0,right=0;
	for(int i=0;a[i]!='\0';i++)//括号正确与否判断
	{
		if(a[i]=='(') 
		{
			left++;
			if(a[i+1]=='+'||a[i+1]=='-'||a[i+1]=='*'||a[i+1]=='/')
			{
				printf("左括号的右边不能与运算符直接相连\n\n");
				return 0;
			}
			if(a[i+1]==')')
			{
				printf("括号不能为空\n");
				return 0;
			}
			if(a[i-1]>=48&&a[i-1]<=57)
			{
				printf("左括号的左边不能与数字直接相连\n\n");
				return 0;
			}
			if(a[i-1]>='a'&&a[i-1]<='z'||a[i-1]>='A'&&a[i-1]<='Z')
			{
				printf("左括号的左边不能与变量直接相连\n\n");
				return 0;
			}			
		}
		if(a[i]==')') 
		{
			right++;
			if(a[i-1]=='+'||a[i-1]=='-'||a[i-1]=='*'||a[i-1]=='/')
			{
				printf("右括号的左边不能与运算符直接相连\n\n");
				return 0;
			}
			if(a[i+1]>=48&&a[i+1]<=57)
			{
				printf("右括号的右边不能与数字直接相连\n\n");
				return 0;
			}
			if(a[i+1]>='a'&&a[i+1]<='z'||a[i+1]>='A'&&a[i+1]<='Z')
			{
				printf("右括号的右边不能与变量直接相连\n\n");
				return 0;
			}
			if(left<right)
			{
				printf("括号有误\n\n");
				return 0;
			}			
		}
	}
	if(left!=right)
	{
		printf("括号不成对\n\n");
		return 0;
	}	
	for(i=0;a[i]!='\0';i++)        //去除括号
	{
		if(a[i]=='('||a[i]==')') 
		{
			char temp[100];
			shift(a,temp,i,1);
		}
	}
	return 1;	
}
int searchSign(char a[])
{
	int i=0,num=0;
	if(a[i]=='+'||a[i]=='-'||a[i]=='*'||a[i]=='/')
	{
		printf("不能以运算符开头\n\n");
		return 0;
	}
	for(i=1;a[i]!='\0';i++)  
	{
		if(a[i]=='+'||a[i]=='-'||a[i]=='*'||a[i]=='/')
		{
			if(a[i+1]=='+'||a[i+1]=='-'||a[i+1]=='*'||a[i+1]=='/')						
			{
				printf("运算符不能连续出现\n\n");
				return 0;
			}
		}
		if(a[i]=='/'&&a[i+1]==48)
		{
			printf("除数不能为0\n\n");
			return 0;
		}
		if(a[i]<'0'||a[i]>'9')
			if(a[i]<'a'||a[i]>'z')
				if(a[i]<'A'||a[i]>'Z')
					if(a[i]!='+'&&a[i]!='-'&&a[i]!='*'&&a[i]!='/')
					{
						printf("有非法符号出现\n\n");
						return 0;
					}
	}
	i--;
	if(a[i]=='+'||a[i]=='-'||a[i]=='*'||a[i]=='/')
	{
		printf("不能以运算符结尾\n\n");
		return 0;
	}
	return 1;
}
int searchOthers(char a[])
{
	int j,len=strlen(a);
	for(j=0;j<len;j++)
	{
		if(a[j]>='a'&&a[j]<='z'||a[j]>='A'&&a[j]<='Z')	
			if(a[j-1]>='0'&&a[j-1]<='9')
			{
				printf("数字不能与变量直接相连\n\n");
				return 0;
			}	
	}
	return 1;
}
void main()
{	
	int flag,n,i;
    char first[100],second[100],temp[100];
	scanf("%d\n",&n);
	for(i=0;i<n;i++)
	{ 
		gets(first);
		gets(second);
		DelType(first,temp);//首先删除变量类型
		//	printf("!!!!!\n%s\n",first);
		if(searchBracket(second))//搜索括号			
			if(searchSign(second))//判断非法符号
			{
				flag= SearchDefine(first,second);//判断是否定义
				if(!flag)
					printf("有变量名未定义\n\n");
				else
					if(searchOthers(second))
						printf("OK\n\n");						
			}
			
	}
}


转载于:https://www.cnblogs.com/murmured/p/5004059.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值