一年前的玩意。
老是有人找我要。。一年前写得这么搓都不敢拿出来。。。。
但是好多人要啊。。。。。直接发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.余数为第二个数。排除掉这种情况后,开始进行除法。除法操作我是正序的引入新的数组。
毕竟用前面的a和b数组时逆序的不好操作。
除法解决了之后,最大公约数和最小公倍数就迎刃而解了。
最大公约数直接调用除法函数使用辗转相除法很快就解决了。
最小公倍数直接用乘法的结果除以最大公约数即可。
同时最大公约数和最小公倍数都不讨论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秒。大大提高了效率。当然,测试的CPU是core 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");
}
}
}