Bootstrap

谭浩强C语言程序设计(6)文件 10章

1、打开文本文件并读取一个字符

桌面上新建文件num.txt。内容为123

#include <cstdio>   // 引入标准输入输出库
#include <cstdlib>  // 引入标准库,包含 exit 函数

int main() {
    FILE* fp;         // 声明一个文件指针,用于操作文件
    char c;           // 声明一个字符变量,用于存储从文件读取的字符

    // 打开名为 "D:\\deskTop\\num.txt" 的文件,权限为只读模式("r")
    fp = fopen("D:\\deskTop\\num.txt", "r");

    // 如果文件打开失败(返回 NULL),说明路径不存在或文件无法访问
    if (fp == NULL) {
        printf("error!"); // 打印错误信息
        exit(0);          // 退出程序,返回值 0 表示正常退出
                          // 建议改为 exit(1) 表示错误退出
    }

    // 使用 fgetc 函数从文件中读取一个字符
    // fgetc 返回读取的字符,文件结束(EOF)时返回 EOF
    c = fgetc(fp);

    // 打印读取的字符
    printf("%c\n", c); // 使用 printf 输出字符

    // 关闭文件,释放文件指针占用的资源
    fclose(fp);

    return 0; // 程序正常结束,返回 0
}

 2、读取文件的全部内容

#include <cstdio>   // 引入标准输入输出库
#include <cstdlib>  // 引入标准库,包含 exit 函数

int main() {
    FILE* fp;         // 声明一个文件指针,用于操作文件
    int c;            // 声明一个整型变量,用于存储从文件读取的字符(包括 EOF)

    // 打开名为 "D:\\deskTop\\num.txt" 的文件,权限为只读模式("r")
    fp = fopen("D:\\deskTop\\num.txt", "r");

    // 如果文件打开失败(返回 NULL),说明路径不存在或文件不可访问
    if (fp == NULL) {
        printf("error!\n"); // 打印错误信息,并添加换行符使输出整齐
        exit(1);            // 退出程序,返回值 1 表示错误退出
    }

    // 使用 fgetc 函数逐个字符读取文件
    // 当 fgetc 返回 EOF 时,表示到达文件末尾或发生错误
    while ((c = fgetc(fp)) != EOF) {
        putchar(c); // 输出当前读取的字符到标准输出(屏幕)
    }

    // 关闭文件,释放文件指针占用的资源
    fclose(fp);

    return 0; // 程序正常结束,返回值为 0
}

3、打开文件并写入字符 

#include <cstdio>   // 引入标准输入输出库
#include <cstdlib>  // 引入标准库,包含 exit 函数

int main() {
    FILE* fp;         // 声明一个文件指针,用于操作文件
    int c;            // 声明一个整型变量,用于存储字符(包括 EOF)

    // 打开名为 "D:\\deskTop\\num.txt" 的文件,权限为写入模式("w")
    fp = fopen("D:\\deskTop\\num.txt", "w");

    // 如果文件打开失败(返回 NULL),说明路径不存在或文件不可访问
    if (fp == NULL) {
        printf("error!\n"); // 打印错误信息,并添加换行符使输出整齐
        exit(1);            // 退出程序,返回值 1 表示错误退出
    }

    // 向文件写入一个字符 '2'(ASCII 码 50 对应字符 '2')
    fputc(50, fp);

    // 关闭文件,释放文件指针占用的资源
    fclose(fp);

    return 0; // 程序正常结束,返回值为 0
}

  • 文件打开模式 "w"

    • 以写入模式打开文件。如果文件不存在,会创建一个新文件;如果文件存在,会清空文件内容。

4、 输入字符串到文件直到输入#为止

#include <cstdio>   // 引入标准输入输出库
#include <cstdlib>  // 引入标准库,包含 exit 函数
#define fileName "D:\\deskTop\\num.txt"  // 定义文件路径常量

