期末编程训练

某不知名学校(dgut)的期末最后一次作业,说实话。。。也挺水的,不少还是之前写过的题

很多题还是不给输出不给输入,简直就是**,磨练心智磨练的一学期了,还是难以接受,每次都想吐槽一下

 

那么,看题吧。

第一题

请编写函数void fun(int x,int *pp,int *n),它的功能是:求出x的偶数因子,并按从小到大的顺序放在pp所指的数组中,这些因子的个数通过形参n返回(假设pp指向足够大的空间。

这道题可能你看起来有点绕,但是其实意思很简单,要你输出一个数所有的偶数因子,比如输入24输出应该是2,4,6,8,12,24。

你也不要被里面什么*pp,*n给吓到了,*pp其实是想让你传进去一个数组名,*n其实是想让你在函数里面改变参数,看一下代码你应该就懂了

个人代码如下:


#include <stdio.h>

void fun(int x, int pp[], int* n)
{
    int i;
    int j = 0;
    for (i = 2; i <= x; i += 2)//每次加2,不要再写一个偶数判断条件多此一举了
        if (x % i == 0) 
        {
            pp[j++] = i;
        }
    *n = j; //通过函数改变main里参数的值
}

int main()
{
//**题目没说pp多大,设大一点防止越界
    int x, pp[999], n;
    scanf("%d",&x);
    //数组名pp就是指针,直接传进去,n传进去要改变值就要传地址
    fun(x, pp, &n);
    for (int i = 0; i < n; i++) printf("%d ",pp[i]);
    printf("\n");
    return 0;
}

第二题

替换字符

编写替换字符的函数replace(char *str,char *fstr,char *rstr),将str所指字符串中凡是与fstr字符串相同的字符替换成rstr(rstr与fstr字符长度不一定相同);从主函数中输入原始字符串、查找字符串和替换字符串,调用函数得到结果。

tnnd真的是一点数据都不给,我一开始还以为是用户自己输入数据,结果你给我输入好了。

复习一下用到的两个函数strncpy,strlen.

strlen:获取字符串长度 不包括'\0'

strnpy:复制字符串,函数原型为char*strncpy(char*dest,char*src,size_tn);

三个参数分别为(指向用于存储复制内容的目标数组首地址,指向要复制的字符串的起点地址,复制长度)

比如下面这段代码就是把b接到a后面



int main() {
	char a[99] = "ass";
	char b[99] = "bbbbb";
	strncpy(a + 3, b, 5);
	printf("%s", a);

	return 0;
}

个人代码如下:

#include <stdio.h>
#include <string.h>//用到strlen strncpy

char *strreplace(char *str, char *fstr, char *rstr) {
	int fstr_len, rstr_len;
	//用指针方便操作字符串
	char *p, *p1, *q;
	//分别求得两个字符串长度
	fstr_len = strlen(fstr);
	rstr_len = strlen(rstr);
	for (p = str; *p != 0; p++) {
		//遍历字符串str ,如果发现有和rstr相同的,指针后移计数
		for (p1 = p, q = fstr; *p1 == *q && *q; p1++, q++);
		//如果*q不为空
		if (*q)
			continue;
		//如果两个字符串不一样长
		if (fstr_len != rstr_len) {
			//printf("%c\n", *p);
			//现在p指向的是字符'a'这步是给rstr让位置
			strncpy(p + rstr_len, p + fstr_len, strlen(p + fstr_len) + 1);
		}
		//如果一样长,忽略上一步
		strncpy(p, rstr, rstr_len);
		p += rstr_len;
	}

	return str;
}


int main() {

	char a[99] = "hi,i am a baby!";
	char b[99] = "am";
	char c[99] = "have";


	printf("%s", strreplace(a, b, c));

	return 0;
}

第三题

输入一个2×3的整数矩阵和一个3×4的整数矩阵,用指针数组实现这两个矩阵的相乘。

矩阵相乘,怎么个相乘法?核心公式是c[i][j] += a[i][k] * b[k][j]

题目要的输入是

1 2 3

4 5 6

1 2 3 4

5 6 7 8

9 10 11 12

要的输出是:

Results:

38 44 50 56

83 98 113 128

感觉考的是数学

不清楚矩阵运算的推荐这两篇文章http://t.csdn.cn/z7nDM

http://t.csdn.cn/m30rq

个人代码如下

#include <stdio.h>

const int M = 2;
const int N = 3;
const int K = 4;

int a[2][3], b[3][4], c[2][4];

int main() {
	int i, j, k;
	for (i = 0; i < M; i++) {
		for (j = 0; j < N; j++) {
			scanf("%d", &a[i][j]);
		}
	}
	for (i = 0; i < N; i++) {
		for (j = 0; j < K; j++) {
			scanf("%d", &b[i][j]);
		}
	}
	for (i = 0; i < M; i++) {
		for (j = 0; j < K; j++) {
			c[i][j] = 0;
			for (k = 0; k < N; k++)
//就这一条核心公式 其他都是常规循环输入输出
				c[i][j] += a[i][k] * b[k][j];
		}
	}
	printf("Results: \n");
	for (i = 0; i < M; i++) {
		for (j = 0; j < K; j++) {
			printf("%d ", c[i][j]);
		}
		printf("\n");
	}



	return 0;
}

第四题

判断一个数m是否是素数

判断一个数m是否是素数有一种更高效的方法,即不用判断2…m-1这个范围内是否有一个数能被m整除,而是判断2…这个范围内是否有一个数能被m整除,减少循环的次数。按照这个方法,改写例题6.8的程序。

送分题,之前都不知道写过多少次了

但是这道题的意思是不是要用循环次数更少,时间复杂度更低的方法?那也行

这就是数论的基础知识了,我们用试除法解决,其实就是这样而已


	for (int i = 2; i < n / i; i++)

我们把原来i<n换成i < n / i因为自己的因子总是小于自己开平方,这样就减少了循环次数

但是为什么是i < n / i而不是i*i<n或者i<sqrt(n)

这就是前人的智慧了,如果是i*i<n两数相乘数据一大就容易超出int 的最大范围

如果是i<sqrt(n)每次循环都要调用一次sqrt函数,浪费了太多时间

一个小小的试除法埋的细节可不少

个人代码:

#include <stdio.h>

int Prime(int n) {
	for (int i = 2; i < n / i; i++) {
		if (n % i == 0)
			return 0;
	}
	return 1;

}

int main() {
	int m;
	scanf("%d", &m);
//自己写一个prime函数判断比一个个循环套好多了
	if (Prime(m)) {
		printf("%d是一个素数。", m);
	} else

		printf("%d不是一个素数。", m);

	return 0;
}

第五题

将两个链表连接在一起

已知L1和L2分别指向两个单向链表的头结点,且已知其长度分别为m和n,试写一算法将两个链表连接在一起。

第一个链表是5 4 3 2 1,第二个链表是11 10 9 8 7 6。tnnd这个可爱的xie老师太忙了,数据都忘记给了,题目也不知道去哪里抄一半过来,每次都是这样,都已经麻木了,先写一遍错的上去拿数据

这道题链表过关了应该问题不打,注意接链表的时候不是头节点接上去,头节点是没有数据的,需要接头节点的下一个节点(首元节点)如果你对链表不是很熟悉,推荐一个生动形象的短视频

【动画演示】链表详解及其底层机制 C语言_哔哩哔哩_bilibili

个人代码如下:

#include <stdio.h>
#include <stdlib.h>//开动态内存用 c语言没有new函数

typedef struct node {
	int val;
	struct node *next;
} node, *List;

//打印链表
void print(List L) {
	L = L->next;
	while (L) {
		printf("%d ", L->val);
		L = L->next;
	}
	printf("\n");
}
//创建链表
List Creat(int n, int m) {
	List head = (List)malloc(sizeof(struct node));
	node *p = head, *q;
	int i;
	for (i = n; i > n - m; i--) {
		//动态开辟内存 因为是做题我后面没有用free释放
		q = (node *)malloc(sizeof(node));
		q->val = i;
		p->next = q;
		p = q;
	}
	p->next = NULL;
	return head;

}

//整合链表
List combine(List L1, List L2) {
	List head = L1;
	while (head->next)//不为空就一直后移
		head = head->next;
		//注意头结点没数据,所以要接L2的next指针
	head->next = L2->next;
	return L1;
}

int main() {
	List L1 = Creat(5, 5);
	List L2 = Creat(11, 6);
	print(combine(L1, L2));

	return 0;
}

第六题

剔除链表中的重复数据

有两个链表a和b,设结点中包含学号、姓名。从a链表中删去与b链表中有相同学号的那些结点。 链表a= {{101,"Wang"},{102,"Li"},{105,"Zhang"},{106,"Wei"}}; 链表b= {{103,"Zhang"},{104,"Ma"},{105,"Chen"},{107,"Guo"},{108,"lui"}};

上一次作业做的,不会那么快就忘了吧?

个人代码如下:

#include <stdio.h>
typedef struct student
{
	int num;
	char name[20];
	struct student *next;
} student;
student *del(student *a, student *b)
{
	student *pre, *current, *head;
	head = a;
 
	while (b != NULL)
	{
		//重置指针指向a链表的头部
		pre = head;
		current = head->next;
		//a 链表的头等于b
		if (pre->num == b->num)
		{
			pre->next = NULL;
			pre = current;
			current = current->next;
			//更新表头
			head = pre;
		}
		else
		{
			while (pre->next != NULL)
			{
				if (current->num == b->num)
				{
					//找到就删除
					pre->next = current->next;
					break;
				}
				else
				{
					//否则继续遍历
					pre = pre->next;
					current = current->next;
				}
			}
		}
		b = b->next;
	}
	return head;
}
 
void printList(student *root)
{
	
	while (root != NULL)
	{
		printf("%d %s\n", root->num, root->name);
		root = root->next;
 
	}
}
 
int main()
{
	student a[4] = { { 101, "Wang" }, { 102, "Li" }, { 105, "Zhang" } ,{ 106, "Wei" } };
	for (int i = 0; i < 3; i++)
	{
		a[i].next = &a[i + 1];
	}
	a[3].next = NULL;
	printf("list A:\n");
	printList(&a[0]);
 
	student b[5] = { { 103, "Zhang" }, { 104, "Ma" }, { 105, "Chen" } , { 107, "Guo" }, { 108, "lui" }};
	for (int i = 0; i < 4; i++)
	{
		b[i].next = &b[i + 1];
	}
	b[4].next = NULL;
	printf("list B:\n");
	printList(&b[0]);
	student *combine = del(a, b);
	printf("result:\n");
	while (combine != NULL)
	{
		printf("%d %s\n", combine->num, combine->name);
		combine = combine->next;
	}
 
	return 0;
}

第七题

将数字按序插入数组

有10-90这9个整数,已按升序存放于长度为10的一维数组中。要求将一整数35插入其中,并保持数组元素仍然有序。

也是之前作业做的,考的就是一个malloc+一个排序

个人代码如下:

#include <stdio.h>
 
 
int main() {
	int i, temp;
	int* s;
 
	//分配动态空间
	s = (int*)malloc(sizeof(int[10]));//s就是我们定义的int类型的动态数组了
 
 
	//初始化10-90
	for (i = 0; i < 9; i++) {
		s[i] = (i + 1) * 10;
	}
 
	//排序
	s[9] = 35;
	for (i = 9; i >= 0; i--) {
		if (s[i] < s[i-1]) {//老一套的选择排序
			temp = s[i];
			s[i] = s[i - 1];
			s[i - 1] = temp;
		}
	}
	for (i = 0; i < 10; i++) {
		printf("%d ", s[i]);
	}
 
	//释放内存
	free(s);//这个是个习惯 虽然做题不释放也可能对 但以后去工作一定会给打死
	return 0;
}

第八题

用递归法求n!

又是递归,递归,简单点说就是函数自己调用自己,这个知识还是蛮重要的,很多算法的模板都会用到,这里的话只是一个最最最简单的递归,递归要想好两件事,一个是终止条件,一个是递归条件。如果对递归函数出入口不是很清楚的可以在vs上分步调试或者自己拿草稿纸演算一遍

个人代码如下:

#include <stdio.h>

int  dfs(int n) {
//终止条件
	if (n == 0)
		return 0;
	if (n == 1)
		return 1;
//递归条件
	if (n > 1)
		return n * dfs(n - 1);
}

int main() {
	int n;
	scanf("%d", &n);

	printf("%d", dfs(n));

	return 0;
}

第九题 

求两个整数的最大公约数和最小公倍数

写2个函数,分别求两个整数的最大公约数和最小公倍数,用主函数调用这两个函数,并输出结果。两个整数由键盘输入。

很早之前就写过的题目,求最小公约数就用辗转相除法(欧几里得算法)最快,如果都期末了还不会辗转相除。。。那就循环暴力解出来吧,最小公倍数就是两数相乘除以最小公倍数

个人代码如下:

# include <stdio.h>
 
int main()
{
	int m;//数学原理转化成程序 欧几里得算法 
	int n;
	scanf("%d %d",&m,&n);
	int i;
		if(m<n) {
	i=m;m=n;n=i;}//这是防止除数大于被除数 进行交换 
	int t1 ,t2;
	t1=m;t2=n;
	int r=m%n;
 
	 if(m>=n){
	
	while(r!=0){
		r=m%n;
	m = n;
	n = r;
	r = m%n;
		
		
	}
	printf("hcf=%d\nlcd=%d",n,t1*t2/n);
}else{
	printf("程序错误");
	
}
 
	return 0;
}

第十题

简单计算器程序

编写一个简单计算器程序,输入格式为:data1 op data2。其中data1和data2是参加运算的两个数,op为运算符,它的取值只能是+、-、*、/。。要求必须使用switch-case语句实现。

输出结果精确到小数点后2位:如输入1+1, 程序应该返回结果0.00。

我知道你出题水,但是这明明是个简单题你标注困难干啥子,困难题你又标注简单,从网上趴下来的时候忘记改了吗?

这个水题之前写过,我直接搬我之前写的代码了

个人代码如下:

# include <stdio.h>
 
int main()
{
	double a1,a2;
	char op;
	scanf("%lf %c %lf",&a1,&op,&a2);
	if(op=='+')printf("%.2lf",a1+a2);
	else if(op=='-')printf("%.2lf",a1-a2);
	else if(op=='*')printf("%.2lf",a1*a2);
	else printf("%.2lf",a1/a2);
		
	return 0;
}

swich写法:

#include  "stdio.h"
int main()
{	
  double a1,a2;
  char op;
scanf("%lf%c%lf",&a1,&op,&a2);
    switch(op){
        case '+':printf("%lf",a1+a2);break;
        case '-':printf("%lf",a1-a2);break;
        case '*':printf("%lf",a1*a2);break;
        case '/':
        	if (a2!=0) printf("%lf",a1/a2);
         else printf("input error");
        break;
default:printf("input error");
    }
     return 0;
}

放假回家了,老师也知道同学们不想写作业,特地把这个作业截止日期设置了长达一个月,太贴心了,要是以后出题能更用心点就更好了,这也是今年最后一次作业了,或者说C语言最后一次作业了?

感觉上学时间没有放假时间长,算了,反正我这种打代码的废宅也体会不到什么大学生活

❀祝各位期末考试必不挂科❀

 

  • 8
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mr丶锤子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值