2024-2025-1 20241314 《计算机基础与程序设计》第十二周学习总结

2024-2025-1 20241314 《计算机基础与程序设计》第十二周学习总结

作业信息

这个作业属于哪个课程 2024-2025-1-计算机基础与程序设计
这个作业要求在哪里 2024-2025-1计算机基础与程序设计第十二周作业
这个作业的目标 复习
作业正文 正文

教材学习内容总结

  1. 引言与文件概述

    • 在《C语言程序设计》的前几章,重点通常放在基本数据类型、控制结构和函数等内容上。到了第11章的文件部分,主要关注的是程序与外部存储设备(如硬盘)之间的数据交换。
    • 文件是存储在外部介质上的数据集合,这些数据可以是程序代码、文本、图像、音频等各种形式。对于C程序而言,能够有效地操作文件是非常重要的,因为它允许程序保存和读取数据,从而实现数据的持久化存储。
  2. 文件类型与存储方式

    • 文本文件
      • 文本文件是基于字符编码(如ASCII或UTF - 8)存储的文件。在文本文件中,每个字符都有对应的编码值。例如,字符'A'在ASCII码中对应的十进制值是65。
      • 当使用文本编辑器打开文本文件时,会将这些编码值转换为可识别的字符显示出来。文本文件的内容可以被人类直接阅读和理解。例如,一个简单的包含“Hello, World!”的文本文件,存储的就是这些字符对应的编码。
    • 二进制文件
      • 二进制文件以二进制形式存储数据,不是以字符编码的方式。它可以存储各种类型的数据,如整数、浮点数、结构体等。
      • 例如,一个整数10在内存中以二进制形式存储(假设为32位整数,其二进制表示为00000000000000000000000000001010),在二进制文件中也是以类似的二进制形式存储。与文本文件不同,二进制文件内容如果直接打开查看,可能是一堆乱码,因为它不是按照字符编码来存储的。
  3. 文件指针与FILE结构体

    • C语言通过文件指针来操作文件。文件指针是一个指向FILE结构体的指针。FILE结构体是在<stdio.h>头文件中定义的,它包含了文件操作所需的各种信息。
    • 例如,文件指针的定义形式为FILE *fp;,这里fp就是文件指针变量。这个FILE结构体内部包含了文件当前的读写位置、缓冲区信息、文件的状态标志(如文件是否已到达末尾、是否发生错误等)等重要信息。
  4. 文件的打开与关闭操作

    • 文件打开函数fopen
      • 语法:FILE *fp = fopen("文件名","打开模式");
      • “文件名”参数指定要打开的文件名称。如果文件不在当前目录下,需要提供完整的路径。例如,在Windows系统下,"C:\\Users\\user\\Documents\\data.txt"指定了C盘用户文档文件夹下的data.txt文件;在Linux系统下,"/home/user/data.txt"指定了用户主目录下的data.txt文件。
      • “打开模式”决定了文件打开后的操作方式。常见的打开模式有:
        • "r":只读模式打开文本文件。如果文件不存在,fopen函数返回NULL,表示打开失败。
        • "w":只写模式打开文本文件。如果文件不存在,会创建新文件;如果文件存在,会清空文件内容。
        • "a":追加模式打开文本文件。如果文件不存在,会创建新文件;如果文件存在,会在文件末尾添加内容。
        • 对于二进制文件,相应的模式有"rb""wb""ab",分别表示二进制文件的只读、只写、追加模式。
      • 例如,要打开一个当前目录下的文本文件test.txt用于读取,可以这样写:
        FILE *fp = fopen("test.txt","r");
        if(fp == NULL) {
            perror("文件打开失败");
            return 1;
        }
        
        这里使用perror函数来输出错误信息,当fpNULL时,perror会输出错误原因。
    • 文件关闭函数fclose
      • 语法:fclose(fp);,其中fp是通过fopen函数打开文件得到的文件指针。
      • 关闭文件的重要性在于确保缓冲区中的数据被正确写入文件,防止数据丢失。同时,及时关闭文件可以释放文件相关的系统资源,使系统能够更好地管理文件。例如,如果程序频繁打开文件而不关闭,可能会导致系统资源耗尽,影响其他程序的运行。
  5. 文件的读写操作

    • 字符读写函数fgetcfputc
      • fgetc函数
        • 语法:int ch = fgetc(fp);,其中fp是文件指针。
        • 功能:从文件指针fp指向的文件中读取一个字符。读取成功后,返回读取到的字符的ASCII码值。如果遇到文件末尾或者读取错误,返回EOFEOF是在<stdio.h>中定义的常量,通常值为 - 1)。
        • 例如,以下代码可以读取一个文本文件的内容并输出到控制台:
          FILE *fp = fopen("input.txt","r");
          int ch;
          while((ch = fgetc(fp))!= EOF) {
              putchar(ch);
          }
          fclose(fp);
          
      • fputc函数
        • 语法:fputc('A',fp);,这里将字符'A'写入文件指针fp指向的文件中。
        • 功能:将一个字符写入文件。如果写入成功,返回写入的字符;如果写入失败,返回EOF
    • 字符串读写函数fgetsfputs
      • fgets函数
        • 语法:char str[100]; fgets(str, sizeof(str),fp);
        • 功能:从文件中读取一行字符串。它会读取最多sizeof(str) - 1个字符(因为要预留一个位置给字符串结束符'\0')到str数组中。
        • 返回值:如果读取成功,返回str(即读取到的字符串的首地址);如果遇到文件末尾或者读取错误,返回NULL。例如,以下代码可以读取文件中的每一行并打印:
          FILE *fp = fopen("lines.txt","r");
          char line[256];
          while(fgets(line, sizeof(line),fp)!= NULL) {
              printf("%s",line);
          }
          fclose(fp);
          
      • fputs函数
        • 语法:fputs("Hello World",fp);,将字符串“Hello World”写入文件(不包括字符串结束符'\0')。
        • 功能:将一个字符串写入文件。如果写入成功,返回一个非负整数;如果写入失败,返回EOF
    • 格式化读写函数fscanffprintf
      • fscanf函数
        • 语法:fscanf(fp,"%d %s", &num, str);,从文件中按照指定格式读取数据。
        • 功能:类似于scanf函数,用于从文件中读取数据。可以读取整数、浮点数、字符串等按照指定格式组合的数据。
        • 返回值:如果成功读取了指定格式的数据,返回成功读取的项数;如果遇到文件末尾或者读取错误,返回EOF
      • fprintf函数
        • 语法:fprintf(fp,"%d %s", num, str);,将数据按照指定格式写入文件。
        • 功能:类似于printf函数,用于将数据写入文件。可以将整数、浮点数、字符串等按照指定格式组合的数据写入文件。
        • 例如,若有一个结构体用于存储学生信息,包括学号和姓名,可以使用fscanf从文件中读取学生信息,使用fprintf将学生信息写入文件:
          struct Student {
              int id;
              char name[50];
          };
          struct Student s;
          FILE *fp = fopen("students.txt","r");
          fscanf(fp,"%d %s", &s.id, s.name);
          fclose(fp);
          fp = fopen("students.txt","w");
          fprintf(fp,"%d %s", s.id, s.name);
          fclose(fp);
          
    • 块读写函数freadfwrite
      • fread函数
        • 语法:fread(&struct_var, sizeof(struct_var), 1,fp);,用于从文件中读取二进制数据块。
        • 功能:从文件中读取一个数据块,数据块大小为sizeof(struct_var),读取的数量为1,存储到&struct_var地址处。常用于读取二进制文件中的结构体、数组等数据。
      • fwrite函数
        • 语法:fwrite(&struct_var, sizeof(struct_var), 1,fp);,用于将二进制数据块写入文件。
        • 功能:将&struct_var地址处的数据块(大小为sizeof(struct_var))写入文件,写入数量为1。例如,将一个结构体数组写入二进制文件:
          struct Data {
              int value;
          };
          struct Data data_array[10];
          FILE *fp = fopen("data.bin","wb");
          fwrite(data_array, sizeof(data_array), 1,fp);
          fclose(fp);
          
  6. 文件的定位操作

    • ftell函数
      • 语法:long offset = ftell(fp);
      • 功能:获取文件指针fp的当前位置,返回值是一个长整型,表示文件指针相对于文件开头的偏移量(以字节为单位)。例如,在读取文件过程中,可以通过ftell函数记录当前读取位置。
    • fseek函数
      • 语法:fseek(fp, offset, origin);,其中fp是文件指针,offset是偏移量(可以是正、负或零),origin是起始位置,有SEEK_SET(文件开头)、SEEK_CUR(文件当前位置)、SEEK_END(文件末尾)三种选择。
      • 功能:用于移动文件指针的位置。例如,fseek(fp, 10L, SEEK_SET);会将文件指针从文件开头向后移动10个字节。这在随机读写文件时非常有用,比如在文件中间插入或修改数据。
    • rewind函数
      • 语法:rewind(fp);
      • 功能:将文件指针重新定位到文件开头。当需要重新读取一个已经打开的文件的内容,或者对文件进行多次读写操作每次从开头开始时,可以使用rewind函数。例如,在一个文件中先读取数据用于统计,然后再读取数据用于打印,就可以在第二次读取前使用rewind函数将文件指针移回开头。