int main() {
    FILE* fp;         // 声明一个文件指针,用于操作文件
    char c;           // 声明一个字符变量,用于存储从键盘输入的字符

    // 打开文件 "D:\\deskTop\\num.txt",以写入模式("w")打开
    fp = fopen(fileName, "w");

    // 如果文件打开失败(返回 NULL),说明路径不存在或文件不可访问
    if (fp == NULL) {
        printf("error!\n"); // 打印错误信息,并添加换行符使输出整齐
        exit(1);            // 退出程序,返回值 1 表示错误退出
    }

    printf("input the string:"); // 提示用户输入字符串

    // 从键盘逐个读取字符,直到输入 '#' 为止
    c = getchar();  // 读取第一个字符
    while (c != '#') {
        fputc(c, fp); // 将字符写入文件
        c = getchar(); // 继续读取下一个字符
    }

    // 关闭文件,释放文件指针占用的资源
    fclose(fp);

    return 0; // 程序正常结束,返回值为 0
}

 5、将一个文件的内容复制到另一个文件

#include <cstdio>   // 引入标准输入输出库
#include <cstdlib>  // 引入标准库,包含 exit 函数
#define fileIN "D:\\deskTop\\in.txt"   // 定义输入文件路径常量
#define fileOUT "D:\\deskTop\\out.txt" // 定义输出文件路径常量

int main() {
    FILE* fin;   // 声明用于输入文件的文件指针
    FILE* fout;  // 声明用于输出文件的文件指针
    char c;       // 声明一个字符变量,用于存储读取的字符

    // 打开文件:以读取模式打开输出文件,以写入模式打开输入文件
    fout = fopen(fileOUT, "r"); // 输出文件用于读取
    fin = fopen(fileIN, "w");   // 输入文件用于写入

    // 检查文件是否成功打开
    if (fout == NULL || fin == NULL) {
        printf("out.txt or in.txt is not exist!\n"); // 打印错误信息
        exit(-1);                                    // 退出程序,返回值 -1 表示错误
    }

    // 从输出文件读取字符,并写入到输入文件
    c = fgetc(fout); // 从输入文件(fout,实际上是 output 文件)读取第一个字符
    while (c != EOF) { // 如果未到达文件末尾(EOF)
        fputc(c, fin); // 将字符写入到输出文件(fin,实际上是 input 文件)
        c = fgetc(fout); // 继续读取下一个字符
    }

    // 关闭文件
    fclose(fin);   // 关闭输入文件
    fclose(fout);   // 关闭输出文件

    return 0; // 程序正常结束,返回值为 0
}

6、 fgetc读取多行字符

#include <cstdio>
#include <cstdlib>
#define fileOUT "D:\\deskTop\\out.txt"

int main() {
    FILE * fout;
    char c;
    fout = fopen(fileOUT,"r");
    if (fout == NULL){
        printf("error");
        exit(-1);
    }
    c = fgetc(fout);
    while (c != EOF){
        putchar(c);
        c = fgetc(fout);
    }
    fclose(fout);
}

7、fgets读取一整行的内容

#include <cstdio>   // 引入标准输入输出库
#include <cstdlib>  // 引入标准库,包含 exit 函数
#define fileOUT "D:\\deskTop\\out.txt"  // 定义文件路径常量

int main() {
    FILE * fout;    // 声明一个文件指针,用于操作文件
    char c[50];      // 声明一个字符数组,用于存储从文件读取的字符串,大小为 50

    // 以只读模式 ("r") 打开文件 "D:\\deskTop\\out.txt"
    fout = fopen(fileOUT, "r");

    // 检查文件是否成功打开
    if (fout == NULL) {
        printf("error"); // 打印错误信息
        exit(-1);        // 退出程序,返回值 -1 表示错误
    }

    // 使用 fgets 函数从文件中读取一行内容
    // 参数说明:
    // - c: 存储读取内容的字符数组
    // - 50: 指定读取的字符数(最多读取 49 个字符,最后一个位置用于存储空字符 \0)
    // - fout: 文件指针
    fgets(c, 50, fout);

    // 打印读取的内容到控制台
    puts(c);

    // 关闭文件
    fclose(fout);

    return 0; // 程序正常结束,返回值为 0
}

fgets 函数

  • 从文件中读取一行内容(以换行符 \n 或文件末尾 EOF 为准)。

puts 函数

  • 将字符串 c 输出到标准输出(屏幕)。

  • 会在字符串末尾自动添加换行符 \n

8、fgets读取全部的内容

#include <cstdio>   // 引入标准输入输出库
#include <cstdlib>  // 引入标准库,包含 exit 函数
#define fileOUT "D:\\deskTop\\out.txt"  // 定义文件路径常量

