吉林大学计算机系高级语言程序设计(C语言)期末题目及解答(上)

内容简介

本人刚刚结束考研初试进程,正在准备吉大的上机复试,决定把大一时的期末题再上机编写一次,想起自己大一期末的时候上天入地地找期末题的编程答案,于是决定专门写一篇blog给各位期末复习的朋友解惑。

①:已完结【因为文章过大所以分为了上下两篇,上篇已完结】
②:录了配套的讲解视频放在B站上,搜索用户“剑桥本桥”即可 .

注:
期末是手撕代码,一般只需要写出函数,在这里我为了演示方便把主函数也写了,大家只看函数部分即可。

2016级

一、编写函数并画出对应的PAD,将整形数组a中的所有元素逆序存放。函数声明为:void rev(int a[ ],int n)

算法思想:
首先,根据题目,输入数据为一个整形数组a及数组的长度n;
其次,要想逆序,可以将数组的第一位与最后一位进行交换,这种交换逐渐向“里面”延伸,直至交换完整个数组(n/2);
最后,输出交换完成后的数组。

#include 
#define N 50//用于指定数组长度
void rev(int a[],int n);

int main()
{
	printf("\n\n\t——本函数用于进行数组逆序——");
	//用户输入数组长度
	printf("\n\n\t请输入数组长度:");
		int n;
		scanf("%d",&n);
	//用户输入数组
    printf("\n\t请输入数组: ");
	    int a[N];
	    for(int i=0;i<n;i++)
			scanf("%d",&a[i]);
	//调用逆序函数
		rev(a,n);
		return 0;
}

//函数定义
void rev(int a[],int n)
{
    int i;
    int j=n-1; 
	for(i=0;i<n/2;i++)  //整数二除扣定范围,进行交换
	{
		int temp; //交换变量
		temp=a[i];
		a[i]=a[j];
		a[j]=temp;
		j--;
	}

    printf("\n\t逆序后的数组为:");  //输出交换后的函数
	for(i=0;i<n;i++)
	{
		printf("%d ",a[i]);
	}
    printf("\n\n\t算法结束");
}

**二、编写函数,比较两个字符串,返回其长度的差值。函数声明为:int comp(char a,char b)
注意,不允许使用string.h头文件和其声明的相关函数

算法思想:
首先,参数传入两个字符串,分别从头到尾遍历并进行计数;
然后,将计算出来的长度做差值,返回该数字。
本题目主要考察字符串以‘\0’结尾

#include
#include
#define N 20
int comp(char *a,char *b);

int main()
{
	printf("\n\n\t——本函数用于计算两个字符串的长度差值——");
	
	//用户输入字符串 
	printf("\n\n\t请输入字符串一:");
		char s1[N];
		scanf("%s",s1);
	printf("\n\n\t请输入字符串二:");
		char s2[N];
		scanf("%s",s2);
	
	printf("\n\n\t两字符串的长度差值为:%d",comp(s1,s2));//调用并输出 
	return 0; 
}

int comp(char *a,char *b)
{
	int i=0,j=0;    //用于计数 
	char *pa=a,*pb=b;//用于比较 
	while((*a)!='\0')//分别计数两字符串长度 
	{
		i++;
		a++;
	}
	while((*b)!='\0')
	{
		j++;
		b++;
	}
	//比较两个字符串 
	while((*pa!='\0')&&(*pb!='\0')
	{
		if((*pa)<(*pb))
		{
			printf("\n\n\t第一个字符串较大");
			break;
		}
		else if((*pa)>(*pb))
		{
			printf("\n\n\t第二个字符串较大");
			break;
		}
		else
		{
			pa++;
			pb++;
		}
	}
	return fabs(i-j);//返回差值的绝对值 
}

三、一个长度为n(n>5),可以在其2/5处折断,变为两段长度分别为2n/5,3n/5的木条;如果得到的木条的长度仍大于五,则继续按照上述方法折断,直到任意木条的长度均不大于5为止。编写递归函数,计算一个长度为n的木条,最后会被折断为多少根木条。

算法思想:
递归题目几乎是C语言期末的必考题,只要把出口和判断条件这两个要点写清楚老师基本就会给分,当然,有完整程序更好。
在此题中,重要的是想清楚最终的递归出口只返回1.
在实际操作中我发现如果将n设置为double类型则无法输出正确结果,大佬们如果看到这里有解决办法请在评论区指点我一下。

#include
int wood(float n);

int main()
{
	float n;
	printf("\n\n\t——本函数用于计算木条数量——");
	//用户输入初始长度 
	printf("\n\n\t请输入木条长度(大于五):");
	scanf("%f",&n);
	printf("\n\n\t该木条将被分成 %d 块。",wood(n));
	return 0;
 } 
 
int wood(float n)
{
	//计算
    if(n>5)
	{
		return wood((n*3)/5)+wood((n*2)/5);
	}
	else
	{
		return 1;
	}
}

四、每个学生的信息卡片包括学号,姓名和联系电话三项,要求:
1)定义存储学生信息的单向链表的结点类型;
2)编写函数,由键盘依次输入n(n>=0)个学生的信息,创建一个用于管理学生联系方式的单向链表,并在创建过程中随时保证该单向链表的节点顺序满足学号从低到高的顺序。
注:必须包含且仅包含与该题目相关的头文件。

算法思路:
知识点:链表动态存储,动态排序
期末考试的时候必须把结构体声明和头文件写上,占好大分。

#include
#include
struct Node* Create();//创建链表函数
void Show(struct Node* head);//显示函数
struct Node* Order(struct Node* x,struct Node* head);//排序函数 
 
//链表结点定义
struct Node{
	int num;//学号
	char name[20];//姓名
	char tel[11]; //电话号码 
    struct Node* next;//下一项指针 
}; 

//主函数
int main()
{
	printf("\n\n\t——本函数用于记录学生信息——");
	struct Node* head;
	head=Create();//创建链表;
	Show(head);//显示链表 
	//Save(head);//写入文件 ———第五题使用时去掉前面的注释号
	return 0;
 } 
 
//创建函数定义
struct Node* Create()
{
	struct Node *head;
	struct Node *p1,*p,*p0;
	//创建第一个结点 
	p=(struct Node*)malloc(sizeof(struct Node));
	head=p;
	printf("\n\n\t学生姓名:");
		scanf("%s",(*p).name);
	printf("\n\n\t学生学号:");
		scanf("%d",&(*p).num);
	printf("\n\n\t学生电话:");
		scanf("%s",(*p).tel);
	(*p).next=NULL;
	p0=p;
	
	printf("\n\n\t请问是否继续输入,继续输入请按1,否则按任意键退出:");
	    int x;
		scanf("%d",&x);
	//建立链表 
	while(x==1)
	{
	p=(struct Node*)malloc(sizeof(struct Node));       
	printf("\n\n\t学生姓名:");
		scanf("%s",(*p).name);
	printf("\n\n\t学生学号:");
		scanf("%d",&(*p).num);
	printf("\n\n\t学生电话:");
		scanf("%s",(*p).tel);
	(*p).next=NULL;
	(*p0).next=p;
	//学号大小判断,因为已经是有序表,可以直接从前向后找第一个比它大的位置
	p1=Order(p,head);

    //分三种情况讨论插入位置
	//结点应该被插入到头结点之前
	if(p1==NULL)
	{
		(*p0).next=NULL;
		(*p).next=head;
		head=p;
	 } 
	else if(p1!=p0)
	{
		struct Node* p2;
		p2=(*p1).next;
		(*p0).next=NULL;
		(*p1).next=p;
		(*p).next=p2;
	}
	else if(p1==p0)
	{
		p0=p;
	}
	printf("\n\n\t请问是否继续输入,继续输入请按1,否则按任意键退出:");
		scanf("%d",&x);	
	 } 
	return head;//返回头结点 
 } 
 
/*特定排序函数,参数为目标结点及链表的头结点,返回值为仅小于目标结点的结点指针*/ 
struct Node* Order(struct Node* x,struct Node* head)
{
	struct Node* h,*p;
	h=head;
	p=h;
	struct Node *p1;
	int k=(*x).num;//k值用于比较
	//头结点特殊处理:如果当前结点应该插入在头结点之前,则
	if((*p).num>=k)
	{
		return NULL;//返回空 
	 } 
	//遍历查找 
	else{
	while((*p).num<k)
	{
		p1=p; 
		p=(*p).next;
	 } 
	return p1;//p1指向的结点是应该插入位置的前驱结点 	
	}
	
 } 
//显示函数
void Show(struct Node* head)
{
	struct Node* h;
	h=head;
	while(h!=NULL)
	{
		printf("\n\t姓名:%s",(*h).name);
		printf("  学号:%d",(*h).num);
		printf("  电话:%s",(*h).tel);
	    h=(*h).next; 
	}
 } 

五、编写函数,将第四题中构建的单向链表中的全部信息写入磁盘D:盘根目录下的address.txt文件中,要求:每次写入一个学生的信息,就从键盘输入该学生的家庭住址,把家庭住址同时写入文件中。
注:必须包含且仅包含与该题相关的头文件。

算法思路:
**知识点:**文件读写。
我个人比较习惯格式化读写(即fprintf 和 fscanf),因为记忆方便,对格式操作也相对简单。

文件读写需要注意几点:
第一,要先对文件指针进行声明 FILE *fp;
第二,打开文件;打开文件时要记得进行错误处理;
第三,对文件的操作结束之后,要用fclose来关闭文件指针:fclose(fp).

*直接在第四题的程序中声明一下这个函数然后直接粘贴在第四题程序后面就可以运行了。

//本函数用于将链表中的信息存入文件 
void Save(struct Node* head)
{
	printf("\n\n\t——本函数用于将链表信息存入文件——");
	struct Node *h;
	h=head;		
	char address[20];

	//写入文件
	FILE *fp;
	if((fp=fopen("E://address.txt","w"))==NULL)  //打开文件
	{
		printf("Can't open this file.\n");
		exit(0);
	}

	while(h!=NULL)     //遍历链表,写入文件
	{
		fprintf(fp,"\n姓名:%s\t学号:%d\t电话:%s\t\n住址:",(*h).name,(*h).num,(*h).tel);
	//用户从键盘输入家庭住址 
       // fprintf(fp,"%s",(*h).name);
		printf("\n\n\t请输入%s同学的家庭住址:",(*h).name);
			scanf("%s",address);
		fprintf(fp,"%s\n",address);
		h=(*h).next;
	 } 
	fclose(fp);
	printf("\n\n\t——写入完成——");
}

2016级唐班

一、编写函数,将两个非递减整形数组a和b合并后存储在a中,并保证处理后的数组仍然按照非递减顺序存储,函数返回值为出现次数最多的元素值,不能定义额外的新数组。
函数声明为:
int merge(inta ,int m, intb, int n)