教材学习中的问题和解决过程

问题1:打开文件必须用指针吗

答:在C语言中,打开文件时通常会使用文件指针,但并不是绝对必须的。以下是一些相关的要点:

  1. 使用指针的原因:文件指针(FILE*类型)用于指向打开的文件。通过这个指针,程序可以读取或写入文件的内容。使用指针可以方便地管理文件操作,例如读取、写入、关闭文件等。

  2. 示例代码

    FILE *file = fopen("example.txt", "r");
    if (file == NULL) {
        perror("Error opening file");
        return -1;
    }
    // 文件操作...
    fclose(file);
    
  3. 没有指针的情况:在某些高层次的编程语言中,或是使用特定的库,可能不需要直接处理文件指针。例如,Python中可以直接通过文件对象进行操作,不需要显示的指针类型。

  4. 抽象封装:在C语言中,虽然文件操作依赖指针,但有些高级的抽象(如类或结构体)可以封装这些操作,间接地使用文件指针。

问题2:fopen函数中不同的文件打开模式(如"r"、"w"、"a"等)是什么意思?它们之间有什么主要的区别?

答:
在C语言中,fopen函数用于打开文件,并允许以不同的模式来读取或写入数据。每种打开模式具有不同的含义和行为。以下是一些常用的文件打开模式及其主要区别:

常用文件打开模式

  1. "r"(只读模式):

    • 打开一个现有的文件进行读取。
    • 文件指针指向文件的开头。
    • 如果文件不存在,fopen返回NULL
  2. "w"(写入模式):

    • 创建一个新文件用于写入(如果文件已经存在,则会被截断为零长度,也就是清空文件)。
    • 文件指针指向文件的开头。
    • 如果文件不存在,自动创建新文件。
  3. "a"(追加模式):

    • 打开一个现有的文件用于写入,并将数据附加到文件末尾。
    • 如果文件不存在,则创建新文件。
    • 文件指针指向文件的末尾。
  4. "r+"(读写模式):

    • 打开一个现有的文件以便读取和写入。
    • 文件指针指向文件的开头。
    • 如果文件不存在,fopen返回NULL
  5. "w+"(读写创建模式):

    • 创建一个新文件用于读取和写入(如果文件已存在将被截断)。
    • 文件指针指向文件的开头。
  6. "a+"(读写追加模式):

    • 打开一个文件用于读取和写入,并将数据附加到文件末尾。
    • 如果文件不存在,将创建新文件。
    • 文件指针指向文件的末尾。

主要区别

  • 文件存在性

    • "r""r+"模式要求文件必须存在;如果不存在,打开失败。
    • "w""w+""a""a+"模式会创建新文件,如果文件不存在。
  • 数据处理方式

    • "w""w+"会清空已有文件的内容,而"a""a+"则会保留文件内容,将新数据追加到文件末尾。
  • 读写权限

    • "r""r+"只有读取权限,不能写入。
    • "w""w+""a""a+"允许写入,有些模式还允许读取。

