实验文档7

关于第7次实验课作业

实验结论

task4.c

编写程序统计文件行数、字符数(不包括空白符(空格、回车、tab键)

复制代码
 1 #define _CRT_SECURE_NO_WARNINGS
 2 #include<stdio.h>
 3 #define N 10000
 4 int main() {
 5     char ch[N];
 6     int line = 1;
 7     int n = 0;
 8     int j = 0;
 9     FILE* fp;
10     fp = fopen("data4.txt", "r");
11     if (!fp) {
12         printf("fail to open the file to read\n");
13         return 0;
14     }
15     int i = 0;
16     while (!feof(fp)) {
17         ch[i] = fgetc(fp);
18         if (ch[i] == '\n') {
19             line++;
20         }
21         if (ch[i] == EOF) {
22             break;
23         }
24         if (ch[i] == '\n' || ch[i] == ' ' || ch[i] == '    ') {
25             j++;
26         }
27         i++;
28     }
29     n = i - j;
30     fclose(fp);
31     printf("data4.txt统计结果:\n");
32     printf("%-20s%-20d\n", "行数", line);
33     printf("%-20s%-20d", "字符数(不计空白符)", n);
34     return 0;
35 }
复制代码

 

 

task5.c

复制代码
  1 #define _CRT_SECURE_NO_WARNINGS
  2 #include <stdio.h>
  3 #include <string.h>
  4 
  5 #define N 10
  6 
  7 typedef struct {
  8     long id;            // 准考证号
  9     char name[20];      // 姓名
 10     float objective;    // 客观题得分
 11     float subjective;   // 操作题得分
 12     float sum;          // 总分
 13     char result[10];    // 考试结果
 14 } STU;
 15 
 16 // 函数声明
 17 void read(STU st[], int n);
 18 void write(STU st[], int n);
 19 void output(STU st[], int n);
 20 int process(STU st[], int n, STU st_pass[]);
 21 
 22 int main() {
 23     STU stu[N], stu_pass[N];
 24     int cnt;
 25     double pass_rate;
 26 
 27     printf("从文件读入%d个考生信息...\n", N);
 28     read(stu, N);
 29 
 30     printf("\n对考生成绩进行统计...\n");
 31     cnt = process(stu, N, stu_pass);
 32 
 33     printf("\n通过考试的名单:\n");
 34     output(stu, N);   // 输出所有考生完整信息到屏幕
 35     write(stu, N);    // 输出考试通过的考生信息到文件
 36 
 37     pass_rate = 1.0 * cnt / N;
 38     printf("\n本次等级考试通过率: %.2f%%\n", pass_rate * 100);
 39 
 40     return 0;
 41 }
 42 
 43 // 把所有考生完整信息输出到屏幕上
 44 // 准考证号,姓名,客观题得分,操作题得分,总分,结果
 45 void output(STU st[], int n) {
 46     int i;
 47 
 48     printf("准考证号\t姓名\t客观题得分\t操作题得分\t总分\t\t结果\n");
 49     for (i = 0; i < n; i++)
 50         printf("%ld\t\t%s\t%.2f\t\t%.2f\t\t%.2f\t\t%s\n", st[i].id, st[i].name, st[i].objective, st[i].subjective, st[i].sum, st[i].result);
 51 }
 52 
 53 // 从文本文件examinee.txt读入考生信息:准考证号,姓名,客观题得分,操作题得分
 54 void read(STU st[], int n) {
 55     int i;
 56     FILE* fin;
 57 
 58     fin = fopen("examinee.txt", "r");
 59     if (!fin) {
 60         printf("fail to open file\n");
 61         return;
 62     }
 63 
 64     while (!feof(fin)) {
 65         for (i = 0; i < n; i++)
 66             fscanf(fin, "%ld %s %f %f", &st[i].id, st[i].name, &st[i].objective, &st[i].subjective);
 67     }
 68 
 69     fclose(fin);
 70 }
 71 
 72 // 把通过考试的考生完整信息写入文件list_pass.txt
 73 // 准考证号,姓名,客观题得分,操作题得分,总分,结果
 74 void write(STU s[], int n) {
 75     FILE* fout;
 76     fout=fopen("list_pass.txt", "w");
 77     if (!fout) {
 78         printf("fail to open the file to write\n");
 79         return;
 80     }
 81     fprintf(fout, "%-20s %-20s %-20s %-20s %-20s %-20s\n","准考证号","姓名","客观题得分","操作题得分","总分","结果");
 82     for (int i = 0; i < n; i++) {
 83         if (s[i].sum >= 60) {
 84             fprintf(fout, "%-20ld %-20s %-20.2f %-20.2f %-20.2f %-20s\n", s[i].id, s[i].name, s[i].objective, s[i].subjective, s[i].sum, s[i].result);
 85         }
 86     }
 87     fclose(fout);
 88 }
 89 // 对考生信息进行处理:计算每位考生考试总分、结果;统计考试通过的人数
 90 int process(STU st[], int n, STU st_pass[]) {
 91     int cnt = 0;
 92     for (int i = 0; i < N; i++) {
 93         st[i].sum = st[i].objective + st[i].subjective;
 94         if (st[i].sum >= 60) {
 95             strcpy(st[i].result, "通过");
 96             st_pass[cnt] = st[i];
 97             cnt++;
 98         }
 99         else {
100             strcpy(st[i].result, "不通过");
101         }
102     }
103     return cnt;
104 }
复制代码

程序正确补足后,预期运行结果如下:

1. 屏幕上输出考生成绩处理后完整信息和通过率

2. 在当前路径下生成数据结果文件list_pass.txt, 里面只保存通过的考生完整信息 

 

 

 

task6.c

必做

复制代码
 1 #define _CRT_SECURE_NO_WARNINGS
 2 #include <stdio.h>
 3 #include<stdlib.h>
 4 #include<time.h>
 5 #include<string.h>
 6 #define N 80
 7 typedef struct {
 8     char num[20];
 9     char name[20];
10     char class[40];
11 }STU;
12 STU st[N];
13 void read();
14 void func();
15 int main()
16 {
17     read();
18     func();
19     return 0;
20 }
21 void read() {
22     FILE* fin;
23     fin = fopen("list.txt", "r");
24     if (!fin) {
25         printf("fail to open the file to read\n");
26         return;
27     }
28     int number;
29     int i = 0;
30     while (!feof(fin)) {
31         number = fscanf(fin, "%s%s%s", st[i].num, st[i].name, st[i].class);
32         if (number != 3) {
33             break;
34         }
35         i++;
36     }
37 }
38 void func() {
39     srand(time(NULL));
40     int cnt[5] = { 0 };
41     int sign = 1;
42     for (int i = 0; i < 5;) {
43         int t = rand() % 80;
44         for (int j = 0; j < 5;j++) {
45             if (cnt[j] == t) {
46                 sign = 0;
47                 break;
48             }
49         }
50         if (sign) {
51             cnt[i] = t;
52             i++;
53         }
54     }
55     printf("--------------------随机抽点名单--------------------\n");
56     for (int i = 0; i < 5; i++) {
57         printf("%-20s %-20s %-40s\n", st[cnt[i]].num, st[cnt[i]].name, st[cnt[i]].class);
58     }
59     printf("--------------------保存到文件--------------------\n");
60     printf("输入文件名:");
61     char filename[20];
62     scanf("%s", filename);
63     strcat(filename, ".txt");
64     FILE* fp;
65     fp = fopen(filename, "w");
66     if (!fp) {
67         printf("fail to open the file to write\n");
68         return;
69     }
70     for (int i = 0; i < 5; i++) {
71         fprintf(fp, "%-20s %-20s %-40s\n", st[cnt[i]].num, st[cnt[i]].name, st[cnt[i]].class);
72     }
73     printf("保存成功!\n");
74 }
复制代码

 

 

 

选做

复制代码
  1 #define _CRT_SECURE_NO_WARNINGS
  2 #include <stdio.h>
  3 #include<stdlib.h>
  4 #include<time.h>
  5 #define N 80
  6 typedef struct {
  7     char num[20];
  8     char name[20];
  9     char class[40];
 10 }STU;
 11 /*
 12 struct tm
 13 {
 14     int tm_sec;  //秒,正常范围0-59, 但允许至61
 15     int tm_min;  //分钟,0-59
 16     int tm_hour; //小时, 0-23
 17     int tm_mday; //日,即一个月中的第几天,1-31
 18     int tm_mon;  //月, 从一月算起,0-11 1 + p->tm_mon;
 19     int tm_year;  //年, 从1900至今已经多少年  1900+ p->tm_year;
 20     int tm_wday; //星期,一周中的第几天, 从星期日算起,0-6
 21     int tm_yday; //从今年1月1日到目前的天数,范围0-365
 22     int tm_isdst; //日光节约时间的旗标
 23 };
 24 */
 25 
 26 STU st[N];
 27 STU stu[5];
 28 void read();
 29 void func();
 30 void bubble();
 31 int main()
 32 {
 33     read();
 34     func();
 35     return 0;
 36 }
 37 void read() {
 38     FILE* fin;
 39     fin = fopen("list.txt", "r");
 40     if (!fin) {
 41         printf("fail to open the file to read\n");
 42         return;
 43     }
 44     int number;
 45     int i = 0;
 46     while (!feof(fin)) {
 47         number = fscanf(fin, "%s%s%s", st[i].num, st[i].name, st[i].class);
 48         if (number != 3) {
 49             break;
 50         }
 51         i++;
 52     }
 53 }
 54 void func() {
 55     srand(time(NULL));
 56     int cnt[5] = { 0 };
 57     int sign = 1;
 58     for (int i = 0; i < 5; ) {
 59         int t = rand() % 80;
 60         for (int j = 0; j < 5; j++) {
 61             if (cnt[j] == t) {
 62                 sign = 0;
 63                 break;
 64             }
 65         }
 66         if (sign) {
 67             cnt[i] = t;
 68             i++;
 69         }
 70     }
 71     // 获取当前时间的时间戳
 72     time_t ct;
 73     time(&ct);
 74 
 75     // 将时间戳转换为本地时间
 76     struct tm* p;
 77     p = localtime(&ct);
 78 
 79     // 准备一个字符数组来存储格式化后的时间字符串
 80     char currenttime[20];
 81 
 82     // 使用strftime格式化时间
 83     strftime(currenttime, sizeof(currenttime), "%Y%m%d", p);
 84     printf("Current time: %s\n", currenttime);
 85     printf("-------------%s抽点名单--------------------\n", currenttime);
 86     strcat(currenttime, ".txt");
 87     FILE* fp;
 88     fp = fopen(currenttime, "w");
 89     if (!fp) {
 90         printf("fail to open the file to write\n");
 91         return;
 92     }
 93     for (int i = 0; i < 5; i++) {
 94         stu[i] = st[cnt[i]];
 95     }
 96     bubble();
 97     for (int i = 0; i < 5; i++) {
 98         printf("%-20s %-20s %-40s\n", stu[i].num, stu[i].name, stu[i].class);
 99         fprintf(fp, "%-20s %-20s %-40s\n", stu[i].num, stu[i].name, stu[i].class);
100     }
101     printf("\n文件保存成功!\n");
102 }
103 
104 void bubble() {
105     for (int i = 0; i < 4; i++) {
106         for (int j = 0; j < 4 - i; j++) {
107             if (strcmp(stu[j].num, stu[j + 1].num) > 0) {
108                 STU temp = stu[j];
109                 stu[j] = stu[j + 1];
110                 stu[j + 1] = temp;
111             }
112         }
113     }
114 }
复制代码

Tips: 1. 实现思路:利用随机数函数。具体实现有多种方式。

如,把数据读入到字符串数组中,生成随机数映 射数组下标,实现随机抽取。

2. 随机抽点可以借助随机函数 rand() 和 srand() 

3. 读取当前系统日期时间自动生成文件名,可以查阅系统日期读取函数 localtime() 或 localtime_s() 的用法,

以及把日期时间转换为字符串的函数 strftime() ,从系统读取的日期时间转换成字符串,作为文件名使用。 

4. 被抽取到的学生信息不能重复,可以定义标记数组辅助处理

 

 

 

附录

task1.c

验证性实验:理解函数 write 和 read 功能,掌握文件打开/关 闭、格式化读写操作

文件读写操作:格式化读、写文本文件 

复制代码
 1 #define _CRT_SECURE_NO_WARNINGS
 2 #include<stdio.h>
 3 
 4 #define N 80
 5 #define M 100
 6 
 7 typedef struct {
 8     char name[N];        //书名
 9     char author[N];        //作者
10 }Book;
11 void write();
12 void read();
13 int main() {
14     printf("测试1: 把图书信息写入文本文件\n");
15     write();
16 
17     printf("\n测试2: 从文本文件读取图书信息, 打印输出到屏幕\n");
18     read();
19 
20     return 0;
21 }
22 void write() {
23     Book x[] = { {"《雕塑家》", "斯科特.麦克劳德"},
24                   {"《灯塔》", "克里斯多夫.夏布特"},
25                   {"《人的局限性》", "塞缪尔.约翰生"},
26                   {"《永不停步:玛格丽特.阿特伍德传》", "罗斯玛丽.沙利文"},
27                   {"《大地之上》", "罗欣顿·米斯特里"},
28                   {"《上学记》", "何兆武"},
29                   {"《命运》", "蔡崇达"} };
30     int n;
31     FILE* fp;
32 
33     // 计算数组x中元素个数
34     n = sizeof(x) / sizeof(x[0]);
35 
36     //以写的方式打开文本文date1.txt
37     fp = fopen("date1.txt", "w");
38     //如果打开文件失败,输出提示信息并返回
39     if (fp == NULL) {
40         printf("fail to open file to write\n");
41         return;
42     }
43     // 将结构体数组x中的图书信息格式化写到fp指向的文件data1.txt
44     for (int i = 0; i < n; i++) {
45         fprintf(fp, "%-40s %-20s\n", x[i].name, x[i].author);
46     }
47     fclose(fp);
48 }
49 void read()
50 {
51     Book x[M];
52     int i, n;
53     int number;
54 
55 
56     FILE* fp;
57 
58     // 以读的方式打开文本文件data1.txt
59     fp = fopen("date1.txt", "r");
60     // 如果打开文件失败,输出提示信息并返回
61     if (fp == NULL) {
62         printf("fail to open file to read\n");
63         return;
64     }
65     // 从文件中读取图书信息,保存到结构体数组x中
66     i = 0;
67     while (!feof(fp)) {
68         number = fscanf(fp, "%s%s", x[i].name, x[i].author);
69         if (number != 2)
70             break;
71         i++;
72     }
73     n = i;
74     // 将图书信息打印输出到屏幕上
75     for (i = 0; i < n; i++) {
76         printf("%d.%-40s%-20s\n", i + 1, x[i].name, x[i].author);
77     }
78     fclose(fp);
79 }
复制代码

程序正确录入、执行后,预期结果如下: 

1. 当前路径下生成数据文件data1.txt(用文本编辑器打开,内容如下所示)

2. 屏幕上输出图书信息

question1:去掉line75-76,重新编译,再次运行程序,观察结果,对比运行结果是否有不同。

结合结果,查阅资料,分析这两行代码放在这里起到什么作用?

answer1:无限循环风险&&数据不准确

当文件读取到末尾(EOF)时,fscanf 将无法再成功读取数据,因此返回的 number 将小于2

(实际上,当遇到EOF时,fscanf 通常会返回EOF本身,通常是一个负值,或者小于尝试读取的项数)。

如果没有 if (number != 2) break; 来检查这一点,循环将继续进行,

但由于 fscanf 失败,x[i] 将不会被正确填充,

而 i 仍然会增加,导致无限循环(或至少直到数组 x 越界)。

即使循环最终由于某种原因(如系统资源耗尽)停止,数组 x 中的数据也将是不准确的,

因为最后一次循环迭代可能由于 fscanf 失败而没有正确填充结构体。

 

 

 

task2.c

 验证性实验:理解函数 write 和 read 功能,练习和掌握二进制 文件数据块读写操作

文件读写操作:以数据块方式读、写二进制文件

复制代码
 1 #define _CRT_SECURE_NO_WARNINGS
 2 #include<stdio.h>
 3 
 4 #define N 80
 5 #define M 100
 6 
 7 typedef struct {
 8     char name[N];       // 书名
 9     char author[N];     // 作者
10 } Book;
11 
12 void write();
13 void read();
14 
15 int main() {
16     printf("测试1: 把图书信息以数据块方式写入二进制文件\n");
17     write();
18 
19     printf("\n测试2: 从二进制文件读取图书信息, 打印输出到屏幕\n");
20     read();
21 
22     return 0;
23 }
24 void write()
25 {
26     Book x[] = { {"《雕塑家》", "斯科特.麦克劳德"},
27                   {"《灯塔》", "克里斯多夫.夏布特"},
28                   {"《人的局限性》", "塞缪尔.约翰生"},
29                   {"《永不停步:玛格丽特.阿特伍德传》", "罗斯玛丽.沙利文"},
30                   {"《大地之上》", "罗欣顿·米斯特里"},
31                   {"《上学记》", "何兆武"},
32                   {"《命运》", "蔡崇达"} };
33     int n;
34     FILE* fp;
35     // 计算数组x中元素个数
36     n = sizeof(x) / sizeof(x[0]);
37     // 以写的方式打开二进制文件data2.dat
38     fp = fopen("data2.dat", "wb");
39     // 如果打开文件失败,输出提示信息并返回
40     if (fp == NULL) {
41         printf("fail to open file to write\n");
42         return;
43     }
44     // 将结构体数组x中的图书信息以数据块方式写入二进制文件data2.dat
45     fwrite(x, sizeof(Book), n, fp);
46     fclose(fp);
47 }
48 void read() {
49     Book x[N];
50     int i, n;
51     int number;
52     FILE* fp;
53 
54     // 以读的方式打开二进制文件data2.dat
55     fp = fopen("data2.dat", "rb");
56     // 如果打开文件失败,输出提示信息并返回
57     if (fp == NULL) {
58         printf("fail to open the file to read\n");
59         return;
60     }
61     // 从二进制文件data2.dat以数据块方式读取图书信息存储到结构体数组x
62     i = 0;
63     while (!feof(fp)) {
64         number = fread(&x[i], sizeof(Book), 1, fp);
65         if (number != 1)
66             break;
67         i++;
68     }
69     n = i;
70     // 在屏幕上打印输出
71     for (i = 0; i < n; i++) {
72         printf("%d.%-40s%-20s\n", i + 1, x[i].name, x[i].author);
73     }
74     fclose(fp);
75 }
复制代码

程序正确录入、执行后,预期结果如下:

1. 当前路径下生成二进制数据文件data2.dat(尝试用文本编辑器打开,其内容不直观可见)

2. 屏幕上输出图书信息 

Tips:

write 模块,向二进制文件data2.dat写入数据时,是一次性写入n项数据

read 模块从二进制文件data2.dat读取数据时,可能并不知道文件中实际包含多少个数据项。因此是逐个数据项读入的

question1:去掉line75-76,重新编译,再次运行程序,观察结果,对比运行结果是否有不同。

结合结果,查阅资料,分析这两行代码放在这里起到什么作用? 

answer1:无限循环&&打印垃圾数据

当文件读取到末尾(EOF)时,fread 将无法再成功读取更多的数据块。

然而,如果没有 if (number != 1) break; 这一条件来检查 fread 的返回值,循环可能会继续执行,

因为 feof(fp) 只有在尝试读取越过文件末尾时才会返回真(true)。

这意味着,在最后一次成功读取之后和 feof(fp) 返回真之间,

可能会有一个或多个循环迭代,其中 fread 失败但循环仍然继续。

即使循环最终由于某种原因(如系统资源耗尽或程序崩溃前的其他错误)停止,

数组 x 中超出实际读取数据范围的部分将包含未初始化的数据(即垃圾数据)。

当打印这些数据时,屏幕上将显示无意义的内容。

 

task3.c

验证性实验:理解函数 write , read_str 和 read_char 功能, 练习以字符、字符串方式读写文件

文件读写操作:以字符、字符串形式读、写 

复制代码
 1 #define _CRT_SECURE_NO_WARNINGS
 2 #include<stdio.h>
 3 
 4 #define N 5
 5 #define M 80
 6 void write();
 7 void read_str();
 8 void read_char();
 9 
10 int main() {
11     printf("测试1: 把一组字符信息以字符串方式写入文本文件\n");
12     write();
13 
14     printf("\n测试2: 从文件以字符串方式读取, 输出到屏幕\n");
15     read_str();
16 
17     printf("\n测试3: 从文件以单个字符方式读取, 输出到屏幕\n");
18     read_char();
19 
20     return 0;
21 }
22 void write() {
23     char* ptr[N] = { "Working\'s Blues",
24                     "Everything Will Flow",
25                     "Streets of London",
26                     "Perfect Day",
27                     "Philadelphia" };
28     FILE* fp;
29     fp = fopen("data3.txt", "w");
30     if (!fp) {
31         printf("fail to open the file to write\n");
32         return;
33     }
34     for (int i = 0; i < N; i++) {
35         fputs(ptr[i], fp);
36         fputs("\n", fp);
37     }
38     fclose(fp);
39 }
40 void read_str() {
41     char songs[N][M];
42     FILE* fp;
43     fp = fopen("data3.txt", "r");
44     if (!fp) {
45         printf("fail to open the file yo read\n");
46         return;
47     }
48     for (int i = 0; i < N; ++i) {
49         fgets(songs[i], 80, fp);
50     }
51     for (int i = 0; i < N; ++i) {
52         printf("%d.%s", i + 1, songs[i]);
53     }
54     fclose(fp);
55 }
56 void read_char() {
57     char ch;
58     FILE* fp;
59     fp = fopen("data3.txt", "r");
60     if (!fp) {
61         printf("fail to open file to read\n");
62         return;
63     }
64     while (!feof(fp)) {
65         ch = fgetc(fp);
66         if (ch == EOF) {
67             break;
68         }
69         putchar(ch);
70     }
71     fclose(fp);
72 }
复制代码

程序正确录入、执行后,预期结果如下:

1. 当前路径下生成文本数据文件data3.txt(用文本编辑器打开,其内容如下所示)

2. 屏幕上输出两次从文件读取的信息 

question1:代码line25字符串 "Working\'s Blues"输出时为什么没有显示反斜杠\? 

answer1:转义字符\'表示’

posted @   知返返返  阅读(37)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示