页数:55页文件大小:893.8 KB来源: C语言程序设计ppt课件
本课件集中讲解课程各次上机作业与习题,先说明动态内存分配malloc与free的用法和编程常见问题,再逐题给出第一次到第六次上机作业的参考答案,内容包括日历显示、十六进制转十进制、矩阵运算、数组转置、学生信息处理、字符串反转与删除、数据移位、字符串排序、矩阵乘法、成绩统计与文件存取等典型题目。
作业习题讲解:本课件集中讲解课程各次上机作业与典型习题,覆盖动态内存分配、日历显示、十六进制转换、矩阵运算、数组转置、学生信息处理、字符串处理、数据移位、字符串排序、矩阵乘法、成绩统计与文件存取等内容,逐题给出思路与参考代码。
申请内存函数 malloc
void *malloc(unsigned size)int *p; p = (int *)malloc(10 * sizeof(int)); 释放内存函数 free:void free(void *p); 释放 p 所指的内存空间,无返回值。p 所指的内存区域必须是用 malloc 申请的,否则调用时可能会破坏系统。
void main() { int n, *p; scanf("%d", &n); p = (int *)malloc(n * sizeof(int)); printf("\nResult:"); assign(p, 10); free(p); }assign 函数中 a[k] = k*10 赋值后再逐个输出。
scanf("%d%d", time1, time2);、scanf("%.2f", &t);、scanf("%f\n", &t);、double number; scanf("%f", &number); 均属错误写法scanf("%d", &number); 或 scanf("%1d%1d%1d%1d", &a, &b, &c, &d);,或 digit1=number/1000; digit2=number%1000/100;c = 5.0/9*(f-32); 与整数除法的区别double sqrt(double);第一次上机作业
if (c >= 'A' && c <= 'Z'),'a' == 'A'+32,用 getchar()、putchar()scanf("%f", &x)、%.2fc = 5.0/9*(f-32);第二次上机作业
t=a; a=b; b=t;for(s=0,i=1;i<=n;i++){ for(t=1,j=1;j<=i;j++) t*=j; s+=1/t; }scanf("%d%c%d", &a, &op, &b);,case '+'、'-'、'*'、'/'、'%' 分别运算void main() { while (1) { printf("Would you like to continue?(y/n)"); fflush(stdin); ch = getchar(); if (ch == 'N' || ch == 'n') break; } }2_5.c Calendar Display:循环输入月份并显示该月日历,询问是否继续。
int dayinmonth[12] = {31,28,31,30,31,30,31,31,30,31,30,31}; days = 0; for (i = 0; i < month-1; i++) days += dayinmonth[i]; int fday = 2; fday = (days + fday) % 7; printf("*********************************************************\n"); printf(" SUN MON TUE WED THU FRI SAT\n"); for (i = 0; i < fday; i++) printf(" "); for (i = 1; i <= dayinmonth[month-1]; i++) if ((i+fday) % 7 == 0) printf("%7d\n", i); else printf("%7d", i); printf("\n");第三次上机作业
char str[N][MAXLEN]; 双重循环逐个判断字符是否为大写且非 A、E、I、O、U 后计数for (i = 0, count = 0; i < N; i++) { gets(str[i]); for (j = 0; str[i][j] != '\0'; j++) if (str[i][j] >= 'A' && str[i][j] <= 'Z' && str[i][j] != 'A' && str[i][j] != 'E' && str[i][j] != 'O' && str[i][j] != 'I' && str[i][j] != 'U') count++; }3.5 String connection:str1 为 "welcome to",str2 为 "china",先用 i 走到 str1 末尾,再把 str2 逐个字符复制到其后。
gets(str1); gets(str2); for (i = 0; str1[i] != '\0'; i++); for (j = 0; str2[j] != '\0';) str1[i++] = str2[j++]; str1[i] = '\0'; puts(str1);3.3 Statistics:输出 NO、MT、EN、PH、SUM、AVE、>90 七列。
| NO | MT | EN | PH | SUM | AVE | >90 |
|---|---|---|---|---|---|---|
| 1 | 97 | 87 | 92 | 276 | 92 | N |
| 2 | 92 | 91 | 90 | 273 | 91 | Y |
| 3 | 90 | 81 | 82 | 253 | 84 | N |
#define N 30 #define M 3 int s[N][M+4]; s[i][M+1] += s[i][j]; if (s[i][j] >= 90) count++; s[i][M+2] = s[i][M+1] / M; if (count >= M) s[i][M+3] = 'Y'; else s[i][M+3] = 'N';输入串 P、f、4、+、1 中,P 与 + 不是十六进制字符被滤去,剩下的 f、4、1 组成新串 num = "f41",再转换为十进制。
3_6.c 十六进制转换十进制:输入字符串含 P、f、4、+、1,先过滤掉不是十六进制数字的字符,得到有效串 "f41"。
void Converse(char str[]) { int i, k; for (i = 0, k = 0; str[i] != '\0'; i++) if (str[i] >= '0' && str[i] <= '9' || str[i] >= 'A' && str[i] <= 'F' || str[i] >= 'a' && str[i] <= 'f') { str[k] = str[i]; k++; } str[k] = '\0'; }过滤函数 Converse 保留 '0'~'9'、'A'~'F'、'a'~'f' 范围内的字符,其余字符(如 P、+)跳过,最后在新位置写入 '0',使原串压缩为合法十六进制串。
for (number = 0, i = 0; num[i] != '\0'; i++) { if (num[i] >= 'A' && num[i] <= 'F') k = num[i] - 'A' + 10; else if (num[i] >= 'a' && num[i] <= 'f') k = num[i] - 'a' + 10; else if (num[i] >= '0' && num[i] <= '9') k = num[i] - '0'; number = number * 16 + k; }3.7 矩阵运算:只累加不在最后一行、不在最后一列、不在副对角线上的元素。
sum = 0; for (i = 0; i < n; i++) for (j = 0; j < n; j++) if (i == n-1 || j == n-1 || i+j == n-1) continue; else sum += a[i][j];第四次上机作业 4_1.c 数组转置:
int a[N][N]; printf("Input n(n<=6):"); scanf("%d", &n); printf("Input the array:\n"); for (i = 0; i < n; i++) for (j = 0; j < n; j++) scanf("%d", &a[i][j]); printf("Display the array:\n"); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) printf("%-4d", a[i][j]); printf("\n"); } transpose(a, n);形参可写 void transpose(int a[N][N], int n); 或 void transpose(int (*a)[N], int n);
for (i = 0; i < n; i++) for (j = 0; j < n; j++) { t = a[i][j]; a[i][j] = a[j][i]; a[j][i] = t; }i=0 时逐列交换,矩阵中出现 1、5、9、13、2、3、4 的变化。注意这种写法把每个元素交换了两次,结果与原矩阵相同。
第二轮 i=1:矩阵继续变化,出现 5、2、2、5 等数值,说明逐个交换会重复还原,不能得到正确转置结果。
第三轮 i=2:矩阵中出现 5、2、2、5、3、9、7、10、11、12、15 等数值,交换结果仍被反复还原。
第四轮 i=3:最终矩阵中出现 4、13、14、8、15、12、16,因每个元素被交换两次,矩阵与初始状态相同。
for (i = 0; i < n; i++) for (j = 0; j < i; j++) { t = a[i][j]; a[i][j] = a[j][i]; a[j][i] = t; }只遍历下三角(j<i),每个元素对交换一次,才是正确的转置写法。图示 i=0 时不发生交换。
i=1 时 j=0,交换 a[1][0] 与 a[0][1],矩阵中出现 5、2。
i=2 时 j 取 0、1,分别交换对应元素,矩阵中出现 5、9、2、3、10、7。
i=3 时 j 取 0、1、2,交换三对元素,矩阵最终为 5、9、13、2、3、4、10、7、14、8、15、12,完成转置。
void sort(char name[][LEN], float s[]) { int i, j, k; float t; char string[LEN]; for (i = 0; i < N-1; i++) { k = i; for (j = i+1; j < N; j++) if (s[j] > s[k]) k = j; if (k != i) { t = s[i]; s[i] = s[k]; s[k] = t; strcpy(string, name[i]); strcpy(name[i], name[k]); strcpy(name[k], string); } } }4.2 学生信息由 input()、sort()、display()、search() 四个函数组成,main 中依次输入、显示、排序、再显示,并按姓名查找成绩。
4_3.c 字符串处理 SAMPLE OUTPUT:菜单 1.Reverse a string. 2.Delete a character in a string.
选择 1 输入 holiday,输出 Reversed string is:yadiloh;选择 2 输入 one world, one dream 并输入字符 o,输出 Deleted string is:ne wrld, ne dream。
while (1) { printf("1.Reverse a string.\n"); printf("2.Delete a character in a string.\n"); printf("Please input your choice:"); scanf("%d", &choice1); switch (choice1) { ... } printf("Would you like to continue?(y/n)"); fflush(stdin); choice2 = getchar(); if (choice2 == 'N' || choice2 == 'n') break; }Algorithm:i 指向字符串末尾,j 从 0 开始,while j < i 时交换对应字符,然后 j++、i--。
for (i = 0; str[i] != '\0'; i++); i--; for (j = 0; j < i; j++, i--) { c = str[i]; str[i] = str[j]; str[j] = c; }也可用 i = strlen(str); i--;,函数声明为 void strreverse(char s[]);
Delete a character in a string:原串 one world, one dream,c='o',用下标 i 逐个扫描、j 逐个写入,遇 o 则跳过,得到 ne wrld, ne dream。
void delchar(char s[], char c);扫描到一个 o 时,i 前进一位而 j 不动,该字符不被写入,其余字符继续复制到新位置。
继续扫描直到字符串结束,用 k 记录写入位置,最后写入 '0',得到 newrld, ne dream 形式的结果串。
4.4 分别用函数和带参数的宏,从三个数中找出最大数。
#define MAX(a,b,c) ((a)>(b)?(a):(b))>c?((a)>(b)?(a):(b)):c void main() { int a, b, c; printf("Input 3 integers:\n"); scanf("%d%d%d", &a, &b, &c); printf("Max of %d,%d,%d is %d\n", a, b, c, MAX(a,b,c)); }5_1.c 数据移位(第五次上机作业):有 n(n<=10)个整数,使前面各数顺序向后移 m(m<=n)个位置,最后 m 个数变成最前面的 m 个数。编写函数 shift(a, n, m) 实现上述功能,在主函数中输入 n 个整数和输出调整后的 n 个数。
示意图:数组共 n 个元素,后 m 个元素将整体移到数组最前面,n 与 m 的取值决定移动的范围。
移位过程:每轮把最后一个元素取出,其余元素从后往前依次后移一位,再把取出的元素放到首位。
移位第二轮:继续把当前最后一个元素取出并放到前面,数组中已有两个元素完成移位。
移位第三轮:三个元素完成移位,前段元素继续顺序后移。
移位第四轮:移位过程推进,数组前部已被末尾元素占据。
#include <stdio.h> #include <stdlib.h> void shift(int a[], int n, int m); void main() { int i, n, m; int *a; printf("Input n(n<=10):"); scanf("%d", &n); a = (int *)malloc(n * sizeof(int)); for (i = 0; i < n; i++) scanf("%d", a+i); printf("Input m(m<=%d):", n); scanf("%d", &m); shift(a, n, m); for (i = 0; i < n; i++) printf("%d ", *(a+i)); } void shift(int a[], int n, int m) { int i, j, t; for (i = 0; i < m; i++) { t = a[n-1]; for (j = n-2; j >= 0; j--) a[j+1] = a[j]; a[0] = t; } }5_2.c 字符串排序:在主函数中输入 10 个不等长的字符串放入二维字符数组中,编写函数 sort() 利用指针数组对其排序,在主函数中输出排好序的字符串。
#define N 10 #define M 80 char s[N][M], *strp[N]; for (i = 0; i < N; i++) gets(s[i]); for (i = 0; i < N; i++) strp[i] = s[i]; sort(strp); for (i = 0; i < N; i++) puts(strp[i]);sort 中用选择法比较 strcmp 结果,交换的是指针值而不是字符串内容。
| 对比项 | char a[5][9] | char *a[5] |
|---|---|---|
| 存储方式 | 每行固定 9 字节,连续存放 | 每个元素是指针,指向的字符串长度可变 |
| 内存开销 | 固定,可能浪费 | 按需分配,节省空间 |
| 排序开销 | 交换需移动整行字符 | 只交换指针,效率高 |
char **strp; scanf("%d", &n); strp = (char **)malloc(n * sizeof(char *)); for (i = 0; i < n; i++) strp[i] = (char *)malloc(M * sizeof(char)); fflush(stdin); for (i = 0; i < n; i++) gets(strp[i]); sort(strp, n); for (i = 0; i < n; i++) puts(strp[i]); for (i = 0; i < n; i++) free(strp[i]); free(strp);先为指针数组分配空间,再为每行字符串分配空间,用完逐级 free 释放。
5.3 学生成绩统计:有一个班级 30 个学生 5 门课,编写函数实现:
#define N 30 #define M 5 int s[N][M+3]; ave = average(s); findfail(s); findgood(s);5_4.c Matrix Multiply:结果矩阵 C 的第一行依次为 30、36、42、50。
结果矩阵第二行数值为 66、81、96、116。
结果矩阵第三行数值为 102、126、150、182。
结果矩阵第四行数值为 138、171、204、248。
for (i = 0; i < m; i++) for (j = 0; j < m; j++) { c[i][j] = 0; for (k = 0; k < n; k++) c[i][j] += a[i][k] * b[k][j]; }定义一个结构体类型,从键盘输入 20 个学生的学号、姓名和数学、英语、计算机成绩,要求:
struct student { long num; char name[20]; float score[M]; float average; }; #define N 4 #define M 3 void main() { int i, j; struct student s[N]; for (i = 0; i < N; i++) { scanf("%ld%s", &s[i].num, s[i].name); for (j = 0; j < M; j++) scanf("%f", &s[i].score[j]); } calstuave(s); calcourseave(s); find(s); sort(s); output(s); }第六次上机作业 成绩处理:定义一个结构体类型,从键盘输入 20 个学生的学号和数学、英语、计算机成绩,完成四项统计输出。
文件:将上面成绩处理程序中从键盘读入的学生原始数据保存到文件 studata.dat 中;从文件中读入数据后,按平均成绩排序,并将排好序的数据保存到文件 sorted.dat 中。
typedef struct student { long num; float score[M]; float average; } STU;void main() { int n, i, j; STU *s; printf("Please input the number of students(n):"); scanf("%d", &n); s = (STU *)malloc(sizeof(STU) * n); puts("Input data of n students(num math eng computer):"); for (i = 0; i < n; i++) { scanf("%ld", &s[i].num); for (j = 0; j < M; j++) scanf("%f", &s[i].score[j]); } calstuave(n, s); save(n, s, "studata.dat"); load(&n, s, "studata.dat"); calcourseave(n, s); find(n, s); sort(n, s); save(n, s, "sorted.dat"); out(n, s); }void calstuave(int n, STU *s) { for (int i = 0; i < n; i++) { s[i].average = 0; for (int j = 0; j < M; j++) s[i].average += s[i].score[j]; s[i].average /= M; } for (int i = 0; i < n; i++) printf("Number:%ld Average:%.2f\n", s[i].num, s[i].average); } void calcourseave(int n, STU *s) { float ave[M]; for (int j = 0; j < M; j++) { ave[j] = 0; for (int i = 0; i < n; i++) ave[j] += s[i].score[j]; ave[j] /= n; } printf("Math Average:%.2f\nEnglish Average:%.2f\nComputer Average:%.2f\n", ave[0], ave[1], ave[2]); }void find(int n, STU *s) { int i, max = 0; for (i = 1; i < n; i++) if (s[i].average > s[max].average) max = i; puts("the highest average student is:\n"); printf("%ld %.2f %.2f %.2f %.2f\n", s[max].num, s[max].score[0], s[max].score[1], s[max].score[2], s[max].average); } void sort(int n, STU *s) { int i, j, k; STU t; for (i = 0; i < n-1; i++) { k = i; for (j = i+1; j < n; j++) if (s[j].average > s[k].average) k = j; if (i != k) { t = s[i]; s[i] = s[k]; s[k] = t; } } }void save(int n, STU *s, char *fname) { FILE *fp; if ((fp = fopen(fname, "wb")) == NULL) { printf("File open error.\n"); exit(0); } fwrite(&n, sizeof(int), 1, fp); for (int i = 0; i < n; i++) fwrite(s+i, sizeof(STU), 1, fp); fclose(fp); } void load(int *n, STU *s, char *fname) { FILE *fp; if ((fp = fopen(fname, "rb")) == NULL) { printf("File open error.\n"); exit(0); } fread(n, sizeof(int), 1, fp); for (int i = 0; i < *n; i++) fread(s+i, sizeof(STU), 1, fp); fclose(fp); }void out(int n, STU *s) { puts("After sorting:\n"); for (int i = 0; i < n; i++) { printf("%ld ", s[i].num); for (int j = 0; j < M; j++) printf("%.2f ", s[i].score[j]); printf("%.2f\n", s[i].average); } }下载地址:{{downurl}}
{{{a}}}
{{#b}}{{{b}}}
{{/b}} {{/title}} {{#nolog}}登陆注册
{{/nolog}} {{#djsx}}点我刷新
{{/djsx}} {{#gocz}} {{/gocz}} {{#ffqr}} {{/ffqr}}