int main() {
    FILE * fout;    // 声明一个文件指针,用于操作文件
    char c[50];      // 声明一个字符数组,用于存储从文件读取的字符串,大小为 50

    // 以只读模式 ("r") 打开文件 "D:\\deskTop\\out.txt"
    fout = fopen(fileOUT, "r");

    // 检查文件是否成功打开
    if (fout == NULL) {
        printf("error"); // 打印错误信息
        exit(-1);        // 退出程序,返回值 -1 表示错误
    }

    // 使用循环逐行读取文件内容并打印
    while (fgets(c, 50, fout)) { // 如果 fgets 成功读取一行内容
        printf("%s", c);          // 打印读取到的内容
    }

    // 关闭文件
    fclose(fout);

    return 0; // 程序正常结束,返回值为 0
}

  • while (fgets(c, 50, fout)) 是一种惯用的写法,用于逐行读取文件内容。

9、读取文件中的若干字符串,对字母进行大小排序,将排序好的字符串再保存到文件

#include <cstdio>   // 引入标准输入输出库
#include <cstdlib>  // 引入标准库函数,如 exit()
#include <cstring>  // 引入字符串操作函数,如 strcpy(), stricmp()

#define fileOUT "D:\\deskTop\\out.txt"  // 定义文件路径宏,存储目标文件路径

// 二分插入排序函数,对字符串数组进行排序
void sort(char (*p)[20], int n) {
    int high, mid, low;  // 定义二分查找的变量
    char temp[20];       // 临时变量,用于存储当前待插入的字符串

    // 从第二个元素开始,逐个插入到已排序的部分
    for (int i = 1; i < n; ++i) {
        strcpy(temp, p[i]);  // 保存当前待插入的字符串
        low = 0;             // 初始化查找范围的起点
        high = i - 1;        // 初始化查找范围的终点

        // 二分查找插入位置
        while (low <= high) {
            mid = (low + high) / 2;  // 计算中间位置
            if (stricmp(temp, p[mid]) > 0) {  // 如果待插入字符串大于中间位置的字符串
                low = mid + 1;  // 在右半部分继续查找
            } else {
                high = mid - 1;  // 在左半部分继续查找
            }
        }

        // 将插入位置之后的元素向后移动
        for (int j = i - 1; j >= low; --j) {
            strcpy(p[j + 1], p[j]);
        }

        // 将待插入字符串插入到正确位置
        strcpy(p[low], temp);
    }
}

int main() {
    FILE *fout;        // 文件指针,用于文件操作
    char c[3][20];     // 用于存储从文件中读取的字符串数组,最多存储3个长度为20的字符串

    // 打开文件以读取数据
    fout = fopen(fileOUT, "r");  // 以只读模式打开文件

    // 检查文件是否成功打开
    if (fout == NULL) {
        perror("Error opening file");  // 输出错误信息
        exit(EXIT_FAILURE);  // 退出程序
    }

    // 从文件中读取数据到数组 c 中
    for (int i = 0; i < 3; ++i) {
        fgets(c[i], 20, fout);  // 读取一行字符串,最多读取 19 个字符
    }

    // 关闭文件
    fclose(fout);

    // 调用排序函数对数组 c 进行排序
    sort(c, 3);

    // 打开文件以写入排序后的数据
    fout = fopen(fileOUT, "w");  // 以写入模式打开文件

    // 将排序后的数据写入文件
    for (int i = 0; i < 3; ++i) {
        fputs(c[i], fout);  // 将字符串写入文件
    }

    // 关闭文件
    fclose(fout);

    return 0;  // 程序正常结束
}

 10、fscanf读取文件的内容

#include <cstdio>    // 引入标准输入输出库
#include <cstdlib>   // 引入标准库函数,如 exit()

#define fileOUT "D:\\deskTop\\out.txt"  // 定义文件路径宏,存储目标文件路径

int main() {
    FILE *fout;  // 文件指针,用于文件操作
    int i;       // 用于存储从文件中读取的整数
    float f;     // 用于存储从文件中读取的浮点数

    // 打开文件以读取数据
    fout = fopen(fileOUT, "r");  // 以只读模式打开文件

    // 检查文件是否成功打开
    if (fout == NULL) {
        perror("Error opening file");  // 输出错误信息
        exit(EXIT_FAILURE);  // 终止程序
    }

    // 从文件中读取整数和浮点数
    fscanf(fout, "%d", &i);  // 读取文件中的整数
    fscanf(fout, "%f", &f);  // 读取文件中的浮点数

    // 关闭文件
    fclose(fout);

    // 打印读取的整数和浮点数
    printf("%d\n", i);  // 打印整数
    printf("%f", f);    // 打印浮点数

    return 0;  // 程序正常结束
}

 