算法思路:
显然,m是数组a的长度,n是数组b的长度,因为不能建立新的数组,所以是将一个数组的元素逐个插入第一个数组中,和2016级普班题目的排序思想是一样的。
唯一需要注意的地方在于,数组在插入元素的时候需要全组后移,先挪后再挪前,否则会发生覆盖问题。
具体排序思想为:
对B数组进行从前到后的遍历,给每一个元素在A数组中找出相应的位置;
另外,要找出出现次数最多的元素,可以在排序之后进行检索,因为是正序,所以相同大小的元素会被安排在一起。
建议测试用例:
插入数组头,插入数组尾,重复元素序列。

#include 
#define N 20
int merge(int*a ,int m, int*b, int n);//合并函数声明

int main()
{
	printf("\n\n\t——本函数用于将两个数组按照递增序列合并为一个——");
	int a[N*2+1];  //在本算法中将a数组设定为了被插入的数组 
	int b[N];
	int m,n; 
	//用户输入数据 
	printf("\n\n\t请输入数组A的长度值m  :");
	    scanf("%d",&m);
	printf("\n\n\t请输入数组B的长度值n  :");
	    scanf("%d",&n);
	printf("\n\n\t请输入数组一的数据:");
		for(int i=0;i<m;i++)
		{
			scanf("%d",&a[i]);
		}
	printf("\n\n\t请输入数组二的数据:");
	    int c2=0;
		for(int i=0;i<n;i++)
		{
			scanf("%d",&b[i]);
		 } 
		 
    //调用合并函数
	int max;
	max=merge(a,m,b,n);
	if(max==0)
	{
		printf("\n\n\t本数组中无重复元素。");
	}
	else
	{
		printf("\n\n\t数组中出现次数最多的元素为: %d",max);		
	}

	//输出合并后的数组
	printf("\n\n\t排序后的数组为:");
	for(int i=0;i<m+n;i++)
	{
		printf("%d ",a[i]);
	 } 
	return 0;
 } 
//合并函数 
int merge(int*a ,int m, int*b, int n)
{
	int j=0,i;//变量i用于遍历A数组
	for(j=0;j<n;j++) 
	{
		i=0;
		while(b[j]>a[i])//查找B中元素应该插入的位置 
        {
        	i++;
		}
		i--;//i回退一位 
		
		if(i==m)//末位插入 
		{
			a[i]=b[j];
		}
		else//向中间插入的情况 
		{
			for(int k=m-1;k>i;k--)//挪空 
			{
			a[k+1]=a[k];   //注意是用前面的值覆盖后面 
			}
			//插入元素
			a[i+1]=b[j];
		}
		//改变数组a的长度
		m++; 
	}
	//结束之后再次遍历数组A,因为已经是增序排列,所以一样的元素肯定会排在一起
	int max=0;
	int count=0;
	int k0;
	for(int k=0;k<m;k++)
	{
		count=0;
		if(a[k+1]==a[k])
			count++;
		if(count>max)
		{
			max=count;
			k0=k;
			}	
	 } 
	return a[k0];
}

*二、编写函数,求一个字符串的最小字符。函数声明为:
char minchar (char a)

算法思路:
字符之间比大小就是比ASCLL码。

#include
#define N 50
char minchar(char *a);

int main()
{
	printf("\n\n\t——本函数用于寻找一个字符串中的最大字符——");
	char a[N];
	//用户输入字符串 
	printf("\n\n\t请输入字符串:");
		scanf("%s",a);
	//调用并输出 
	printf("\n\n\t该字符串中的最小字符为:  %c",minchar(a));
	return 0;
 } 
//寻找一个字符串中的最大字符 
char minchar(char *a)
{
	int i=0;
	char *p;
	char min=a[0];
	p=a;
	
	while(*p!='\0')//遍历 
	{
		if(*p<a[i])
		{
			min=a[i]; 
		}
		i++;
		p++;
	}
	return min;
}
 

四、CCF会员的信息卡至少包括:会员号(5位数字+1位大写字母)、姓名、会员类别、有效期(包含年、月、日)等信息
例如:15316S、吕帅、高级会员、20181231
1)定义存储CCF会员上述信息的单向链表结点类型;
2)编写函数,依次由文件in.txt读入所有会员的信息(文件中每个会员信息包括会员号、姓名、有效期);会员类别为冗余信息,由会员号的最后一位可以推导出,创建一个用于管理会员信息的单向链表,使该链表有序;
3)假定管理会员的单向链表已经按照会员号的五位数字(唯一标识)从小到大排序。编写函数,将该单向链表修改为:首先按照会员类别排序,相同类别的会员按照5位数字从小到大排序。

算法思路:
主要是强调一下vip排序这块的思路:设置三个指针,分别指向“非会员”“普通会员”和“高级会员”的结点结尾,便于下次插入。
(这道题VIPORDER部分的代码还有问题)

#include 
#include 
struct Num{
	int n;  //会员号中的数字 
	char a;  //会员号中的字母 
};
struct Node{
	struct Num num;
	char name[10];
	int vip;   //vip类型分为:0-非会员;1-普通会员;2-高级会员 
	int date;
	struct Node* next;
};

void WriteFile();//为了读入方便,直接用写入方式创建文件 
struct Node* Create();//从文件读入会员信息,并创建链表,返回头指针 
struct Node* VipOrder(struct Node* head);//按会员等级排序 
void Show(struct Node* head);//展示链表 
//主函数 
int main()
{
	printf("\n\n\t——本程序用于处理CCF会员信息——");
	
	//初次使用应当写入文件 
	printf("\n\n\t请问是否需要写入文件?");
	printf("\n\t需要请输入1;不需要请输入0:");
		int x;
		scanf("%d",&x);
	if(x==1)
		WriteFile();
	
	//第二问,生成链表 
	struct Node* head;
		printf("\n\n\t——正在从文件读入会员信息并生成链表——");

			head=Create();//创建链表 
			Show(head);//显示链表 
	
	//第三问,排序链表 
	printf("\n\n\t请问是否需要按照会员等级排序?");
	printf("\n\t需要请输入1;不需要请输入0:");
		scanf("%d",&x);
	struct Node *viphead;
	if(x==1)
	{
	//	printf("test.");
		viphead=VipOrder(head);
		Show(viphead);
	 } 
	 
	printf("\n\n\t——算法结束——");
	return 0;
 } 
 
//写入文件 
void WriteFile()
{
	printf("\n\n\t——请向文件写入会员信息——");
	printf("\n\n\t非会员—0;普通会员-1;高级会员-2"); 
	
	//打开文件 
	FILE *fp;
	if((fp=fopen("E://in.txt","w"))==NULL)
	{
		printf("Can't open this file.\n'");
		exit(0);
	}
	
	//用户写入文件 
	int i=1;
	int x=0;
	do{
	printf("\n\n\t第%d位会员信息:\n\t会员号:",i);
		int xn;
		char xa;
		char xname[10];
		int xvip;
		int xdate;
		scanf("%d",&xn);scanf("%c",&xa);
	printf("\n\t姓名:");
		scanf("%s",xname);
	printf("\n\t会员类型:");
		scanf("%d",&xvip);
	printf("\n\t有效期:");
		scanf("%d",&xdate);
	fprintf(fp,"%d%c ",xn,xa);
	fprintf(fp,"%s ",xname);
	fprintf(fp,"%d ",xvip);
	fprintf(fp,"%d\n",xdate);
	
	i++;
	printf("\n\n\t请问是否继续输入用户信息?继续,请输入1,否则输入0.");
		scanf("%d",&x);
	}while(x==1);
	
	fclose(fp);
	printf("\n\n\t——写入结束——");
}
//从文件读入信息并创建链表 
struct Node* Create()
{
	//打开文件 
	FILE *fp;
	if((fp=fopen("E://in.txt","r"))==NULL)
	{
		printf("Can't open this file.\n'");
		exit(0);
	}
		
		int xn;
		char xa;
		char xname[10];
		int xvip;
		int xdate;	
		
	   struct Node * head,*p,*p0;
		//从文件读入数据 
		fscanf(fp,"%d%c",&xn,&xa);
		fscanf(fp,"%s",xname);
	    fscanf(fp,"%d",&xvip);
	    fscanf(fp,"%d",&xdate);
		//创建链表
		p= (struct Node*)malloc(sizeof(struct Node));
		head=p;
		(*p).num.n=xn;
		(*p).num.a=xa;
		//(*p).name=xname;//不知道字符串能不能直接等于:不能
		 int j=0;
		 while(xname[j]!='\0')
		 {
		 	(*p).name[j]=xname[j];
		 	j++;
		 }
		(*p).vip=xvip;
		(*p).date=xdate;
		p0=p;
		
	char ch;
	while((ch=fgetc(fp))!=EOF)  //读到文件尾 
	{
		//从文件读入数据 
		fscanf(fp,"%d%c",&xn,&xa);
		fscanf(fp,"%s",xname);
	    fscanf(fp,"%d",&xvip);
	    fscanf(fp,"%d",&xdate);

		//创建链表	
		p= (struct Node*)malloc(sizeof(struct Node));
		(*p0).next=p;	
		
		(*p).num.n=xn;
		(*p).num.a=xa;
	//	(*p).name=xname;//不知道字符串能不能直接等于——不能。 
	    	j=0;
		 while(xname[j]!='\0')
		 {
		 	(*p).name[j]=xname[j];
		 	j++;
		 } 
		(*p).vip=xvip;
		(*p).date=xdate;
		(*p).next=NULL;
		
		p0=p;
	}
	return head;//返回头指针 
}
//显示函数,便于测试 
void Show(struct Node* head)
{
	printf("\n\n\t——链表信息展示——");
	struct Node *h;
	h=head;
	int i=1;
    while((*h).next!=NULL)
    {
    	printf("\n\n\t编号:%d 会员号:%d%c 姓名:%s ",i,(*h).num.n,(*h).num.a,(*h).name);
    	i++;
		if((*h).vip==0)
    	{
    		printf(" 非会员 "); 
		}
		else if ((*h).vip==1)
		{
			printf(" 普通会员 ");
		}
		else
		{
			printf(" 高级会员 "); 
		}
		printf("有效日期:%d\n",(*h).date);
		
		h=(*h).next;
	}

 } 
