某不知名学校(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
个人代码如下:
#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语言最后一次作业了?
感觉上学时间没有放假时间长,算了,反正我这种打代码的废宅也体会不到什么大学生活
❀祝各位期末考试必不挂科❀