11、使用fprintf写数据到文件 

    fout = fopen(fileOUT,"w");
    fprintf(fout,"%d",12);
    fprintf(fout,"%s","哈哈哈");
    fprintf(fout,"%f",3.14);

    fclose(fout);

 12、使用fread,fwrite读写数据到文件

#include <cstdio>    // 包含标准输入输出函数头文件
#include <cstdlib>   // 包含标准库函数头文件

#define fileName "D:\\deskTop\\out.dat"  // 定义目标文件路径(用户需要确保该路径存在)
#define N 3                               // 定义学生信息的数量

// 定义学生结构体
struct student {
    int num;     // 学号
    char name[20]; // 姓名(最多19个字符,实际存储需要额外的空字符)
} stu[N];          // 创建学生结构体数组

int main() {
    // 输入三个学生的信息
    for (int i = 0; i < N; ++i) {
        printf("Input the %d info (num, name):\n", i + 1); // 提示用户输入第i+1个学生的信息
        // 使用 %19s 限制名字的长度,避免缓冲区溢出
        if (scanf("%d %19s", &stu[i].num, stu[i].name) != 2) { // 读取学号和名字
            printf("Input error!\n"); // 输入异常提示
            return -1;                // 退出程序
        }
    }

    // 写入到文件
    FILE *file; // 定义文件指针
    file = fopen(fileName, "wb"); // 以二进制写模式打开文件
    if (file == NULL) { // 检查文件是否成功打开
        printf("Failed to open file %s!\n", fileName); // 打开失败提示
        return -1;                                  // 退出程序
    }

    for (int i = 0; i < N; ++i) { // 遍历学生数组
        // 将每个学生结构体写入文件
        if (fwrite(&stu[i], sizeof(struct student), 1, file) != 1) {
            printf("Failed to write student %d to file!\n", i + 1); // 写入失败提示
        }
    }

    fclose(file); // 关闭文件

    printf("Three students' information has been written to file %s successfully!\n", fileName); // 写入成功提示

    // 读取文件验证是不是写入成功了
    file = fopen(fileName, "rb"); // 以二进制读模式打开文件
    for (int i = 0; i < N; ++i) { // 遍历学生数组
        fread(&stu[i], sizeof(struct student), 1, file); // 从文件中读取每个学生结构体
        printf("%d %s\n", stu[i].num, stu[i].name); // 输出读取的学生信息
    }

    return 0; // 程序结束,返回退出码0(正常退出)
}

size_t fwrite(const void *ptr, size_t size, size_t count, FILE *stream);

  • ptr:指向要写入的数据的指针。
  • size:每个数据项的大小(以字节为单位)。
  • count:要写入的数据项的个数。
  • stream:指向 FILE 对象的指针,表示要写入的文件。
if (fwrite(&stu[i], sizeof(struct student), 1, file) != 1) { printf("Failed to write student %d to file!\n", i + 1); } 
  • &stu[i]:指向 stu 数组中第 i 个 student 结构体的指针。
  • sizeof(struct student):每个 student 结构体的大小。
  • 1:写入一个 student 结构体。
  • file:指向要写入的文件的指针。

 
 
size_t fread(void *ptr, size_t size, size_t count, FILE *stream); 
  • ptr:指向存储读取数据的内存块的指针。
  • size:每个数据项的大小(以字节为单位)。
  • count:要读取的数据项的个数。
  • stream:指向 FILE 对象的指针,表示要读取的文件。
 
 
fread(&stu[i], sizeof(struct student), 1, file); 
  • &stu[i]:指向 stu 数组中第 i 个 student 结构体的指针。
  • sizeof(struct student):每个 student 结构体的大小。
  • 1:读取一个 student 结构体。
  • file:指向要读取的文件的指针。

13、rewind函数实现读取文件信息,第一次将文件信息输出,第二次将文件复制到另一个文件