//按会员等级排序 
struct Node* VipOrder(struct Node* head)
{
	//遍历链表,找出第一个非会员,普通会员和高级会员的位置,并添加指针
printf("test2");
	struct Node *q0,*q1,*q2;
	struct Node *h;
	h=head;
	bool x0=false,x1=false,x2=false;
	while(h!=NULL)
	{
printf("test3");   //问题出在这里,第一个找不到 
		if(((*h).vip==0)&&(x0=false))
		{
			q0=h;
			x0=true;
		}
	    else if(((*h).vip==1)&&(x1==false))
		{
			q1=h;
			x1=true;
		 } 
		else if(((*h).vip==2)&&(x2==false))
		{
			q2=h;
			x2=true;	
		}
		
		h=(*h).next;		
		}
printf("\ntest_%s %s %s",(*q0).name,(*q1).name,(*q2).name);
printf("test4");	
	//排序,添加一个哨兵结点 
	struct Node *pre=(struct Node*)malloc(sizeof(struct Node));
    (*pre).next=head; 
    struct Node *p;
    p=head;
	 
	 while(p!=NULL)
	 {
printf("test5");
	 	//特殊处理 
	 	if((p==q0)||(p==q1)||(p==q2))
	 	{
	 	    pre=p;
	        p=(*h).next;
		 }
printf("test5.1");
	 	//从h的本来位置去掉它 
	 	struct Node* temp;//q0,q1,q2的后继结点 
	 	(*pre).next=(*p).next;
printf("test5.2");
	 	//将h连在q0,q1,q2后面 
	 	if((*p).vip==0)
	 	{
	 		temp=(*q0).next;
	 		(*q0).next=p;
	 		(*p).next=temp;
		 }
	    else if((*p).vip==1)
		{
			temp=(*q1).next;
			(*q1).next=p;
			(*h).next=temp;
		}
		else if((*p).vip==2)
		{
			temp=(*q2).next;
			(*q2).next=p;
			(*p).next=temp;
		}
printf("test6");
		//将h恢复到本来位置 
		p=(*pre).next;
	 }
printf("test7");
	 return head;
 } 

2016级B卷

1.编写函数,实现按照如下公式计算的功能:
f(n)=0/(12!)+1/(23!)+2/(34!)+……+n/((n+1)(n+2)!),其中n为自然数。

算法思想:
要单独给出一个计算阶乘的递归函数。个人认为这道题的重点在于要对整数除法进行一个浮点数转换

#include 
int factor(int n);//计算n的阶乘
float cal(int n);//特殊计算式计算函数 

int main()
{
	printf("\n\n\t——本函数用于计算特殊计算式——");
	printf("\n\n\t请输入结束n值:");
		int x;
		scanf("%d",&x);
	printf("\n\n\t计算结果为:%.5f ",cal(x));
	printf("\n\n\t——算法结束——");
	return 0;
 } 
 //特殊计算式计算函数 
float cal(int n)
{
	float sum=0;
	for(int i=0;i<=n;i++)
	{
		sum=sum+i/float((i+1)*factor(n+2));  //浮点数转换
	}
	return sum;
}
//阶乘计算函数
int factor(int n)
{
	if(n==1)
	  return 1;
	else{
		return n*factor(n-1);
	}
 } 

2.编写bool函数,判断给定的整数数组a[n]中是否存在元素a[i],i的取值范围为0到n,等于其前边所有元素之和,即a[i]=a[0]+a[1]+a[2]+a[3]+…a[i-1]

算法思想:
函数声明为bool sumi (int *a,int n) //参数为数组头地址和数组长度,返回值为true,则存在该元素,返回值为false,则无此元素。
这个算法的缺点是当一个数组中同时有几个和元素的时候它只能输出第一个。改进方法为在判断函数中设置一个数组来存储所有的和元素,并通过参数返回。

#include 
#define N 50
bool sumi(int *a,int n);

int main()
{
	printf("\n\n\t——本函数用于判断数组中有没有和元素——");
	printf("\n\n\t请输入数组长度:");
		int n;
		scanf("%d",&n);
	printf("\n\n\t请输入数组数据:");
		int a[N];
		for(int i=0;i<n;i++)
			scanf("%d",&a[i]); 
	bool ans=sumi(a,n);
		if(ans==true)
		{
			printf("\n\n\t数组中有一个元素值为前面所有元素之和: %d",a[n]);
		}
		else if(ans==false)
		{
			printf("\n\n\t数组中没有和元素。");
		}
	printf("\n\n\t——算法结束——");
	return 0;
	 } 

bool sumi(int *a,int n)
{
	int sum=0;
	for(int i=0;i<n;i++)
	{
		if(sum==a[i])
		{
		//	p=&a[i];
		//	printf("%d",a[i]);
			a[n]=a[i];  //为了输出方便所以设置另a[n]存储这个元素
			return true;
		}
		else if(sum!=a[i])
		{
			sum=sum+a[i];
		}
	}
	return false;
}

3.编写一个递归函数,计算组成给定正整数n的所有数字之和。
例如:给定参数为1035,则返回结果应该为9(通过1+0+3+5=9获得)

算法思想:
①分离数位;
②递归出口为n/10==0 .
③int sep (int n); //返回值为数位加和,参数为数字本身

#include 
int sep(int n);//递归分离数位函数

int main()
{
	printf("\n\n\t——本函数用于分离数位并加和——");
	printf("\n\n\t请输入要分离的数字:");
		int n;
		scanf("%d",&n);
		if(n<0)//负数处理 
		{
			n=-n;
		}
	printf("\n\n\t该数字的数位和为:%d",sep(n)); 
	printf("\n\n\t——算法结束——");
	return 0;
 } 
 
int sep(int n)
{
	if((n/10)==0)
	{
		return n;
	}
	else
	{
		return (n%10)+sep(n/10);
	}
}

4.构造一个表示教师的结构体(包含三个字段,姓名,性别,年龄),编写函数,读入M个教师的信息,存入一个结构体数组中,如下图所示:(原题用true和false表示了性别,在这里使用o和1进行区分)
张三 李四 … 赵九
男(1) 女(0)… 男(1)
50 37 … 29

算法思想:
本题重点考察结构体数组。为了测试方便添加了一个显示函数,

#include 
#define N 20
struct Teach{
	char name[20];
	int sex;
	int age;
};

int Create (struct Teach *t);//键盘输入函数 ,返回值为数组长度 
void Show(struct Teach *t,int n);//显示函数 ,参数为数组头和数组长度 

int main()
{
	printf("\n\n\t——本函数用于保存教师信息——");
	struct Teach t[N];
    int n=Create(t);
	Show(t,n);
	printf("\n\n\t——算法结束——");
	return 0;
}

int Create(struct Teach *t)
{
	int x=1;
	int i=0;
	while(x==1)
	{
		printf("\n\n\t请键入第%d位教师信息:",i+1);

		printf("\n\t姓名:");
			scanf("%s",t[i].name); 
		printf("\n\t年龄:");
			scanf("%d",&t[i].age);
		printf("\n\t性别:(男-1;女-0):");
			scanf("%d",&t[i].sex);
			while((t[i].sex!=0)&&(t[i].sex!=1))
			{
				printf("\n\t输入错误,请输入0或者1:");
				scanf("%d",&t[i].sex);	 
			}
		i++;
		printf("\n\n\t请问是否继续输入?继续输入按1,否则按0");
			scanf("%d",&x);
	}
	return i;
}

void Show(struct Teach *t,int n)//显示函数 
{
	printf("\n\n\t显示教师信息数组:");
	int i;
	for(i=0;i<n;i++)
	{
		printf("\n\n\t姓名:%s  年龄:%d 性别:  ",t[i].name,t[i].age);
			if(t[i].sex==1)
			{
				printf("男");
			}
			else if(t[i].sex==0)
			{
				printf("女");
			}
	}
 } 

五、设有一个保存教师信息的单链表,(每个结点包含四个字段:姓名,性别,年龄,后继指针),构造该链表中一节的数据类型声明:编写函数,在给定链表上查找所有女教师的信息,并存储到指定文件output.txt中。

算法思想:
考察的知识点有:
①结构体构造(结构体数组和链表的差别);
②结构体链表查找;
③文件写入。

手撕代码时只写void FindFemale函数即可,其它两个函数都是为了测试方便才写的。

#include 
#include //因为涉及文件

struct Node{
	char name[20];   //姓名 
	int sex;   //性别 
	int age;   //年龄 
	struct Node* next;   //后继指针 
}; 

struct Node* Create();//创建链表函数
void Show(struct Node *head);//显示链表函数
void FindFemale(struct Node* head);//查找女教师并写入文件

int main()
{
	printf("\n\n\t——本函数用于对教师信息的处理——");
	printf("\n\n\t是否创建链表?创建请输入1,不创建请输入0");
	//理论上应该在这里添加一个文件读入函数,如果用户选择0就从文件读入,但是我懒了 
		int x;
		scanf("%d",&x);
		while((x!=1)&&(x!=0))
		{
			printf("\n\n\t请输入1或0: ");
			scanf("%d",&x);
		 } 
	struct Node*head;
	if(x==1)
	{
		head=Create();	
	}
	Show(head);
	printf("\n\n\t——现在开始查找女教师信息——");
		FindFemale(head);
	printf("\n\n\t——算法结束——");
	return 0;
 } 
//创建函数 
struct Node* Create()
{
	int i=1;
	int x;
	struct Node *p=(struct Node*)malloc(sizeof(struct Node));
	struct Node *p0,*head;

		printf("\n\n\t请输入第%d个教师信息:",i);
		printf("\n\t姓名:");
			scanf("%s",(*p).name);
		printf("\n\t性别:(男-1;女-0)");
			scanf("%d",&(*p).sex);
		printf("\n\t年龄:");
			scanf("%d",&(*p).age); 
		(*p).next=NULL; 
		p0=p;
		head=p;
		
		printf("\n\n\t请问是否要继续输入?继续输入-1,否则输入-0");
			scanf("%d",&x);
		
	while(x==1)
	{
		p=(struct Node*)malloc(sizeof(struct Node));
		(*p0).next=p;
			printf("\n\n\t请输入第%d个教师信息:",i);
		printf("\n\t姓名:");
			scanf("%s",(*p).name);
		printf("\n\t性别:(男-1;女-0)");
			scanf("%d",&(*p).sex);
		printf("\n\t年龄:");
			scanf("%d",&(*p).age); 
		(*p).next=NULL; 
		p0=p;
		
		printf("\n\n\t请问是否要继续输入?继续输入-1,否则输入-0");
		scanf("%d",&x);
	}
	return head;
}
//显示函数 
void Show(struct Node *head)
{
	printf("\n\n\t——显示函数——");
	struct Node *h=head;
	while(h!=NULL)
	{
		printf("\n\n\t姓名:%s  年龄: %d  性别:",(*h).name,(*h).age);
			if((*h).sex==1)
				printf("男");
			else if((*h).sex==0)
				printf("女");
		h=(*h).next;
	}
}
//查找女性教师 
void FindFemale(struct Node* head)
{
	FILE *fp;
	if((fp=fopen("E://output.txt","w"))==NULL)
	{
		printf("\n\n\t文件打开出错");
		exit(0);
	}
	
	struct Node *h;
	h=head;
	while(h!=NULL)
	{
		if((*h).sex==0)
		{
			fprintf(fp,"\n\n姓名:%s  年龄:%d  性别:",(*h).name,(*h).age);
			if((*h).sex==0)//不是我沙雕了,我是想测试一下对不对 
				fprintf(fp,"女");
		}
		h=(*h).next;
	}
	
	fclose(fp);
 } 

