本文主要是介绍西北农林科技大学2023级C语言期末考试题解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
Readme
本题解只提供了题目和题解代码,未提供讲解,后续会跟新B站视频详细讲解,大家可以关注等候。
B站:沐晨汐er_
链接:沐晨汐er_的个人空间-沐晨汐er_个人主页-哔哩哔哩视频 (bilibili.com)
A题 WA了20多发哈哈哈哈
题目
E
题目描述
现有n×n的棋盘,棋盘上每个格子只能放入黑白两种棋子中的一个,分别用字符'+'表示黑色棋子、'*'表示白色棋子、'0'表示未着子。
编写Judge函数,Judge函数原型如下:
int Judge(char **str, int n, char ch, struct solu *ps);
其中,形参str是指向棋盘的指针,形参n表示棋盘大小(n×n),形参ch('+'、'*'分别表示黑白棋子)表示棋子颜色,形参ps是指向保存连珠方法的结构体变量。
通过调用Judge函数,判断落子布局是否可以组成五子连珠,若可以则返回1,并将找到的第一个连珠方法保存在ps指向的结构体变量中;否则返回0。struct solu结构体的定义如下:
struct solu{int x;int y;char direction;
};
其中,用x和y分别表示字符ch表示的棋子组成的第一个五子连珠的起始行号和起始列号(行号和列号均从0开始),用direction保存五子连珠的四种方向,可以在四种符号:'-','|','\','/'中取值,分别表示以x和y为起点,向右横向、向下竖向、向右下斜向、向左下斜向构成了五子连珠。
五子连珠寻找的优先级规则为:行优先(即先判断第0行的所有位置,然后是第1行、第2行……依次类推),方向优先级判断顺序为:向右横向、向下竖向、向右下斜向、向左下斜向。
输入:
+ 20
0+0++*0+*+++000++0++
0+00+0+*0+*00*00***0
+0+0000+++*0+**+*0**
+**+0++*0*+0**0*0**0
*00*++0*0*++00*+00*0
*+*0*++*00*+0+0+**+0
+*+++0+0000+0***+**+
00*0+*0**+*0*000**++
*+**000+0+***++**+++
*00+*+*+00++0***0*0*
+*0**++0++*0+****00*
*+**+++0++++*0000+++
+*+000*0**++*+**+0**
+*0****+000*++++0*0*
+**0*+*00+000*0**+0+
0**+**+***0*+**00+*0
*+0++***0000+*+++0**
+0**+0+++*+0++**+000
**++++**00++00*++0*+
00*000+00++00+0+*+00
说明:分别用字符'+'、'*'、'0'代表黑子、白子、未着子,第一行输入"+ 20"表示在20×20的棋盘上对黑子是否能够组成五子连珠进行判断。
输出:
1 1 \
说明:该结果表明第1行,第1列,有一个由'+'组成的向右下斜向的五子连珠方案,是满足条件的第一个解
代码
// E.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>struct solu
{int x;int y;char direction;
};int Judge(char **str, int n, char ch, struct solu *ps){char t = '\0';for (int i = 0; i < n; i++){for (int j = 0; j < n; j++){if (str[i][j] == ch){if (j <= n-5 && str[i][j+1]==ch && str[i][j+2]==ch &&str[i][j+3]==ch && str[i][j+4]==ch){t = '-'; }else if (i <= n-5 && str[i+1][j]==ch && str[i+2][j]==ch &&str[i+3][j]==ch && str[i+4][j]==ch){t = '|'; }else if (i <= n-5 && j <= n-5 && str[i+1][j+1]==ch && str[i+2][j+2]==ch &&str[i+3][j+3]==ch && str[i+4][j+4]==ch){t = '\\'; }else if (i <= n-5 && j >= 4 && str[i+1][j-1]==ch && str[i+2][j-2]==ch &&str[i+3][j-3]==ch && str[i+4][j-4]==ch){t = '/'; }}if (t != '\0'){ps->x = i;ps->y = j;ps->direction = t;return 1;}}}return 0;
}int main()
{int n, i;char ch;struct solu s = {-1, -1, ' '};scanf("%c%d", &ch, &n);char *board[n];for(i = 0; i < n; i++){board[i] = (char *)malloc((n+1)*sizeof(char));memset(board[i], 0, (n+1)*sizeof(char));scanf("%s", board[i]);}if (Judge(board, n, ch, &s) == 1)printf("%d %d %c\n", s.x, s.y, s.direction);elseprintf("0\n");for(i = 0; i < n; i++){free(board[i]);}return 0;
}
D
题目描述
给定一个有m个元素(m<50)的正整数整型数组nums和一个正整数k(0<k<20),现需要向nums数组中追加填充k个最小的未出现在数组nums中且互不相同的正整数,要求使填充后数组的各元素的累加和最小。请编写函数MinInsert()返回填充到nums中的k个整数之和。
函数原型:int MinInsert(int *pnums, int m, int k);
其中,形参pnums是指向nums整型数组的指针,形参m是数组元素的个数,形参k是要填充的正整数个数。
函数算法请参考下面的流程图。
注意:不能改变指定函数原型,仅需提交MinInsert()函数及其调用的自定义函数的实现代码。
示例 1:
输入:nums = {1,4,25,10,25}, k = 2
输出:5
解释:向数组中填充的两个互不相同且未出现的正整数是 2 和 3 。nums 最终元素和为 1 + 4 + 25 + 10 + 25 + 2 + 3 = 70 ,这是所有情况中的最小值。
所以填充到数组中的两个整数之和是 2 + 3 = 5 ,所以返回 5 。示例 2:
输入:nums = {5,6}, k = 6
输出:25
解释:向数组中填充的六个互不相同且未出现的正整数是 1 、2 、3 、4 、7 和 8 。nums 最终元素和为 5 + 6 + 1 + 2 + 3 + 4 + 7 + 8 = 36 ,这是所有情况中的最小值。
所以填充到数组中的六个整数之和是 1 + 2 + 3 + 4 + 7 + 8 = 25 ,所以返回 25 。
请参考下面的流程图编写代码。其中,gap是数组中的间隙。要循环判定数组的间隙大小,当间隙gap大于待填数量k时,依次填入整数;否则依次填满间隙,再调整待填数量k。最后如未达到要求的待填数量,则继续在尾部填充。
代码
// D.
#include <stdio.h>int MinInsert(int *pnums, int m, int k){int *t = pnums;for (int i = 0; i < m; i++){for (int j = 0; j < m; j++){if (t[j] > t[i]){int x = t[i];t[i] = t[j];t[j] = x;}} }int sum = 0, cnt = 0;for (int i = 0; i < m; i++){if (i == 0){int cha = t[i] - 0;if (cha > 1){for (int j = 1; j < t[i]; j++){sum += j;cnt++;if (cnt == k) return sum; }}}else{int cha = t[i] - t[i-1];if (cha > 1){for (int j = t[i-1]+1; j < t[i]; j++){sum += j;cnt++;if (cnt == k) return sum; }}}}if (cnt < k){ int x = t[m-1]+1;while (cnt != k){sum += x;x++;cnt++;}}return sum;
}int a[N] = {5,8,13};
void solve() {cout << MinInsert(a,3,15) << endl;
}signed main() {int t = 1;while(t--) {solve();}return 0;
}
C
题目描述
假定有下面的结构体:
typedef struct {unsigned int year; /* 有效年份 1900~2050 年*/unsigned int month;unsigned int day;
} Date, *PDate;
请实现下面的两个函数,其原型要求如下:
int ToDate(char *str, PDate pd);
int DaysCount(PDate sdate, PDate edate);
ToDate()函数将字符串str中的合法日期存入指针变量pd指向的结构体成员中,其中字符串str的基本形式为“YYYY-MM-DD”,YYYY代表年,MM代表月,DD代表日,如str为“2023-12-30”,则ToDate()函数的功能是将2023、12、30分别存入pd->year、pd->month、pd->day中。如果str中的日期数值范围或数据格式非法,函数返回-1,正常返回0。
DaysCount()函数计算两个日期sdate和edate之间差距是多少天,并返回计算结果。
输入:
2008-08-08
2023-12-30
输出:
5622
可以使用sscanf函数从字符串str中将年月日读取为整数,例如,sscanf(str, "%d-%d-%d", &year, &month, &day)。
另外,提供以下日期计算结果,供程序测试使用。
- 1949年10月01日开国大典,至今(2023年12月30日)已过27118天。
- 1950年10月25日抗美援朝,至今(2023年12月30日)已过26729天。
- 今天是2023年12月30日,距离西北农林科技大学90周年校庆(2024年09月10日),还有255天。
- 2023年09月11日开学,至今(2023年12月30日)已过110天。
代码
// C.
#include <stdio.h>
#include <stdlib.h>typedef struct {unsigned int year;unsigned int month;unsigned int day;
} Date, *PDate;int is_leap(int);
int month_days(int ,int);int ToDate(char *str, PDate pd){ int year,month,day;if ((sscanf(str, "%d-%d-%d", &year, &month, &day)) == 3){if (year >= 1900 && year <= 2050 && month >= 1 && month <= 12 && day >= 1 && day <= 31){pd->day = day;pd->month = month;pd->year = year;return 0;}return -1;}return -1;
}
int DaysCount(PDate sdate, PDate edate){int res = 0;// 开始那年 int flag = is_leap(sdate->year);res += month_days(sdate->month,flag) - sdate->day;for (int i = sdate->month+1; i <= 12; i++){res += month_days(i,flag);}// 后面的每一年 for (int i = sdate->year+1; i <= edate->year; i++){res += is_leap(i) ? 366 : 365;}// 减去多加的flag = is_leap(edate->year);res -= month_days(edate->month,flag) - edate->day;for (int i = edate->month+1; i<= 12; i++){res -= month_days(i,flag);} return res;
}int main()
{char str1[12], str2[12];Date sd, ed;fgets(str1, 12, stdin);fgets(str2, 12, stdin);if (ToDate(str1, &sd) == 0 && ToDate(str2, &ed) == 0)printf("%d\n", DaysCount(&sd, &ed));elseprintf("input data is invalid.\n");return 0;
}int is_leap(int year)
{return ((year%4==0&&year%100!=0)||year%400==0);
}int month_days(int month, int leap)
{int m_days[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};if(month == 2)return (leap == 1) ? 29 : 28;elsereturn m_days[month];
}
B(?)
疑问
不懂为什么排序的算法,冒泡排序(稳定性算法)过85%,选择排序1.0过92%,最基础的选择排序2.0AC了。有大佬可以解释一下吗??
题目描述
从二进制文件“stud.dic”中读取指定范围内的学生数据,并使用结构体、文件操作、函数指针等实现对各科成绩的升、降序通用化排序。程序主体框架已完成,请仔细阅读已有代码,并完成下面的两个函数:
1.通用排序
函数原型为:void sort(stu *stud, int mode, int sub, int n);
其中,形参sub用于指定需要排序的科目,取值为0、1或2代表的科目编号,形参mode用于指定排序模式,1表示升序,2表示降序,从而实现对形参n指定的n个学生成绩进行排序,形参stud是需要参与排序学生的数组首地址指针。
2.从二进制文件读入指定数据
函数原型为:stu *read( FILE *fp, int m, int n);
其中,形参fp传入的是已打开二进制文件的文件指针,形参m用于指定范围的起始位置(从0开始编号), 形参n用于指定需要读取的学生数据个数。在函数内部,用动态内存分配存储空间,读入指定的数据到分配的空间后,返回其首地址。
注意:
- 在程序主体框架中,已给出了结构体、主函数、辅助函数类型定义以及所需要完成的函数原型。
- 不能改变程序主体框架和指定函数原型,仅需提交sort()和read()函数及其调用的自定义函数的实现代码。
- 在二进制文件中,学生信息最多为30条,且姓名中可能会有空格,如:“白 莹”,成绩中可能含有小数。
输入:
起始学生序号m,学生数量n,排序方式mode,排序科目编号sub
0 3 1 0
输出:
从第m个开始的n个学生信息,并以mode方式对科目sub排序
0th: 2009011360 卢 莹 13.27 85.45 26.72
1th: 2010036201 张 阳 87.10 54.00 63.90
2th: 2010036209 赵扶强 90.50 54.00 65.00
代码
// B.
#include <stdio.h>
#include <stdlib.h>#define M 30typedef struct STUDENT
{int studentID;char studentName[10];float score[3];
} stu, *pstu;
typedef int (*CmpFunPtr)(float, float); /* 定义函数指针类型CmpFunPtr,该类型的指针指向的函数应该返回一个整型数据,且含有两个float型形参。 */int compareA(float, float); /* 降序排序比较函数 */
int compareD(float, float); /* 升序排序比较函数 */
stu *read(FILE *fp, int m, int n);
void sort(stu *stud, int mode, int sub, int n);
void print(pstu stud, int n);
CmpFunPtr setmode(int mode); /* 返回一个CmpFunPtr类型的函数指针 */int main()
{struct STUDENT *stud;FILE *fp;int m, n, mode, sub;scanf("%d%d%d%d",&m, &n, &mode, &sub);if(m < 0 || m > M || n < 0 || n+m > M || (mode != 1 && mode != 2) || (sub != 0 && sub !=1 && sub != 2)){printf("error!\n");exit(0);}fp = fopen("stud.dic", "rb");if(fp == NULL )exit(0);stud=read(fp, m, n);sort(stud, mode, sub, n);print(stud, n);free(stud);fclose(fp);return 0;
}CmpFunPtr setmode(int mode)
{if (mode == 1)return compareD;elsereturn compareA;
}
void print(pstu stud, int n)
{int i;for(i = 0; i < n; i++){printf("%dth: %d %s %.2f %.2f %.2f\n", i, stud[i].studentID,stud[i].studentName, stud[i].score[0], stud[i].score[1], stud[i].score[2]);}
}int compareA(float x, float y)
{return x > y;
}
int compareD(float x, float y)
{return x < y;
}
stu *read(FILE *fp, int m, int n)
{stu *stud = (stu *)malloc(n * sizeof(stu));if (stud == NULL){exit(1);}fseek(fp, m * sizeof(stu), SEEK_SET);fread(stud, sizeof(stu), n, fp);return stud;
}void sort(stu *stud, int mode, int sub, int n){// 选择排序、快速排序、希尔排序、堆排序不是稳定的排序算法。// 冒泡排序、插入排序、归并排序、基数排序是稳定的排序算法。// //冒泡
// for (int i = 0; i < n; i++){
// for (int j = 0; j < n-1; j++){
// if (mode == 1){ // 升序
// if (stud[j].score[sub] > stud[j+1].score[sub]){
// stu temp = stud[j];
// stud[j] = stud[j+1];
// stud[j+1] = temp;
// }
// }else{ // 降序
// if (stud[j].score[sub] < stud[j+1].score[sub]){
// stu temp = stud[j];
// stud[j] = stud[j+1];
// stud[j+1] = temp;
// }
// }
// }
// }// 选择 1.0for (int i = 0; i < n - 1; i++){for (int j = i+1; j < n; j++){if (mode == 1){ // 升序 if (stud[j].score[sub] < stud[i].score[sub]){ // 比该位置小就换 stu temp = stud[i];stud[i] = stud[j];stud[j] = temp;} }else{ // 降序 if (stud[j].score[sub] > stud[i].score[sub]){stu temp = stud[i];stud[i] = stud[j];stud[j] = temp;} }}}
// // 选择 2.0
// for (int i = 0; i < n - 1; i++){
// int idx = i;
// for (int j = i+1; j < n; j++){
// if (mode == 1){ // 升序
// if (stud[j].score[sub] < stud[idx].score[sub]){
// idx = j;
// }
// }else{ // 降序
// if (stud[j].score[sub] > stud[idx].score[sub]){
// idx = j;
// }
// }
// }
// stu temp = stud[i];
// stud[i] = stud[idx];
// stud[idx] = temp;
// }
}
A(过 90%)
疑问
不懂,说我越界了,求大佬指点,wa了20多发。。。。。。。。
题目描述
“行程长度编码(Run-Length Encoding,RLE)”是一种无损压缩编码方法,其核心思想是依次记录符号序列中的每个字符(忽略大小写)及其重复出现的次数。例如用户输入字符序列(字符串)AaABBBbCBB,则其RLE编码的结果为3A4B1C2B。
下面的代码实现对输入字符串的RLE编码,现要求在函数int rle(char *code, const char *seq);及 函数readSeq(char *seq, int n);定义中的五个空白处填充适当的表达式,完成程序功能。
其中:rle()函数形参seq为长度在(0, 80]间(strlen(seq)>0&&strlen(seq)≤80)的全部由大小写英文字母组成的字符串指针,形参code为RLE编码后的结果字符串指针。编码正常结束函数返回0;如字符串指针seq为空或字符串长度不合法时,不进行编码函数直接返回-1;当字符串seq中出现非英文字母的其他字符时,也不进行编码函数直接返回-2。
readSeq()从键盘读取最多n个字符到seq字符串中,以回车符或EOF字符为结束标志。
输入1:
KAAAEE
输出1:
1K3A2E
输入2:
aaaaaaaaaabbbbbbbbbbaaaaaaaaaabbbbbbbbbbaaaaaaaaaabbbbbbbbbbaaaaaaaaaabbbbbbbbbb
输出2:
10A10B10A10B10A10B10A10B
输入3:
abcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefab
输出3:
1A1B1C1D1E1F1A1B1C1D1E1F1A1B1C1D1E1F1A1B1C1D1E1F1A1B1C1D1E1F1A1B1C1D1E1F1A1B1C1D1E1F1A1B1C1D1E1F1A1B1C1D1E1F1A1B1C1D1E1F1A1B1C1D1E1F1A1B1C1D1E1F1A1B1C1D1E1F1A1B
代码
// A.
#include <stdio.h>
#include <string.h>#define MAX_SEQ_LEN 80int rle(char *code, const char *seq);
int readSeq(char *seq, int n);int main()
{char seq[MAX_SEQ_LEN + 1] = { 0 };char code[2 * MAX_SEQ_LEN + 1];int r;readSeq(seq, MAX_SEQ_LEN);r = rle(code, seq);switch (r) {case 0:printf("%s\n", code);break;case -1:printf("Length is inValid.\n");break;case -2:printf("Has inValid character.\n");break;}return 0;
}/* 以上代码禁止提交 */
int readSeq(char *seq, int n)
{int ch, k;k = 0;while ((ch = getchar())) {if (ch == '\n' || ch == EOF || k == n) break; // if (__________(1)_________)seq[k++] = ch;}seq[k] = '\0'; // _____(2)______;return k;
}int rle(char *code, const char *seq)
{int i, len = 0;if (strlen(seq) <= 0 || strlen(seq) > 80) return -1; // if (________(3)_______)const char *p = seq; // p = seq;
// char *ptr = code;// while (*p != '\0' && strlen(code) < strlen(seq)*2-1) while (*p) { // while (____(4)____)char token = *p;i = 1;token &= 0xDF;if (token > 'Z' || token < 'A')return -2;while ((*(++p) == token || *(p) == token+32) && *p != '\0'){ // while (___(5)___)i++;}
// while (1){
// p++;
// if (*p == '\0') break;
// if (*p != token && *p != token+32) break;
// i++;
// }len = sprintf(code, "%d%c", i, token);code += len;}*code = '\0';
// code = ptr;return 0;
}// aaaaaaaaaabbbbbbbbbbaaaaaaaaaabbbbbbbbbbaaaaaaaaaabbbbbbbbbbaaaaaaaaaabbbbbbbbbb
// abcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefab
这篇关于西北农林科技大学2023级C语言期末考试题解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!