#include <cstdio>  // 包含标准输入输出库的头文件,提供文件操作和字符输入输出等函数,如 fopen、getc、putchar 等
#include <cstdlib> // 包含标准库的头文件,提供通用工具函数,不过在本代码中未实际使用相关功能
#include <cstring> // 包含字符串处理函数的头文件,在本代码中未实际使用相关功能
#define N 3       // 定义一个常量 N,值为 3,但在本代码中未使用该常量

int main() {
    // 定义两个文件指针,用于操作文件
    // fp1 用于读取源文件
    // fp2 用于写入目标文件
    FILE *fp1, *fp2; 

    // 以只读文本模式打开文件 "D:\\deskTop\\file1.txt" ,并将文件指针赋值给 fp1
    // "r" 表示以只读方式打开文本文件
    fp1 = fopen("D:\\deskTop\\file1.txt",  "r"); 

    // 以只写文本模式打开文件 "D:\\deskTop\\file2.txt" ,并将文件指针赋值给 fp2
    // "w" 表示以只写方式打开文本文件,如果文件不存在则创建,如果存在则清空文件内容
    fp2 = fopen("D:\\deskTop\\file2.txt",  "w"); 

    // 检查文件是否成功打开
    // 如果 fp1 或 fp2 为 NULL,说明文件打开失败
    if (fp1 == NULL || fp2 == NULL) {
        printf("文件打开失败!\n");
        return 1; // 返回非零值表示程序异常退出
    }

    // 读取文件内容并输出到控制台
    // 定义一个整型变量 c,用于存储从文件中读取的字符
    int c; 
    // 使用 getc 函数从文件 fp1 中逐个读取字符,直到文件结束(EOF 表示文件结束符)
    while ((c = getc(fp1)) != EOF) { 
        // 使用 putchar 函数将读取的字符输出到控制台
        putchar(c); 
    }

    // 将文件指针 fp1 重新指向文件的开头位置
    // 这样后续可以再次从文件开头开始读取内容
    rewind(fp1); 

    // 将文件 fp1 的内容复制到文件 fp2 中
    // 再次从文件 fp1 中逐个读取字符,直到文件结束
    while ((c = getc(fp1)) != EOF) { 
        // 使用 fputc 函数将读取的字符写入到文件 fp2 中
        fputc(c, fp2); 
    }

    // 关闭文件指针,释放系统资源
    // 关闭文件 fp1
    fclose(fp1); 
    // 关闭文件 fp2
    fclose(fp2); 

    return 0; // 返回 0 表示程序正常退出
}

14、使用rewind函数和fseek函数实现随机读写,在磁盘文件上存有 10 个学生的数据。要求将第 1,3,5,7,9 个学生数据输入计算机,并在屏幕上显示出来。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#define N 10

struct Student{
    int num;
    char name[10];
}stu[N];



int main() {

        // 输入10个学生的信息
        for (int i = 0; i < N; ++i) {
            printf("Input the %d info (num, name):\n", i + 1); // 提示用户输入第i+1个学生的信息
            // 使用 %19s 限制名字的长度,避免缓冲区溢出
            if (scanf("%d %9s", &stu[i].num, stu[i].name) != 2) { // 读取学号和名字
                printf("Input error!\n"); // 输入异常提示
                return -1;                // 退出程序
            }
        }


    //以二进制的形式保存到文件
    FILE *fp1,*fp2;
    fp1 = fopen("D:\\deskTop\\file1.txt", "wb");

    //10个学生的数据输出到文件
    for (int i = 0; i < N; ++i) {
        fwrite(&stu[i],sizeof (struct Student),1,fp1);
    }

    fp1 = fopen("D:\\deskTop\\file1.txt", "rb");
    //读取学生的信息
    for (int i = 0; i < N; i+=2) {
        fseek(fp1,i*sizeof (struct Student),0);
        fread(&stu[i],sizeof (struct Student),1,fp1);
        printf("%d %s\n",stu[i].num,stu[i].name);
    }

    fclose(fp1);

}

15、从键盘输入一个字符串,将其中的小写字母全部转换成大写字母,然后输出到一个磁盘文件 test 中保存,输入的字符串以“!”结束。

#include <cstdio>
#include <cctype>
#define N 10




int main() {
    FILE *fp;
    fp = fopen("D:\\deskTop\\test.txt","w");

    char ch;
    while ((ch = getchar()) != '!'){
        if (islower(ch)){
            ch = toupper(ch);
        }
        fputc(ch,fp);
    }
    fclose(fp);
}