2015级唐班(A卷)

1.编写函数,将一个十进制整数转换为二进制输出。

算法思想:
不断用十进制数除以二并取余数,设置一个数组保存余数然后逆序输出。

#include 
#define N 50
void change2(int x);//十进制转二进制函数

int main()
{
	printf("\n\n\t——本函数用于将十进制数转换为二进制——");
	printf("\n\n\t请输入要转换的十进制数: ");
		int x;
		scanf("%d",&x);
	change2(x);
	printf("\n\n\t——算法结束——");
	return 0;
 } 
//十进制转换为二进制的函数 
void change2(int x)
{
	int a[N];
	int i=0;
	while(x!=0)
	{
		if(x%2==1)
			a[i]=1;
		else if(x%2==0)
			a[i]=0;
		i++;
		x=x/2;
	}
	printf("\n\n\t转换而成的二进制为: ");//逆序输出数组 
	for(int j=i-1;j>=0;j--)
	{
		printf("%d ",a[j]);
	}
}

2.编写函数 int mergearr (int a[], int m, int b[], int n),将两个严格增序数组a和b合并后存储在a中,并保证处理后的数组仍然严格增序,函数值返回合并后数组a中的元素个数,不能定义额外的新数组。

算法思想:
这道题中的考察点主要是“严格增序”,非严格增序可以存在相同元素,严格增序则不能,也就是说在合并之后需要去重(或者直接在合并过程中检测到重复的就删除,毕竟在原数组中不会出现重复)

#include 
#define N 50
int mergearr(int a[],int m,int b[],int n);

int main()
{
	printf("\n\n\t——本函数用于合并两个严格递增函数——");
	int a[2*N];
	int b[N];
	
	//用户输入数组长度 
	printf("\n\n\t请输入a数组的长度:");
		int m;
		scanf("%d",&m);
	printf("\n\n\t请输入b数组的长度:");
		int n;
		scanf("%d",&n);
	
	//用户输入数组数据 
	printf("\n\n\t请输入A数组:");
	int i;
		for( i=0;i<m;i++)
		{
			scanf("%d",&a[i]);
		}
	printf("\n\n\t请输入B数组:");
		for( i=0;i<n;i++) 
		{
			scanf("%d",&b[i]);
		}
		
	int len=mergearr(a,m,b,n);//调用合并函数
	
	//输出结果 
	printf("\n\n\t合并后的数组长度为: %d  数组数据为:",len);
		for(i=0;i<len;i++)
		{
			printf("%d ",a[i]);
		 } 
	printf("\n\n\t——算法结束——");
	return 0; 
}

int mergearr(int a[],int m,int b[],int n)
{
	int i=0,j;//i是A的下标,j是B的下标
	int count=m;
	for(int j=0;j<n;j++)//遍历B数组 
	{
		while(b[j]>a[i])//寻找插入位置 
		{
			i++;
		 } 
		//去重处理
		if(b[j]==a[i])
		{
			continue;//跳过本次循环,直接看下一位 
		 } 
		//进行插入 
		for(int k=m;k>i;k--)//挪出插入位置 
		{
			a[k]=a[k-1];
		}
		a[i]=b[j]; 
		count++;//长度计数器加一 
		m++;
	 } 
	return count; 
}

*3.根据递归公式给出递归函数:
f(n) = 1(n=2时)
f(n) = f(i)f(n+1-i)从2到n-1项的加和 (n>=3时)

算法思想:
算就完事了莫得思想

#include 
int cal(int n,int i);//递归函数

int main()
{
	printf("\n\n\t——本函数用于根据递归式进行递归计算——");
	printf("\n\n\t请输入n值: ");
		int n;
		scanf("%d",&n);
		while(n<4)
		{
			printf("\n\n\t输入错误,请输入大于等于3的n 值:");
			scanf("%d",&n);
		}
	int i=2;
	printf("\n\n\t计算结果为 %d",cal(n,i));
	printf("\n\n\t——算法结束——");
	return 0;
 } 
 
int cal(int n,int i)
{
	if(n==2)
		return 1;//递归出口
	else if(n>=3) 
	{
		if(i==(n-1))
			return cal(n-1,i)*cal(n+1-i,i);
		else if(i<(n-1))
			return cal(i,i)*cal(n+1-i,i)+cal(i,i+1)*cal(n+1-i,i+1);
	}
}

4.职工的信息卡至少包括工号、姓名出生年月等信息。限定:工号为整形且不超过整形的取值范围。
1)定义存储职工信息的单向链表的节点类型;

答:见结构体定义。

2)编写函数,由文件in.txt中依次读入k个职工的完整信息,创建一个用于管理职工信息的单向链表;
答:知识点:从文件读入并创建链表,见 Create 函数。

3)假定管理职工信息的单向链表已经按照工号从小到大排序。编写函数,由键盘键入1个职工的信息,按工号顺序插入到用于管理职工信息的单向链表中。
答:知识点:链表按序插入,见 Insert 函数。

#include 
#include 
#define N 20
struct Node{
	int num;
	char name[N];
	int date;
	struct Node* next;
};

void WriteFile();//为了测试方便先写入文件 
struct Node* Create();//从文件读入并创建链表 
struct Node* Insert(struct Node *head);//向有序链表插入结点 
void Show(struct Node* head);//显示链表函数

int main()
{
	printf("\n\n\t——本函数用于链表操作——");
	//初次使用应当写入文件 
	printf("\n\n\t请问是否需要写入文件?");
	printf("\n\t需要请输入1;不需要请输入0:");
		int x;
		scanf("%d",&x);
	if(x==1)
		WriteFile();
	
	//从文件读入并创建链表
	struct Node* head=Create(); 
	//显示链表
	Show(head);
	//向链表插入数据
	printf("\n\n\t请问是否向链表插入数据?(是-1;否-0)");
		scanf("%d",&x);
	
	struct Node* nhead;
	while(x==1)
	{
	    nhead=Insert(head); 
	    Show(nhead);
	    printf("\n\n\t请问是否继续插入数据?(继续插入-1;否-0 )");
	    	scanf("%d",&x);
	}
	
	printf("\n\n\t——算法结束——");
	return 0;
 } 
 
//写入文件 
void WriteFile()
{
	printf("\n\n\t——请向文件写入职工信息——");
	
	//打开文件 
	FILE *fp;
	if((fp=fopen("E://in.txt","w"))==NULL)
	{
		printf("Can't open this file.\n'");
		exit(0);
	}
	
	//用户写入文件 
	int i=1;
	int x=0;
	do{
	printf("\n\n\t第%d位职工信息:\n\t工号:",i);
		int num;
		char name[N];
		int date;
		scanf("%d",&num);
	printf("\n\t姓名:");
		scanf("%s",name);
	printf("\n\t出生日期:");
		scanf("%d",&date);
	fprintf(fp,"%d ",num);
	fprintf(fp,"%s ",name);
	fprintf(fp,"%d \n",date);

	i++;
	printf("\n\n\t请问是否继续输入职工信息?继续,请输入1,否则输入0.");
		scanf("%d",&x);
	}while(x==1);
	
	fclose(fp);
	printf("\n\n\t——写入结束——");
}
//从文件读入职工信息并创建链表 
struct Node* Create()
{
	printf("\n\n\t——现在开始创建链表——");
	FILE *fp;
	if((fp=fopen("E:\\in.txt","r"))==NULL)
	{
		printf("\n\n\t文件打开错误。");
		exit(0);
	}
	
	struct Node* head;
	struct Node *p,*p0;
	p=(struct Node*)malloc(sizeof(struct Node));
	fscanf(fp,"%d",&(*p).num);
	fscanf(fp,"%s",(*p).name);
	fscanf(fp,"%d",&(*p).date);
	(*p).next=NULL;
	p0=p;
	head=p;
	char ch;
	while((ch=fgetc(fp))!=EOF)
	{
		p=(struct Node*)malloc(sizeof(struct Node));
		fscanf(fp,"%d",&(*p).num);
		fscanf(fp,"%s",(*p).name);
		fscanf(fp,"%d",&(*p).date);
		(*p).next=NULL;
		(*p0).next=p;
		p0=p;
	}
	fclose(fp);//关闭文件指针 
	printf("\n\n\t——链表创建完成——");
	return head;
}
//向有序链表插入结点
struct Node* Insert(struct Node *head) 
{
	printf("\n\n\t请输入要插入结点的数据:");
	struct Node *p=(struct Node*)malloc(sizeof(struct Node));

	printf("\n\n\t工号:");
		scanf("%d",&(*p).num);
	printf("\n\t姓名:");
		scanf("%s",(*p).name);
	printf("\n\t出生日期:");
		scanf("%d",&(*p).date);	 
	(*p).next=NULL;
	
	//遍历链表找到相应位置
	struct Node *h,*p0;
	h=head;
	p0=h;
	while(h!=NULL)
	{
		if((*h).num>=(*p).num)//插入 
		{
			if(h==head)  //头指针特殊处理 
			{
				(*p).next=h;
			    	head=p;
				break; 
			}
			else{
				(*p).next=h;
				(*p0).next=p;
				break;
			}	
		}
		else
		{
			p0=h;
			h=(*h).next;
		}
	 } 
	return head;
 } 
//显示链表函数
void Show(struct Node* head)
{
	struct Node *h;
	h=head;
	while((*h).next!=NULL)
	{
		printf("\n\n\t工号:%d  姓名:%s  出生日期:%d",(*h).num,(*h).name,(*h).date);
		h=(*h).next;
		}
}

2014级期末考试题A

1.编写函数 int delarr(int a[] ,int n),并画出对应的PAD,删除有n个元素的正整型数组a中所有素数,要求:
1)数组a中剩余元素保持原来次序;
2)将处理后的素组输出;
3)函数值返回剩余元素个数;
4)不能额外定义新数组。

算法思想:
①独立设置一个判断素数的函数;
②删除元素的时候使用覆盖的方法;
③考虑两个素数相连的情况。

#include 
#define N 20
int delarr(int a[],int n);//删除数组中的所有素数
bool IsPrime(int x);//判断x是不是素数 