示例代码

以下是一个示例,展示如何使用这些模式:

#include <stdio.h>

int main() {
    // 只读
    FILE *file1 = fopen("example.txt", "r");
    if (file1 == NULL) {
        perror("Error opening file for reading");
    }

    // 写入(清空文件)
    FILE *file2 = fopen("example.txt", "w");
    if (file2 == NULL) {
        perror("Error opening file for writing");
    }

    // 追加
    FILE *file3 = fopen("example.txt", "a");
    if (file3 == NULL) {
        perror("Error opening file for appending");
    }

    // 读写
    FILE *file4 = fopen("example.txt", "r+");
    if (file4 == NULL) {
        perror("Error opening file for reading and writing");
    }

    // 关闭文件
    fclose(file1);
    fclose(file2);
    fclose(file3);
    fclose(file4);

    return 0;
}

问题3:在处理多个文件时,是否可以同时打开多个文件指针?如果可以,如何确保同时进行的文件操作不会互相干扰?

答:
在C语言中,可以同时打开多个文件指针,这对于处理多个文件是非常常见的情况。例如,程序可以同时读取一个文件并写入另一个文件。在操作多个文件时,有几件事需要注意,以确保文件操作互不干扰:

同时打开多个文件指针

你可以简单地通过多次调用fopen()来打开多个文件。每个打开的文件都会返回一个独立的FILE*指针。例如:

#include <stdio.h>

int main() {
    FILE *file1 = fopen("file1.txt", "r");
    FILE *file2 = fopen("file2.txt", "w");

    if (file1 == NULL || file2 == NULL) {
        perror("Error opening files");
        return -1;
    }

    // 处理文件...

    fclose(file1);
    fclose(file2);
    return 0;
}

确保操作不互相干扰

  1. 使用独立的文件指针:每个文件都通过单独的FILE*指针进行操作。在写入或读取文件时,确保使用正确的指针。例如,不要在写入file2时错误地使用file1

  2. 检查返回值:在每次文件操作后确认操作是否成功,例如检查fgets()fprintf()等函数的返回值,以确保操作没有出错。

  3. 控制文件位置:利用fseek()ftell()等函数管理每个文件的读取和写入位置,确保在通用操作中不产生混淆。

  4. 正确关闭文件:在完成所有文件操作后,应确保使用fclose()关闭每个文件。这不仅释放了资源,还确保所有缓冲区数据已正确写入文件。

  5. 防止竞争条件:在多线程程序中处理文件时,确保对文件的访问是线程安全的。这可以通过互斥锁等机制来实现,以避免多个线程同时对同一个文件进行操作。

示例

下面是一个简单的示例,展示如何同时读取一个文件并向另一个文件写入数据,而不产生干扰:

#include <stdio.h>

int main() {
    FILE *inputFile = fopen("input.txt", "r");
    FILE *outputFile = fopen("output.txt", "w");

    if (inputFile == NULL || outputFile == NULL) {
        perror("Error opening files");
        return -1;
    }

    char buffer[100];

    // 读取 input.txt 的内容并写入 output.txt
    while (fgets(buffer, sizeof(buffer), inputFile) != NULL) {
        fputs(buffer, outputFile); // 将读取的内容写入 output.txt
    }

    // 关闭文件
    fclose(inputFile);
    fclose(outputFile);

    return 0;
}

在这个例子中,inputFileoutputFile是两个独立的文件指针,用于同时读写不同的文件。它们的操作彼此独立,不会干扰。

基于AI的学习





posted @ 2024-12-15 18:08  欧阳嘉盛  阅读(4)  评论(0编辑  收藏  举报