16、有两个磁盘文件 A 和 B,各存放一行字母,今要求把这两个文件中的信息合并(按字母顺序排列),输出到一个新文件 C 中去。

#include <cstdio> // 包含标准输入输出库

#define N 10 // 定义常量N,但在代码中未使用

int main() {
    FILE *fpA, *fpB, *fpC; // 定义三个文件指针,分别用于文件A、B和C
    fpA = fopen("D:\\deskTop\\C\\A.txt", "r"); // 以只读模式打开文件A
    fpB = fopen("D:\\deskTop\\C\\B.txt", "r"); // 以只读模式打开文件B
    fpC = fopen("D:\\deskTop\\C\\C.txt", "w"); // 以写入模式打开文件C,用于存储结果

    char s[100]; // 定义一个字符数组,用于存储从文件A和B读取的内容
    int ch; // 定义一个整型变量,用于存储从文件中读取的字符
    int i = 0; // 初始化索引变量i,用于跟踪字符数组中的位置

    // 从文件A读取内容到字符数组s
    while ((ch = getc(fpA)) != EOF) { // 读取直到文件结束
        s[i++] = ch; // 将读取的字符存储到数组s中,并递增索引i
    }

    // 从文件B读取内容到字符数组s
    while ((ch = getc(fpB)) != EOF) {
        s[i++] = ch; // 同上
    }

    s[i] = '\0'; // 在数组s的末尾添加空字符,以形成一个字符串

    // 对数组进行排序(使用简单的选择排序算法)
    int high, low, mid; // 定义变量用于排序算法中的索引
    char temp; // 定义一个临时变量,用于交换字符
    for (int j = 1; j < i; ++j) { // 从第二个字符开始排序
        high = j - 1; // 初始化high为当前字符的前一个字符
        low = 0; // 初始化low为数组的开始
        temp = s[j]; // 保存当前要插入排序的字符
        while (low <= high) { // 当low不大于high时继续
            mid = (low + high) / 2; // 找到中间位置
            if (temp > s[mid]) { // 如果temp大于中间字符
                low = mid + 1; // 将low移动到mid的右侧
            } else { // 否则
                high = mid - 1; // 将high移动到mid的左侧
            }
        }
        // 将当前位置之后的所有字符向后移动,为temp腾出位置
        for (int k = j - 1; k >= low; --k) {
            s[k + 1] = s[k];
        }
        s[low] = temp; // 将temp插入到正确的位置
    }

    puts(s); // 输出排序后的字符串

    // 将排序后的字符串写入文件C
    fwrite(s, i * sizeof(char), 1, fpC); // 写入整个字符串

    // 关闭所有打开的文件
    fclose(fpA);
    fclose(fpB);
    fclose(fpC); // 注意:在原代码中遗漏了对文件C的关闭
}

17、有 5 个学生,每个学生有 3 门课程的成绩,从键盘输入学生数据(包括学号,姓名,3门课程成绩),计算出平均成绩,将原有数据和计算出的平均分数存放在磁盘文件 stud 中。

#include <cstdio>

struct Student{
    int num;
    char name[10];
    float scores[3];
    float ave;
}stu[5];
int main(){
    FILE *fp;
    fp = fopen("D:\\deskTop\\C\\stud.txt","w");

    //键盘输入数据
    for (int i = 0; i < 5; ++i) {
        float sum = 0;
        printf("input the No.%d's info:\n",i+1);
        scanf("%d %s %f %f %f",&stu[i].num,stu[i].name,
              &stu[i].scores[0],&stu[i].scores[1],&stu[i].scores[2]);
        for (int j = 0; j < 3; ++j) {
            sum+=stu[i].scores[j];
        }
        stu[i].ave = sum/3;
    }

    //写到文件
    for (int i = 0; i < 5; ++i) {
        if (fwrite(&stu[i],sizeof (struct Student),1,fp) != 1){
            printf("input error");
        }
    }

    fclose(fp);

    //获取文件数据
    fp = fopen("D:\\deskTop\\C\\stud.txt","r");
    for (int i = 0; i < 5; ++i) {
        fread(&stu[i],sizeof (struct Student),1,fp);
        printf("%d %s %f %f %f %f\n",stu[i].num,stu[i].name,
              stu[i].scores[0],stu[i].scores[1],stu[i].scores[2],stu[i].ave);
    }
    fclose(fp);
}

;