int main()
{
	printf("\n\n\t——本函数用于删除数组中的所有素数——");
		int a[N];
	printf("\n\n\t请输入数组长度:");
		int n;
		scanf("%d",&n);
	printf("\n\n\t请输入数组数据:"); 
		for(int i=0;i<n;i++)
		{
			scanf("%d",&a[i]);
		}
	int len=delarr(a,n);//调用函数
	printf("\n\n\t删除素数后,数组中还有%d个元素,",len);
	printf("\n\n\t数组数据为: ");
		for(int i=0;i<len;i++)
			printf("%d ",a[i]);
	printf("\n\n\t——算法结束——");
	return 0; 
 } 
//删除数组中的素数 
int delarr(int a[],int n)
{
	int len=n;
	for(int i=0;i<len;i++)
	{
		if(IsPrime(a[i])==true)//如果是素数,删除素数 
		{
			for(int k=i;k<len;k++)
			{
				a[k]=a[k+1];
				len--;
				i--;//避免两个素数相连的问题 
			}
		}
	}
	return len;
}
//判断素数函数,是素数返回true ,不是素数返回false
bool IsPrime(int x)
{
	if(x==1)
	{
		return false;
	}
	for(int i=2;i<x;i++)
	{
		if((x%i)==0)
		{
			return false;
		}
	}
	return true;
 } 

*2.编写函数bool cmpstr(char s),判定一个给定字符串s是否对称,对称字符串也成为回文,是满足从左到右和从右到左均相同的字符序列(不考虑默认字符串结尾’\0’)

算法思想:
先统计字符串长度,再前后比较

#include 
#define N 20
bool cmpstr(char *s);//判断是否是回文 

int main()
{
	printf("\n\n\t——本函数用于判断一个字符串是不是回文——");
	printf("\n\n\t请输入字符串:");
		char s[N];
		scanf("%s",s);
	if(cmpstr(s)==true)
		printf("\n\n\t是回文。");
	else
		printf("\n\n\t不是回文。");
	printf("\n\n\t——算法结束——");
	return 0;
}
//判断是否是回文 
bool cmpstr(char *s)
{
	//首先计算字符串长度
	int n=0;
    int	i=0;
	while(s[i]!='\0')
	{
		n++;
		i++;
	 } 
	//判断是否是回文
	int j=n-1;
	for(i=0;i<n/2;i++)
	{
		if(s[i]!=s[j])
		{
			return false;
		}
		else
		{
			j--;
		}
	 } 
	return true;
}

3.编写递归函数float comp(float a[],int n),计算给定n个元素的float型数组中所有元素的算术平均值。
算法思想:
要计算算术平均值,需要连续加法和一次除法,因此除法只能是顶层运算,特殊处理。

#include 
#define N 20
float comp(float a[],int n);

int main()
{
	printf("\n\n\t——本函数用于递归计算浮点型数组的算术平均值——");
	printf("\n\n\t请输入浮点型数组长度:");
		int n;
		scanf("%d",&n);
	printf("\n\n\t请输入浮点型数组数据:");
		float a[N];
		for(int i=0;i<n;i++)
		{
			scanf("%f",&a[i]);
		}
	//调用递归函数
	printf("\n\n\t该浮点型数组的算术平均值为 %.2f ",comp(a,n));
	printf("\n\n\t——算法结束——");
	return 0; 
 } 

//递归计算浮点型函数
float comp(float a[],int n)
{
	
	if(a[n]=='\0')//最顶层是除法运算 
	{
		return comp(a,n-1)/n;
	}
	if(n==0)//底层都是加法 
	{
		return a[0];
	}
	else
	{
		return a[n]+comp(a,n-1);
	}
 } 

四、每个学生的信息卡片包括学号、姓名、年龄三项。定义存储学生信息的单向链表的节点类型;编写函数,由键盘依次输入n个学生的信息,创建一个用于管理学生信息的单向链表。

五、编写函数,把上中创建的单向链表中所有年龄为z的几点删除(z的指由用户键盘输入,且年龄为z的结点可能有多个),将处理后的单向链表的所有学生信息存储到名为output.txt的文本文件中。

算法思路:
四和五连起来写了

#include 
#include 

struct Node{
	int num;
	char name[20];
	int age;
	struct Node* next;
};

struct Node* Create();//创建链表函数
void Show(struct Node * head);//显示链表函数
struct Node* Delete(struct Node* head,int z);//删除年龄为z的结点
void WriteFile(struct Node *head);//将链表写入文件

int main()
{
	printf("\n\n\t——本函数用于处理学生信息——");
	printf("\n\n\t请先创建链表:");
		struct Node *head=Create();
	printf("\n\n\t您创建的链表为:\n");
		Show(head);
	printf("\n\n\t请输入要被删除的年龄z:");
		int z;
		scanf("%d",&z);
		struct Node *nhead=Delete(head,z);
	printf("\n\n\t删除后的链表为:");
		Show(nhead);
	
	//写入文件
		WriteFile(nhead);
	printf("\n\n\t——算法结束——");
	return 0; 
 } 
 //创建链表函数
struct Node* Create()
{
	struct Node* head,*p,*p0;
	p=(struct Node*)malloc(sizeof(struct Node))	;
	p0=p;
	head=p;
	
	int i=1;
	printf("\n\n\t请输入第%d 个学生信息:",i);
	i++;
	printf("\n\t姓名:");
		scanf("%s",(*p).name);	
	printf("\n\t学号:");
		scanf("%d",&(*p).num);
	printf("\n\t年龄:");
		scanf("%d",&(*p).age);
	(*p).next=NULL;
	printf("\n\n\t请问是否要继续输入?(是-1;否-0)");
		int x;
		scanf("%d",&x);
		while((x!=1)&&(x!=0))
		{
			printf("\n\n\t输入错误,只能输入1或0,请重新输入: ");
			scanf("%d",&x);
		}
	while(x==1)
	{
		p0=p;
		p=(struct Node*)malloc(sizeof(struct Node));
		(*p0).next=p;
			printf("\n\n\t请输入第%d 个学生信息:",i);
		i++;
		printf("\n\t姓名:");
			scanf("%s",(*p).name);	
		printf("\n\t学号:");
			scanf("%d",&(*p).num);
		printf("\n\t年龄:");
			scanf("%d",&(*p).age);
		(*p).next=NULL;
		
		printf("\n\n\t请问是否要继续输入?(是-1;否-0)");
		scanf("%d",&x);
		while((x!=1)&&(x!=0))
		{
			printf("\n\n\t输入错误,只能输入1或0,请重新输入: ");
			scanf("%d",&x);
		}
	}
	return head;
}
//显示函数 
void Show(struct Node * head)
{
	struct Node * h;
	h=head;
	while(h!=NULL)
	{
		printf("\n\n\t学号:%d  姓名:%s  年龄:%d",(*h).num,(*h).name,(*h).age);
		h=(*h).next;
	}
}
//删除年龄为z的结点
struct Node* Delete(struct Node* head,int z)
{
	struct Node *h,*p0;
	h=head;
	p0=h;//p0是p的前驱结点 
	while((*h).next!=NULL)
	{
		if((*h).age==z)
		{
			if(h==head)//头结点特殊处理
			{
				h=(*h).next;
				p0=h;
				head=h;
			 } 
			else{
				(*p0).next=(*h).next;
				h=(*p0).next;
			}
		}
		else{
			p0=h;
			h=(*h).next;
		}
	}
	return head;
 } 
//将链表写入文件
void WriteFile(struct Node *head)
{
	FILE *fp;
	if((fp=fopen("E://output.txt","w"))==NULL)
	{
		printf("\n\n\t打开文件失败");
		exit(0);
	}
	
	struct Node *h;
	h=head;
	while(h!=NULL)
	{
		fprintf(fp,"%d %s %d \n",(*h).num,(*h).name,(*h).age);
		h=(*h).next;
	}
	
	fclose(fp);
}

2014级B卷

一、编写函数并画出对应的PAD,删除整形数组中所有为0的元素,将处理后的数组输出,并返回剩余元素个数。
注意:函数中不能定义额外的新数组。

算法思想:
注意连续两个零的情况。

#include 
#define N 20
int Del(int *a,int n);//删除A数组中所有为零的元素,n为数组长度,返回值为剩余元素个数

int main()
{
	printf("\n\n\t——本函数用于删除数组中所有零元素——");
	printf("\n\n\t请输入数组长度:");
		int n;
		scanf("%d",&n);
	printf("\n\n\t请输入数组数据:");
		int a[N];
		for(int i=0;i<n;i++)
		{
			scanf("%d",&a[i]);
		}
	//调用删除函数
	int len=Del(a,n);
	printf("\n\n\t剩余元素个数为%d,数组数据为:",len);
		for(int i=0;i<len;i++)
		{
			printf("%d ",a[i]);
		 } 
	printf("\n\n\t——算法结束——");
	return 0;
 } 
//删除A数组中所有为零的元素,n为数组长度,返回值为剩余元素个数
int Del(int *a,int n)
{
	int i;
	for(i=0;i<n;i++)
	{
		if(a[i]==0)
		{
			int j;
			for(j=i;j<n;j++)
			{
				a[j]=a[j+1];
			}
			n--;//数组长度减短
			i--;//避免连续两位是零 
		}
	}
	return n;
}

2.编写函数,对一个给定字符串中的所有字符(不考虑默认字符串结束符’\0’)进行排序,使得排序后的字符串满足从左到右为ASCLL码递增的字符序列。
注:本题中不准使用string.h头文件和相关的字符串处理函数,以及系统定义的各类排序函数。

算法思想:
依然是冒泡排序,只是换成了字符型。

#include 
#define N 20
void Sort(char *a,int n);//排序函数无返回值,第一个参数为数组首地址,第二个为数组长度

int main()
{
	printf("\n\n\t——本程序用以给字符串按照阿瑟码排序——");
	printf("\n\n\t请输入字符串的长度:");
		int n;
		scanf("%d",&n);
	printf("\n\n\t请输入字符串");
		char s[N];
		scanf("%s",s);
	Sort(s,n);
	printf("\n\n\t排序后的字符串为:");
		for(int i=0;i<n;i++)
			printf("%c",s[i]);
	printf("\n\n\t——算法结束——") ;
	return 0;
 } 
 
void Sort(char *a,int n)
{
	bool change;
		for(int i=0;i<n;i++)
		{
			change=false;
			for(int j=0;j<n-i-1;j++)
			{
				if(a[j]>a[j+1])//发现反序对 
				{
					char temp=a[j+1];
					a[j+1]=a[j];
					a[j]=temp;
					change=true; 
				}
			}
			if(change==false)//无反序对时,跳出循环 
				break;
		}
}

3.编写递归函数,计算给定数组中所有元素的中位数,中位数标准定义为:按照从小到大排序后正中间的数。如果元素个数为偶数,取最中间的两个数的平均数作为中位数。本题可以粗略地认为n个元素的中位数为按照从小到大排序后的第n/2个数。

算法思想:
这个递归函数要完成排序,和找中位数两个功能。
这个题我用臭流氓打法解决了,大家如果有正经思路欢迎在评论区进行分享。

#include 
#define N 20
int FindMid(int *a,int n,bool sort);

int main()
{
	printf("\n\n\t——本程序用于找中位数——");
	printf("\n\n\t请输入数组长度:");
		int n;
		scanf("%d",&n);
	printf("\n\n\t请输入数组数据:");
		int a[N];
		for(int i=0;i<n;i++)
		{
			scanf("%d",&a[i]);
		 } 
	printf("\n\n\t数据中的中位数为: %d",FindMid(a,n,false));
	printf("\n\n\t——算法结束——");
	return 0;
 } 
 
int FindMid(int *a,int n,bool sort)
{
	if(sort==true)
	{
		return a[n/2];
	}
	else if(sort==false)
	{
		bool change;
		for(int i=0;i<n;i++)
		{
			change=false;
			for(int j=0;j<n-i-1;j++)
			{
				if(a[j]>a[j+1])//发现反序对 
				{
					char temp=a[j+1];
					a[j+1]=a[j];
					a[j]=temp;
					change=true; 
				}
			}
			if(change==false)//无反序对时,跳出循环 
				break;
		}
		return FindMid(a,n,true);
	}
}

4.每个教师的信息卡片包括教工号、姓名、性别、入职年份(限定为1900-2100之间的整数)思想。定义存储教师信息的单向链表的结点类型;编写函数,由当前目录下文件名为:input.txt的文件依次读入n个教师的信息,创建一个用于管理信息的单向链表。
(四题五题一起写了)
5.编写函数,在上题创建的单向链表中删除所有入职年份大于k(k的值由用户从键盘输入,且限定为1900-2100之间的整数)的结点。

算法思想:
我们来捋顺一下这道题在上机操作时到底需要多少个函数:
①首先定义结构体;
②定义一个向文件写入的函数;
③定义一个从文件读取并创建链表的函数;
④为了测试要定义一个显示函数;
⑤用户输入k并删除相应结点。

#include 
#include 
//结构体定义 
struct Node{
	int num;
	char name[20];
	int sex;
	int year;
	struct Node* next;
};

//函数声明
void WriteFile();//从键盘写入函数
void WriteHead(struct Node *head);//将链表保存到文件函数 
struct Node* Create();//从文件读入并创建函数 
void Show(struct Node * head);//显示函数
struct Node* Del(struct Node* head,int k);//删除年份为k的结点 

//主函数
int main() 
{
	printf("\n\n\t——本算法用于处理教师信息——");
	printf("\n\n\t请问是否需要写入数据?初次调用本系统需写入。");
	printf("\n\t需要——1;不需要——0");
		int x;
		scanf("%d",&x);
		while((x!=1)&&(x!=0))
		{
			printf("\n\n\t输入错误,请输入1或0");
			scanf("%d",&x);
		}
		if(x==1)
		{
			WriteFile();
		}
	struct Node *head=Create();//从文件读入并创建链表
	//显示链表
	Show(head);
	//删除年份为k的结点
	printf("\n\n\t请问您要删除的年份是? ");
		int k;
		scanf("%d",&k);
	struct Node *newhead=Del(head,k);
	Show(newhead);
	WriteHead(newhead);//保存改变
	printf("\n\n\t——算法结束——");
	return 0; 
}
//从键盘写入函数
void WriteFile()
{
	FILE *fp;
	if((fp=fopen("E://input.txt","w"))==NULL)
	{
		printf("文件打开错误。");
		exit(0);
	}
	
	int i=1;
	printf("\n\n\t请输入第%d位教师信息:",i);
	i++;
	printf("\n\t姓名:");
		char name[20];
		scanf("%s",name);
	printf("\n\t工号:");
		int num;
		scanf("%d",&num);
	printf("\n\t性别:");
		int sex;
		printf("\n\t男—1,女—0");
		scanf("%d",&sex);
		while((sex!=1)&&(sex!=0))
		{
			printf("\n\t只能输入1或0,请重新输入:");
			scanf("%d",&sex);
		}
	printf("\n\t年份:");
		int year;
		scanf("%d",&year);
		while((year<1900)||(year>2100))
		{
			printf("\n\t入职年份区间为1900-2100,请重新输入:");
			scanf("%d",&year);
		}
	//写入文件 
	fprintf(fp,"%d %s %d %d\n",num,name,sex,year);
	//继续输入 
	printf("\n\n\t请问是否继续输入数据?(是-1,否-0)");
		int x;
		scanf("%d",&x);
		while((x!=1)&&(x!=0))
		{
			printf("\n\n\t输入错误,请输入1或0");
			scanf("%d",&x);
		}
	
	while(x==1)
	{
	printf("\n\n\t请输入第%d位教师信息:",i);
	i++;
	printf("\n\t姓名:");
		char name[20];
		scanf("%s",name);
	printf("\n\t工号:");
		int num;
		scanf("%d",&num);
	printf("\n\t性别:");
		int sex;
		printf("\n\t男—1,女—0");
		scanf("%d",&sex);
		while((sex!=1)&&(sex!=0))
		{
			printf("\n\t只能输入1或0,请重新输入:");
			scanf("%d",&sex);
		}
	printf("\n\t年份:");
		int year;
		scanf("%d",&year);
		while((year<1900)||(year>2100))
		{
			printf("\n\t入职年份区间为1900-2100,请重新输入:");
			scanf("%d",&year);
		}
	//写入文件 
	fprintf(fp,"%d %s %d %d\n",num,name,sex,year);
	
	//继续输入 
	printf("\n\n\t请问是否继续输入数据?(是-1,否-0)");
		scanf("%d",&x);
		while((x!=1)&&(x!=0))
		{
			printf("\n\n\t输入错误,请输入1或0");
			scanf("%d",&x);
		}
	}
	fclose(fp);//关闭文件 
 } 
//从文件读入并创建链表
struct Node* Create()
{
	printf("\n\n\t——正在从文件读入信息并创建链表——");
	FILE *fp;
	if((fp=fopen("E://input.txt","r"))==NULL)
	{
		printf("文件打开错误。");
		exit(0);
	}
	
	struct Node *p,*head,*p0;
	p=(struct Node*)malloc(sizeof(struct Node));
	head=p;
	p0=p;
	
	fscanf(fp,"%d",&(*p).num);
	fscanf(fp,"%s",(*p).name);
	fscanf(fp,"%d",&(*p).sex);
	fscanf(fp,"%d",&(*p).year);
	(*p).next=NULL;
	
	char ch;
	while((ch=fgetc(fp))!=EOF)
	{
		p=(struct Node*)malloc(sizeof(struct Node));
		(*p0).next=p;
			fscanf(fp,"%d",&(*p).num);
			fscanf(fp,"%s",(*p).name);
			fscanf(fp,"%d",&(*p).sex);
			fscanf(fp,"%d",&(*p).year);
			(*p).next=NULL; 
		p0=p;
	}
	fclose(fp);
	return head;
 } 
//将链表保存到文件函数
void WriteHead(struct Node *head)
{
	printf("\n\n\t——正在将链表保存到文件——");
	struct Node *p;
	p=head;
	
	FILE *fp;
	if((fp=fopen("E://input.txt","w"))==NULL)
	{
		printf("文件打开错误。");
		exit(0);
	}
	
	while((*p).next!=NULL)
	{
		fprintf(fp,"%d ",(*p).num);
		fprintf(fp,"%s ",(*p).name);
		fprintf(fp,"%d ",(*p).sex);
		fprintf(fp,"%d \n",(*p).year);
		p=(*p).next;
	}
	
	fclose(fp);
 } 
//显示函数
void Show(struct Node *head)
{
	printf("\n\n\t——显示链表数据——");
	struct Node *p;
	p=head;
	
	while((*p).next!=NULL)
	{
		printf("\n\n\t姓名:%s 工号:%d 入职年份:%d 性别:",(*p).name,(*p).num,(*p).year);
		if((*p).sex==1)
		{
			printf("男"); 
		}
		else if((*p).sex==0)
		{
			printf("女"); 
		}
		p=(*p).next;
	}
 }
//删除入职年龄为k的教师信息 
struct Node* Del(struct Node* head,int k)
{
	struct Node *p,*p0;
	p=head;
	p0=p;
	while(p!=NULL)
	{
		if((*p).year==k)
		{
			if(p==head)//删除头指针特殊处理 
			{
				p=(*p).next;
				p0=p;
				head=p;
			}
			else{
				(*p0).next=(*p).next;
				p=(*p0).next;
			}
		}
		else{
			p0=p;
			p=(*p).next;
		}
	}
	return head;
}

2013级A卷

这张卷上的所有题前面都出过一模一样的。

2012级A卷

1.编写函数,输出任意正整数n的位数(n默认为存储十进制的整形变量)
例如:正整数13,则输出2,;正整数3088,则输出4

分离数位的基本操作。

#include 
int depart(int n);//分离数位函数并返回位数

int main()
{
	printf("\n\n\t——本函数用于计算某个正整数的位数——");
	printf("\n\n\t请输入n值:") ;
		int n;
		scanf("%d",&n);
	printf("\n\n\t位数为%d",depart(n));
	printf("\n\n\t——算法结束——");
	return 0;
 } 
 
int depart(int n)
{
	int count=0;
	while(n!=0)
	{
		n++;
		n=n/10;
		count++;
	}
	return count;
}

2.编写函数,对给定有序整形数组进行整理,使得所有整数只保留一次出现(去重。)

算法思想:因为有序,所以相同的数据必然相邻;上机时应当先对其进行排序操作。

#include 
#define N 20
void Sort(int *a,int n);//排序函数
int Only(int *a,int n);//去重函数

int main()
{
	printf("\n\n\t——本函数用于对数组进行去重——");
	printf("\n\n\t请输入数组长度:");
		int n;
		scanf("%d",&n);
	printf("\n\n\t请输入数组数据:");
		int a[N];
		for(int i=0;i<n;i++)
		{
			scanf("%d",&a[i]);
		}
		
	Sort(a,n);
	int len=Only(a,n);
	printf("\n\n\t去重后的数组为:");
		for(int i=0;i<len;i++)
			printf("%d ",a[i]);
	printf("\n\n\t——算法结束——");
	return 0;
 } 

void Sort(int *a,int n)
{
	bool change;
		for(int i=0;i<n;i++)
		{
			change=false;
			for(int j=0;j<n-i-1;j++)
			{
				if(a[j]>a[j+1])//发现反序对 
				{
					int  temp=a[j+1];
					a[j+1]=a[j];
					a[j]=temp;
					change=true; 
				}
			}
			if(change==false)//无反序对时,跳出循环 
				break;
		}
}

int Only(int *a,int n)
{
	int i;
	int len=n;
	for(i=0;i<len;i++)
	{
		if(a[i]==a[i+1])
		{
			for(int j=i+1;j<n;j++)
				a[j]=a[j+1];
			i--;//避免连续多个相同的情况 
			len--;
		}
	}
	return len;
}

3.编写递归函数,求两个数x和y的最大公约数。

#include 

int gcd(int x,int y);//递归找最大公约数

int main()
{
	printf("\n\n\t——本程序用于递归找最大公约数——");
	printf("\n\n\t请输入第一个数值:");
		int x;
		scanf("%d",&x);
	printf("\n\n\t请输入第二个数值:");
		int y;
		scanf("%d",&y);
	if(gcd(x,y)==1)
		printf("\n\n\t两数互质");
	else
		printf("\n\n\t它们的最大公约数为:%d",gcd(x,y));
	printf("\n\n\t——算法结束——");
	return 0;
 } 
 
int gcd(int x,int y)
{
	if(y==0)
		return x;
	else{
		return gcd(y,x%y);
	}
}

4.给定如图1所示的存储学生信息的结构体数组(每个结构体包含三个字段:姓名,性别,成绩)。编写函数,将制定文件in.txt
中所有的男生学生信息存储到该结构体数组中。(假定文件中存储信息与结构体格式对应)

算法思想:
创建结构体数组,从文件读入

我懒了,测试的时候需要自己先在E盘目录下创建一个in.txt,并写入数据

#include 
#include 
#define N 100

struct Node{      //结构体定义 
	char name[20];
	bool sex;
	int grade;
};

int main()
{
	FILE *fp;
	if((fp=fopen("E://in.txt","r"))==NULL)
	{
		printf("文件打开错误");
		exit(0);
	}
	
	struct Node stu[N];//定义结构体数组
	int i=0;
	
	char ch;
	while((ch=fgetc(fp))!=EOF)
	{
		fscanf(fp,"%s",stu[i].name);
		int check;
		fscanf(fp,"%d",&check);
			if(check==0)
				stu[i].sex=false;
			else if(check==1)
				stu[i].sex=true;
		fscanf(fp,"%d",&stu[i].grade);
	 } 
	
	fclose(fp);
}

5…给定一个单链表(每个结点包括两个字段:整数信息,后继指针),编写函数,删除该单链表中整数信息为奇数的结点。

#include 
#include 
struct Node{
	int data;
	struct Node* next;
};

struct Node * Del(struct Node *head);

int main()
{
	printf("\n\n\t——本函数用于删除链表中的奇数结点——");
	printf("\n\n\t请输入链表数据:");
	struct Node *p,*head;
	p=(struct Node*)malloc(sizeof(struct Node));
		head=p;
		int i=1;
		printf("\n\n\t请输入第%d个结点的数据值:",i);
			scanf("%d",&(*p).data);
			i++;
		(*p).next=NULL;
	printf("\n\n\t请问是否要继续输入(是=1,否=0): ");
		int x;
		scanf("%d",&x);
		while((x!=0)&&(x!=1))
		{
			printf("\n\n\t只能输入0或1,请重新输入:");
			scanf("%d",&x); 
		}
	struct Node *p0;
	
	while(x==1)
	{
		p0=p;
		p=(struct Node*)malloc(sizeof(struct Node));
		(*p0).next=p;
		
		printf("\n\n\t请输入第%d个结点的数据值:",i);
			scanf("%d",&(*p).data);
			i++;
		(*p).next=NULL;
			
		printf("\n\n\t请问是否要继续输入(是=1,否=0): ");
			scanf("%d",&x);
			while((x!=0)&&(x!=1))
			{
				printf("\n\n\t只能输入0或1,请重新输入:");
				scanf("%d",&x); 
			}
	}
	
	printf("\n\n\t——链表建立完成——");
	struct Node *h=Del(head);//调用删除奇数结点的函数
	printf("\n\n\t删除奇数数据节点后的链表为: ");
		while(h!=NULL)
		{
			printf("%d ",(*h).data);
			h=(*h).next;
		 } 
	printf("\n\n\t——算法结束——");
	return 0;
		
}

struct Node * Del(struct Node *head)
{
	struct Node* h,*p,*p0;
	p=head;
	h=head;
	p0=p;
	while(p!=NULL)
	{
		if(((*p).data%2)==1)
		{
			if(p==h)//头结点特殊处理 
			{
				p=(*p).next;
				h=p;
			}
			else{
				(*p0).next=(*p).next;
				p=(*p0).next;
			}
		}
		else if(((*p).data%2)==0)
		{
			p0=p;
			p=(*p).next;
		}
	}
	return h;
}

2011级A卷

1.编写函数,判定正整数m和n(均至少为2)是否满足:数m为数n的最小质因数(能整除n的最小质数)

#include 

bool IsPrime(int m,int n);//判断m是不是n的最小质因数
int main()
{
	printf("\n\n\t请输入整数n: ");
		int n;
		scanf("%d",&n);
		while(n<2)
		{
			printf("\n\n\tn值至少为2,请重新输入:");
			scanf("%d",&n); 
		}
	printf("\n\n\t请输入整数m: ");
		int m;
		scanf("%d",&m);
		while(m<2)
		{
			printf("\n\n\tm值至少为2,请重新输入:");
			scanf("%d",&m);
		}
	bool res=IsPrime(m,n);
	if(res==true)
	{
		printf("\n\n\t%d 是 %d 的最小质因数",m,n);
	}
	else if(res==false)
	{
		printf("\n\n\t%d 不是%d 的最小质因数",m,n);
	}
	printf("\n\n\t——算法结束——");
	return 0;
 } 
 
bool IsPrime(int m,int n)
{
	bool res=false;//防止没有素因数的情况
 
	for(int i=2;i<n;i++)
	{
		if(n%i==0) //i是因数 
		{
			bool p=true;//判断i是不是素数
			 
			for(int j=2;j<i/2;j++)
			{
				if(i%j==0)
				{
					p=false;
					break;
				}
			}
			
			if(p==true)//如果是素因数,判断是否等于m 
			{
				if(i==m)
				{
					res=true;
				}
				else if(i!=m)
				{
					res=false;
				}
				break;
			}
			
		}
	}
	return res;
}

2.编写函数,对给定的整数数组a的前n个元素排序,使得所有正整数均出现在负整数和零之前;(正整数序列和负整数序列不需要排序)
(个人认为出题老师想表达的意思是一个长为n的数组)

算法思想:
这个题就是繁琐:
①首先要先把零元素集中在一起;
②再次遍历,零前负数向后挪:
1)如果零后有正数,与零后第一个正数做交换;
2)如果零后没有正数,从当前位置开始整体向前挪一位,然后把当前数值存到最后一位;
③零后正数,将零到该正数的位置整体向后挪一位,然后该正数存到零前;
④零,零前正数,零后负数都不需要挪动。

#include 
#define N 20
void PositiveSort(int *a,int n);

int main()
{
	printf("\n\n\t请输入序列长度:");
		int n;
		scanf("%d",&n);
		while((n<0)||(n>N))
		{
			printf("\n\n\t序列长度应该在0-%d之间,请重新输入:",N);
			scanf("%d",&n);
		}
	printf("\n\n\t请输入序列数据:");
		int a[N];
		for(int i=0;i<n;i++)
		{
			scanf("%d",&a[i]);
		}
	PositiveSort(a,n);
	printf("\n\n\t排序后的数组为:");
		for(int i=0;i<n;i++)
		{
			printf("%d ",a[i]);
		}
	printf("\n\n\t——算法结束——");
	return 0;
 } 

void PositiveSort(int *a,int n)
{
	int ps,pe;//ps向第一个零的位置 
	bool l=false;
	int j;
	int temp; 
	for(int i=0;i<n;i++)
	{
		if((a[i]==0)&&(l==false))//找第一个零的位置 
		{
			ps=i;
			pe=ps;
			l=true;
		}
		else if((a[i]==0)&&(l==true))//把后面的零统一在一起 
		{
		 	pe++;//ps用来记录零元素结束的地方  
   //交换这个零与第一个零后面的一个数 
			temp=a[pe];
			a[pe]=a[i];
			a[i]=temp;
		}
	}

	//再次遍历,遇到正数放在零前,遇到负数放在零后
	for(int i=0;i<n;i++)
	{
		if(a[i]==0)
		{
			continue;//不处理零 
		}
	   if((a[i]>0)&&(i<ps))//在零前的正数不需要移动 
		{
			continue;
		}
	    if((a[i]<0)&&(i>pe))//在零后的负数不需要移动
		{
			continue;
		 } 
		bool change=false;
	   if((a[i]<0)&&(i<ps))//零前负数 
		{
			for(j=pe;j<n;j++)
			{
				if(a[j]>0)//与零后正数交换 
				{
					temp=a[i];
					a[i]=a[j];
					a[j]=temp;
					change=true;
					break;//交换之后退出循环 
				}
			 }
			if(change==false)//如果零后没有正数 ,存到最后一位 
			{
				temp=a[i];
				for(j=i;j<n;j++)
				{
					a[j]=a[j+1]; 
				}
				a[n-1]=temp;
				ps--;
				pe--;
			 } 
		 } 
	 if((a[i]>0)&&(i>pe))//零后正数
		{
			temp=a[i];
			for(j=i;j>ps;j--)
			{
				a[j]=a[j-1];
			}
			a[ps]=temp;
			ps++;
			pe++;
		 } 
	 } 
}

3.编写递归函数,实现如下计算式的功能,(如果独立编写阶乘运算函数,可以不考虑存储溢出)
f(n) = 0/(12!) + 1/(23!) + 2/(34!) + 3/(45!) + …+ n/((n+1)*(n+2)!),其中,n为自然数。

上文已经实现过一模一样的题。

4.定义一个表示学生的结构体(包含三个字段:姓名、性别、成绩),编写函数,将如图所示的结构体数组s中的前n个学生的信息,存储到目录下的output.txt文件中。(个人认为出题老师想表达的是存储n个学生的信息)

#include 
#include 
#include 
#define N 20
struct Node{
	char name[20];
	int sex;
	int grade;
};

int main()
{
	printf("\n\n\t请输入学生数量:");
		int n;
		scanf("%d",&n);
		while(n<0)
		{
			printf("\n\n\t学生人数不能为0,请重新输入:");
			scanf("%d",&n); 
		}
	struct Node s[N];
	printf("\n\n\t请写入学生信息:");
	for(int i=0;i<n;i++)
	{
		printf("\n\n\t请输入第%d个学生的信息:",i+1);
			printf("\n\n\t姓名:");
				scanf("%s",s[i].name);
			printf("\n\n\t性别(男-0,女-1):");
				scanf("%d",&s[i].sex);
				while((s[i].sex!=0)&&(s[i].sex!=1))
				{
					printf("\n\n\t只能输入0或1,请重新输入:");
					scanf("%d",&s[i].sex);
				}
	       printf("\n\n\t成绩:");
	       	   scanf("%d",&s[i].grade);		 
	}
	//打开文件
	FILE *fp;
	if((fp=fopen("E://output.txt","w"))==NULL)
	{
		printf("\n\n\t打开文件失败");
		exit(0);
	 } 
	
	for(int i=0;i<n;i++)
	{
		fprintf(fp,"%s %d %d\n",s[i].name,s[i].sex,s[i].grade);
	}
}

5.定义一个单链表(每个结点包含两个字段:整数信息,后继指针),编写函数,删除该单链表中所含整数信息等于整数x的多个重复结点。

#include 
#include 
struct Node{
	int data;
	struct Node *next;
};

int main()
{
	printf("\n\n\t请输入链表长度:");
		int n;
		scanf("%d",&n);
	printf("\n\n\t现在开始建立链表:");
	struct Node *p;
	struct Node *head,*p0;
	printf("请输入数据:"); 	
	p=(struct Node*)malloc(sizeof(struct Node));
	scanf("%d",&(*p).data);	
	(*p).next=NULL;
	head=p;
	p0=p;
	
	for(int i=0;i<n-1;i++)
	{
		p=(struct Node*)malloc(sizeof(struct Node));
		scanf("%d",&(*p).data);
		(*p).next=NULL;
		(*p0).next=p;
		p0=p;
	}
	
	printf("\n\n\t请输入想删除的数据:");
		int x;
		scanf("%d",&x);
	struct Node *h,*h0;
	h=head;
	h0=h;
	while(h!=NULL)
	{
		if((*h).data==x)
		{
			if(h==head)
			{
				h=(*h).next;
				head=h;
				}
			else
			{
				(*h0).next=(*h).next;
			 	h=(*h).next;
				}	
		}
		else{
			h0=h;
			h=(*h).next;
		}
	}
	
	printf("\n\n\t删除后的链表数据为:");
	h=head;
	while(h!=NULL)
	{
		printf("%d ",(*h).data);
		h=(*h).next;
		}	
		
}

2010级A卷

1.编写程序,根据如下公式计算圆周率π的值,精确到(1e-5)
π/2=(2/12/3)(4/34/5)…*(2n/(2n-1)*2n/(2n+1)…

个人觉得是递归,但是调不出来

2.编写程序,由键盘输入一个字符串(仅保留数字字符,英文字符和空格),把该字符串中英文字符和空格过滤掉,提取所有整数,并将得到的整数序列输出到文件in.txt中。

算法思想:
主要考察ASCLL码序列问题。

#include 
#define N 30

int main()
{
	printf("\n\n\t请输入字符串:");
		char a[N];
		scanf("%s",a);
	int i=0;
	while(a[i]!='\0')//48-57 
	{
		if((a[i]<48)||(a[i]>57))//ASCLL表上非数字部分 
		{
			a[i]=' ';//转为空格 
		}
		i++;
	}
	FILE *fp;
	if((fp=fopen("E://in.txt","w"))==NULL)
	{
		printf("打开文件失败");
	}
	
	fprintf(fp,"%s",a);
	
	printf("\n\n\t——算法结束——");
	return 0;
}

3.编写程序,打印一个n行n列矩阵中所有满足下面条件的元素aij;
1)aij是第i行中所有元素的最大值;
2)如果将第j列中所有元素按照从小到大的顺序排序,aij是排列后的中位数。

算法思想:
1)遍历第i行,预设最大值,每一行输出一个最大值(多个最大值特殊处理);
2)按列遍历,单独设置一个一维数组排序的函数;

#include 
#define N 3

int FindMid(int *a);//找一维数组中位数的函数
void ErWei(int a[][N]);//题设函数

int main()
{
	printf("\n\n\t请输入数组数据(%dX%d):\n",N,N);//用户输入数据 
		int a[N][N];
		int i,j;
		for(i=0;i<N;i++)
		{
			printf("\t");	
			for(j=0;j<N;j++)
				scanf("%d",&a[i][j]);
		}
			
	ErWei(a);
	printf("\n\n\t——算法结束——");
	return 0;
 } 
 
void ErWei(int a[][N])
{
	//按行遍历,输出每行最大元素
	int i,j;
	for(i=0;i<N;i++)
	{
		int max=a[i][0];//找最大值 
		for(j=1;j<N;j++)
		{
			if(a[i][j]>max)
				max=a[i][j];
		}
		
		for(j=0;j<N;j++)  //避免多个最大值的情况 
		{
			if(a[i][j]==max)
				printf("\n\ta[%d][%d]为第%d行最大值:%d",i,j,i,max);
		}
	}
	
	//按列遍历,输出列中位数
	printf("\n\n");
	int s[N];
	for(j=0;j<N;j++)
	{
		for(i=0;i<N;i++)
			s[i]=a[i][j];
	 	
		int r;	
		r=FindMid(s);
		printf("\n\t%d 是第%d列的中位数。",r,j+1);
	 } 		 
}

//找一维数组中位数的函数
int FindMid(int *a)
{
	int i,j;
	for(i=0;i<N;i++)//先冒泡排序 
	{
		bool swap=false;
		for(j=0;j<N-1-i;j++)
		{
			if(a[j]>a[j+1])
			{
				int temp=a[j];
				a[j]=a[j+1];
				a[j+1]=temp;
				swap=true;
			}
		}
		if(swap==false)
		{
			break;
		}
	}
	return a[N/2];//返回中位数 
}

4.每个学生的信息卡片包括学号、姓名和性别三项。编写程序,由键盘依次输入n个学生的信息,创建一个用于管理学生信息的单链表,并在该单链表中添加一个给定结点x。(个人认为出题老师的意思是写一个插入函数)
四五合并在一起写了
5.编写程序,在上述建立的单链表中删除所有学号为z的结点(学号为z的结点可能有多个。)

#include 
#include 

struct Node{
	int num; //学号 
	char name[20]; //姓名 
	int sex;   //性别 
	struct Node *next;
};

struct Node* Create();//创建链表函数,返回头指针
struct Node* Insert(struct Node *head);//向链表插入结点
struct Node* Delete(struct Node *head,int x);//删除特定结点函数
void Show(struct Node* head);

int main()
{
	printf("\n\n\t——本程序用于对学生信息进行操作——");
	
	struct Node*head =Create();
	Show(head);
	
	printf("\n\n\t请问是否要向链表插入结点?");
		printf("是——1,否——0");
		int k;
		scanf("%d",&k); 
		while((k!=1)&&(k!=0))
		{
			printf("\n\n\t只能输入1或0,请重新输入:");
			scanf("%d",&k);
		}
	if(k==1)
	{
		head=Insert(head);
		Show(head);
	}
	
	printf("\n\n\t请输入要删除结点的学号数据:");
		int x;
		scanf("%d",&x);
		head=Delete(head,x);
		Show(head);
	
	printf("\n\n\t——算法结束——");
	return 0;
 } 

struct Node* Create()
{
	printf("\n\n\t——正在创建链表——");
	printf("\n\n\t请输入学生信息:");
		
	struct Node *p,*p0,*head;
	p=(struct Node*)malloc(sizeof(struct Node));
	head=p;
	p0=p;
	
	printf("\n\n\t姓名:");
		scanf("%s",(*p).name);
	printf("\n\n\t学号:");
		scanf("%d",&(*p).num);
	printf("\n\n\t性别:(男-1;女-0)");
		scanf("%d",&(*p).sex);
		while(((*p).sex!=0)&&((*p).sex!=1))
		{
			printf("\n\n\t只能输入1或0,请重新输入:");
			scanf("%d",&(*p).sex);
		}
	(*p).next=NULL;
	printf("\n\n\t请问是否要继续输入?是——1,否——0   :");
		int x;
		scanf("%d",&x);
		while((x!=1)&&(x!=0))
		{
			printf("\n\n\t只能输入1或0,请重新输入:");
			scanf("%d",&x);
		}
		
	while(x==1)
	{
	p=(struct Node*)malloc(sizeof(struct Node));
	printf("\n\n\t姓名:");
		scanf("%s",(*p).name);
	printf("\n\n\t学号:");
		scanf("%d",&(*p).num);
	printf("\n\n\t性别:(男-1;女-0)");
		scanf("%d",&(*p).sex);
		while(((*p).sex!=0)&&((*p).sex!=1))
		{
			printf("\n\n\t只能输入1或0,请重新输入:");
			scanf("%d",&(*p).sex);
		}
	(*p).next=NULL;
	(*p0).next=p;
	p0=p;
	printf("\n\n\t请问是否要继续输入?是——1,否——0   :");
		scanf("%d",&x);
		while((x!=1)&&(x!=0))
		{
			printf("\n\n\t只能输入1或0,请重新输入:");
			scanf("%d",&x);
		}
	}
	
	return head;
}

struct Node * Insert(struct Node*head)
{
	printf("\n\n\t请输入要插入结点的数据:");
	struct Node *p;
	p=(struct Node*)malloc(sizeof(struct Node));
	printf("\n\n\t姓名:");
		scanf("%s",(*p).name);
	printf("\n\n\t学号:");
		scanf("%d",&(*p).num);
	printf("\n\n\t性别:(男-1;女-0)");
		scanf("%d",&(*p).sex);
		while(((*p).sex!=0)&&((*p).sex!=1))
		{
			printf("\n\n\t只能输入1或0,请重新输入:");
			scanf("%d",&(*p).sex);
		}
	struct Node *h;
	h=(*head).next;
	
	(*p).next=h;
	(*head).next=p;
	return head;	
}

struct Node* Delete(struct Node*head,int x)
{
	struct Node* h=head;
	struct Node *p0=h;
	while(h!=NULL)
	{
		if((*h).num==x)
		{
			if(h==head)
			{
				h=(*h).next;
				head=h;
			}
			else{
				(*p0).next=(*h).next;
				h=(*h).next;
			}
		}
		else
		{
		p0=h;
		h=(*h).next;		
		}
	}
	return head;
}

void Show(struct Node*head)
{
	struct Node*h=head;
	while(h!=NULL)
	{
		printf("\n\n\t姓名:%s  学号:%d 性别:  ",(*h).name,(*h).num);
		if((*h).sex==0)
			printf("女");
		else
		{
			printf("男");
		}
		h=(*h).next;
	}
}

你可能感兴趣的:(吉大期末题)