• 【复习必备】C语言中的文件操作


    🌹作者:云小逸
    📝个人主页:云小逸的主页
    📝Github:云小逸的Github
    🤟motto:要敢于一个人默默的面对自己,强大自己才是核心。不要等到什么都没有了,才下定决心去做。种一颗树,最好的时间是十年前,其次就是现在!学会自己和解,与过去和解,努力爱自己。==希望春天来之前,我们一起面朝大海,春暖花开!==🤟
    👏专栏:C++👏 👏专栏:Java语言👏
    👏专栏:C语言初阶👏👏专栏:数据结构👏


    前言

    今天这篇文章我们是学习:C语言中的文件操作,这一块知识点还是蛮重要,对于我们学习后续Linux过程有不少的帮助,希望我这篇文章可以帮到你,如果感觉我的文章对你有帮助,记得一键三连哦!
    在这里插入图片描述

    ——————————————————————————————

    一.文件:

    为什么使用文件?

    当我们编写C语言程序时,文件操作是不可或缺的一部分。文件允许我们在程序执行之间保持数据的持久性。无论是存储用户信息、日志记录还是配置文件,文件都发挥着关键作用。

    通过文件操作,我们可以轻松读取和写入数据,实现数据的长期保存和共享。这对于创建数据驱动的应用程序至关重要。此外,文件操作也为数据备份和恢复提供了便捷途径,增加了程序的可靠性。

    C语言提供了强大的文件处理功能,包括打开、读取、写入和关闭文件。了解如何有效地使用这些功能,可以帮助我们更好地控制数据流,提高程序的实用性和可维护性。因此,文件操作是C语言编程中不可或缺的重要组成部分。

    什么是文件:

    我们平时电脑磁盘上的文件就是文件。
    但是在程序设计中,我们一般谈的文件有两种:程序文件、数据文件(从文件功能的角度来分类的)。

    程序文件

    包括源程序文件(后缀为.c),目标文件(windows环境后缀为.obj),可执行程序(windows环境后缀为.exe)。

    数据文件

    文件的内容不一定是程序,而是程序运行时读写的数据,比如程序运行需要从中读取数据的文件,或者输出内容的文件。

    文件名:

    一个文件要有一个唯一的文件标识,以便用户识别和引用。
    文件名包含3部分:文件路径+文件名主干+文件后缀
    例如: c:\code\test.txt
    为了方便起见,文件标识常被称为文件名

    在这里面:
    c:\code\是文件路径
    test是文件名主干
    .txt是文件后缀
    
    • 1
    • 2
    • 3
    • 4

    二.文件的打开和关闭:

    文件指针:

    缓冲文件系统中,关键的概念是“文件类型指针”,简称“文件指针”。
    每个被使用的文件都在内存中开辟了一个相应的文件信息区,用来存放文件的相关信息(如文件的名字,文件状态及文件当前的位置等)。这些信息是保存在一个结构体变量中的。该结构体类型是有系统声明的,取名FILE

    例如,VS2013编译环境提供的 stdio.h 头文件中有以下的文件类型申明

    struct _iobuf {
            char *_ptr;
            int   _cnt;
            char *_base;
            int   _flag;
            int   _file;
            int   _charbuf;
            int   _bufsiz;
            char *_tmpfname;
           };
    typedef struct _iobuf FILE;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    如果你用的vs编辑器比较新,尽可能看不到具体实现,
    如VS2019中是这样的:
    在这里插入图片描述
    不同的C编译器的FILE类型包含的内容不完全相同,但是大同小异。
    每当打开一个文件的时候,系统会根据文件的情况自动创建一个FILE结构的变量,并填充其中的信息,使用者不必关心细节。
    一般都是通过一个FILE的指针来维护这个FILE结构的变量,这样使用起来更加方便。
    下面我们可以创建一个FILE*的指针变量:

    FILE* pf;//文件指针变量
    
    • 1

    定义pf是一个指向FILE类型数据的指针变量。可以使pf指向某个文件的文件信息区(是一个结构体变量)。通过该文件信息区中的信息就能够访问该文件。也就是说,通过文件指针变量能够找到与它关联的文件

    在这里插入图片描述

    文件的打开和关闭:

    正常进行一个文件操作,完整步骤是:

    • 打开文件fopen
    • 读/写文件
    • 关闭文件fclose
      文件在读写之前应该先打开文件,在使用结束之后应该关闭文件。
      在编写程序的时候,在打开文件的同时,都会返回一个FILE*的指针变量指向该文件,也相当于建立了指针和文件的关系

    ANSIC 规定使用fopen函数来打开文件,fclose来关闭文件。
    打开方式如下:

    //打开文件
    FILE * fopen ( const char * filename, const char * mode );
    //关闭文件
    int fclose ( FILE * stream );
    
    • 1
    • 2
    • 3
    • 4

    fopen函数:

    fopen 函数是C标准库中用于打开文件的函数,它允许你创建一个文件指针,并将其与指定的文件相关联,以便进行文件的读取或写入操作。下面是关于 fopen 函数的详细信息:

    函数原型:

    FILE *fopen(const char *filename, const char *mode);
    
    • 1

    参数:

    • filename:一个字符串,表示要打开的文件的路径和文件名。
    • mode:一个字符串,表示打开文件的模式。

    返回值:

    • 如果成功打开文件,fopen 返回一个指向 FILE 结构的指针,该指针用于后续的文件操作。
    • 如果打开文件失败,fopen 返回 NULL 指针。

    常见的打开模式(mode):

    模式含义
    "r"只读模式,用于读取文件。
    "w"写入模式,用于创建新文件并写入数据。如果文件已存在,则截断。
    "a"追加模式,用于在文件末尾写入数据。如果文件不存在,则创建。
    "rb"二进制只读模式,用于以二进制格式读取文件。
    "wb"二进制写入模式,用于以二进制格式创建新文件并写入数据。
    "ab"二进制追加模式,用于以二进制格式在文件末尾写入数据。如果不存在,则创建。

    示例用法:

    #include 
    
    int main() {
        FILE *file;
        
        // 打开一个文件用于读取
        file = fopen("example.txt", "r");
        
        if (file == NULL) {
            printf("无法打开文件\n");
            return 1;
        }
        
        // 在这里可以使用 file 进行文件读取操作
        
        fclose(file); // 关闭文件
        
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    fopen 函数是进行文件输入和输出操作的重要起点,它允许你在C程序中与外部文件进行交互。在打开文件后,你可以使用其他文件操作函数来读取或写入数据,最后使用 fclose 函数来关闭文件。请注意,文件操作过程中应谨慎处理错误情况以确保程序的稳定性。

    fclose函数:

    fclose 函数是C标准库中用于关闭文件的函数。当你完成对一个文件的读取或写入操作后,应该使用 fclose 来关闭文件,这将释放与文件相关的资源并确保文件的完整性。以下是关于 fclose 函数的详细信息:

    函数原型:

    int fclose(FILE *stream);
    
    • 1

    参数:

    • stream:一个指向 FILE 结构的指针,该指针代表要关闭的文件。

    返回值:

    • 如果成功关闭文件,fclose 返回零。
    • 如果关闭文件失败,fclose 返回非零值,通常用于表示关闭文件时发生了错误。

    示例用法:

    #include 
    
    int main() {
        FILE *file;
        
        // 打开一个文件用于读取
        file = fopen("example.txt", "r");
        
        if (file == NULL) {
            printf("无法打开文件\n");
            return 1;
        }
        
        // 在这里可以使用 file 进行文件读取操作
        
        // 关闭文件
        if (fclose(file) == 0) {
            printf("文件已成功关闭\n");
        } else {
            printf("关闭文件时发生了错误\n");
        }
        
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    fclose 函数执行以下操作:

    1. 将文件缓冲区中的未写入数据刷新到文件。
    2. 关闭文件,释放与文件相关的资源。
    3. 返回成功关闭文件时返回零,否则返回非零值以表示错误。

    在文件操作过程中,确保在不再需要文件时及时关闭它,以避免资源泄漏和数据损坏。通常,fclose 应该在文件操作完成后立即调用。

    三.文件的顺序读写:

    以下是一些常用的输入和输出函数,以及它们适用于的流和用途,

    功能函数名适用于
    字符输入函数fgetc所有输入流
    字符输出函数fputc所有输出流
    文本行输入函数fgets所有输入流
    文本行输出函数fputs所有输出流
    格式化输入函数fscanf所有输入流
    格式化输出函数fprintf所有输出流
    二进制输入函数fread文件
    二进制输出函数fwrite文件

    这些函数是C语言标准库中用于处理不同类型输入和输出的常见函数。你可以根据需要选择合适的函数来执行特定的输入和输出操作。

    对于输入输出的理解:

    当我们谈论文件操作时,输入和输出是关键的概念,在这里我将详细介绍,并且同时引入流的概念,以帮助你更好地理解。

    输入(Input):

    输入意味着从外部设备(例如键盘、网络、U盘)将数据传输到计算机的内存中。这就好像你在键盘上输入文字,这些文字被传送到计算机内存中以供程序使用。在文件操作中,输入通常涉及从文件中读取数据并将其加载到内存中,以便我们的程序可以处理这些数据。

    输出(Output):

    输出则是相反的过程,它将内存中的数据传输到外部设备(例如屏幕、网络、U盘)。这就像你的程序将结果显示在屏幕上或将文件保存到U盘中。在文件操作中,输出通常涉及将内存中的数据写入文件,以便我们可以永久地保存或与其他人分享这些数据。

    流的概念:

    流是一个非常有用的概念,它类似于数据的管道,用于将数据从一个地方传送到另一个地方。我们可以把流看作是连接内存和外部设备的桥梁。流可以有不同的类型,如输入流和输出流。

    • 输入流(Input Stream):这是一个通往内存的管道,它允许数据从外部设备(如文件)流向内存。你可以把它想象成一个数据的流水线,将数据加载到程序中。

    • 输出流(Output Stream):这是一个通往外部设备的管道,它允许数据从内存流向外部设备。你可以把它看作是一个将数据输出到文件或显示器的通道。

    在文件操作中,我们使用输入流来读取文件中的数据并将其加载到程序中,然后使用输出流将程序中的数据写入到文件或其他输出设备。这个流的概念使得文件操作更加抽象和灵活,因为它让我们能够轻松地在不同的输入和输出设备之间传输数据,而无需过多关注底层细节。

    因此,简而言之,输入是将数据传入内存,输出是将数据传出内存,而流是在这两者之间起到连接作用的桥梁,使数据能够在内存和外部设备之间流动。这些概念是文件操作中非常重要的基础。

    简而言之:

    • 输入是将数据从外部设备(磁盘、屏幕、网络、U盘等)读取到内存。
    • 输出是将数据从内存写入到外部设备(磁盘、屏幕、网络、U盘等)。
    • 流是内存与外部设备之间的管道,用于在两者之间传输数据。

    PS:
    任何一个c程序默认打开3个流:

    1. 标准输入流(stdin):表示程序的输入数据流,默认情况下通常关联到键盘输入。当你使用 scanf或 getchar 等函数时,它们从标准输入流中读取数据。

    2. 标准输出流(stdout):表示程序的输出数据流,默认情况下通常关联到屏幕。当你使用 printf 或 putchar等函数时,它们将数据写入标准输出流,显示在屏幕上。

    3. 标准错误流(stderr):也是一个输出流,默认情况下通常关联到屏幕。它用于输出程序的错误消息和诊断信息。通常,它与标准输出流不同,这样可以将错误信息与正常输出区分开来。

    字符输入输出:

    字符输入函数fgetc:

    fgetc 函数是C标准库中的一个字符输入函数,用于从指定的输入流中读取一个字符。下面是有关 fgetc 函数的详细信息:

    函数原型:

    int fgetc(FILE *stream);
    
    • 1

    参数:

    • stream:一个指向 FILE 结构的指针,表示要从中读取字符的输入流。

    返回值:

    • 如果成功读取字符,fgetc 返回读取的字符作为整数(int 类型)。如果达到文件结束(EOF),则返回 EOF(通常是 -1)以表示文件结束或读取错误。

    示例用法:

    #include 
    
    int main() {
        FILE *file;
        int ch;
        
        // 打开一个文件用于读取
        file = fopen("example.txt", "r");
        
        if (file == NULL) {
            printf("无法打开文件\n");
            return 1;
        }
        
        // 从文件中逐个字符读取并输出
        while ((ch = fgetc(file)) != EOF) {
            putchar(ch);
        }
        
        // 关闭文件
        fclose(file);
        
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    在这个示例中,我们打开了一个文件以供读取,并使用 fgetc 函数逐个字符地读取文件中的内容。读取到的字符会被输出到屏幕上。EOF 用于表示文件的末尾。读取完成后,我们使用 fclose 函数关闭文件。

    总之,fgetc 允许你从指定的输入流中一个字符一个字符地读取数据,直到文件结束。这在文本处理和文件解析等任务中非常有用。

    字符输入函数fputc:

    fputc 函数是C标准库中的一个字符输出函数,用于将一个字符写入指定的输出流。下面是有关 fputc 函数的详细信息:

    函数原型:

    int fputc(int character, FILE *stream);
    
    • 1

    参数:

    • character:要写入输出流的字符,以整数形式表示。
    • stream:一个指向 FILE 结构的指针,表示要写入的输出流。

    返回值:

    • 如果成功写入字符,fputc 返回写入的字符(character 参数的值)作为整数。
    • 如果写入失败,它返回 EOF(通常是 -1)以表示错误。

    示例用法:

    #include 
    
    int main() {
        FILE *file;
        int ch;
        
        // 打开一个文件以供写入
        file = fopen("output.txt", "w");
        
        if (file == NULL) {
            printf("无法打开文件\n");
            return 1;
        }
        
        // 写入字符到文件中
        ch = 'A';
        if (fputc(ch, file) != EOF) {
            printf("字符写入成功\n");
        } else {
            printf("写入字符时发生了错误\n");
        }
        
        // 关闭文件
        fclose(file);
        
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    在这个示例中,我们打开了一个文件以供写入,并使用 fputc 函数将字符 'A' 写入文件中。如果写入成功,它将返回 'A' 的整数值,表示写入成功。

    总之,fputc 允许你将字符写入指定的输出流,以便将数据写入文件或其他输出设备。这在文件创建和数据记录等任务中非常有用。

    文本行输入输出:

    文本行输入和输出是文件操作中常用的方式,它们允许你逐行读取和写入文本数据。在C语言中,常见的文本行输入输出函数包括 fgetsfputs

    文本行输入函数 fgets

    fgets 函数用于从指定的输入流中读取一行文本(包括换行符 \n),并将其存储为字符串。下面是有关 fgets 函数的详细信息:

    函数原型:

    char *fgets(char *str, int num, FILE *stream);
    
    • 1

    参数:

    • str:指向字符数组的指针,用于存储读取的文本行。
    • num:要读取的最大字符数(包括终止符 \0)。
    • stream:一个指向 FILE 结构的指针,表示要从中读取文本行的输入流。

    返回值:

    • 如果成功读取一行文本,fgets 返回指向存储文本的字符串的指针(即 str 参数的值)。
    • 如果到达文件结束(EOF)或发生错误,它返回 NULL 指针。

    示例用法:

    #include 
    
    int main() {
        FILE *file;
        char line[100]; // 用于存储读取的文本行
        
        // 打开一个文本文件以供读取
        file = fopen("text.txt", "r");
        
        if (file == NULL) {
            printf("无法打开文件\n");
            return 1;
        }
        
        // 从文件中读取一行文本
        if (fgets(line, sizeof(line), file) != NULL) {
            printf("读取的文本行:%s", line);
        } else {
            printf("读取文本行时发生了错误或到达文件末尾\n");
        }
        
        // 关闭文件
        fclose(file);
        
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    文本行输出函数 fputs

    fputs 函数用于将一个字符串写入指定的输出流,通常是一行文本。下面是有关 fputs 函数的详细信息:

    函数原型:

    int fputs(const char *str, FILE *stream);
    
    • 1

    参数:

    • str:要写入输出流的字符串。
    • stream:一个指向 FILE 结构的指针,表示要写入文本行的输出流。

    返回值:

    • 如果成功写入字符串,fputs 返回非负整数值。
    • 如果写入失败,它返回 EOF(通常是 -1)以表示错误。

    示例用法:

    #include 
    
    int main() {
        FILE *file;
        
        // 打开一个文本文件以供写入
        file = fopen("output.txt", "w");
        
        if (file == NULL) {
            printf("无法打开文件\n");
            return 1;
        }
        
        // 将字符串写入文件
        if (fputs("这是一行文本。\n", file) != EOF) {
            printf("字符串写入成功\n");
        } else {
            printf("写入字符串时发生了错误\n");
        }
        
        // 关闭文件
        fclose(file);
        
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    总之,fgets 允许你从输入流中读取一行文本,而 fputs 允许你将字符串写入输出流,通常是一行文本。这对于处理文本文件和日志记录等任务非常有用。

    格式化输入输出:

    格式化输入和输出是C语言中的一种强大的功能,它允许你以特定的格式读取和写入数据。这对于处理各种数据类型、控制输出外观以及进行数据解析非常有用。在C语言中,常见的格式化输入输出函数包括 fscanffprintf

    格式化输入函数 fscanf

    fscanf 函数用于从指定的输入流中按照特定格式读取数据并将其赋值给变量。下面是有关 fscanf 函数的详细信息:

    函数原型:

    int fscanf(FILE *stream, const char *format, ...);
    
    • 1

    参数:

    • stream:一个指向 FILE 结构的指针,表示要从中读取数据的输入流。
    • format:一个格式字符串,指定了如何解析输入数据的规则。
    • ...:格式化输入的变量列表,用于存储解析后的数据。

    返回值:

    • 如果成功读取数据,fscanf 返回成功读取的变量数量。如果达到文件结束(EOF)或发生错误,它返回 EOF(通常是 -1)。

    示例用法:

    #include 
    
    int main() {
        FILE *file;
        int age;
        char name[50];
        
        // 打开一个文本文件以供读取
        file = fopen("data.txt", "r");
        
        if (file == NULL) {
            printf("无法打开文件\n");
            return 1;
        }
        
        // 从文件中按照特定格式读取数据
        if (fscanf(file, "姓名:%s 年龄:%d", name, &age) == 2) {
            printf("姓名:%s\n年龄:%d\n", name, age);
        } else {
            printf("读取数据时发生了错误或到达文件末尾\n");
        }
        
        // 关闭文件
        fclose(file);
        
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    格式化输出函数 fprintf

    fprintf 函数用于按照特定格式将数据写入指定的输出流。下面是有关 fprintf 函数的详细信息:

    函数原型:

    int fprintf(FILE *stream, const char *format, ...);
    
    • 1

    参数:

    • stream:一个指向 FILE 结构的指针,表示要写入数据的输出流。
    • format:一个格式字符串,指定了如何格式化输出数据的规则。
    • ...:格式化输出的变量列表,用于提供要输出的数据。

    返回值:

    • 如果成功写入数据,fprintf 返回写入的字符数量。如果写入失败,它返回负数值以表示错误。

    示例用法:

    #include 
    
    int main() {
        FILE *file;
        int age = 30;
        char name[] = "John Doe";
        
        // 打开一个文本文件以供写入
        file = fopen("output.txt", "w");
        
        if (file == NULL) {
            printf("无法打开文件\n");
            return 1;
        }
        
        // 将数据按照特定格式写入文件
        fprintf(file, "姓名:%s\n年龄:%d\n", name, age);
        
        // 关闭文件
        fclose(file);
        
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    总之,格式化输入函数 fscanf 允许你从输入流中按照特定格式读取数据,而格式化输出函数 fprintf 允许你将数据按照特定格式写入输出流。这些函数非常有用,特别是在处理配置文件、日志文件和用户输入时,因为它们允许你以一种结构化和可控制的方式处理数据。

    二进制输入输出:

    二进制输入输出是C语言中的一种重要功能,它允许你以二进制格式读取和写入数据,而不是文本格式。这对于处理二进制文件、图像、音频和其他非文本数据非常有用。在C语言中,常见的二进制输入输出函数包括 freadfwrite

    二进制输入函数 fread

    fread 函数用于从指定的输入流中读取二进制数据。下面是有关 fread 函数的详细信息:

    函数原型:

    size_t fread(void *ptr, size_t size, size_t count, FILE *stream);
    
    • 1

    参数:

    • ptr:指向目标缓冲区的指针,用于存储读取的数据。
    • size:每个数据项的字节数。
    • count:要读取的数据项数量。
    • stream:一个指向 FILE 结构的指针,表示要从中读取数据的输入流。

    返回值:

    • fread 返回实际读取的数据项数量。如果读取成功,该值等于 count 参数;如果读取失败或到达文件末尾,该值可能小于 count

    示例用法:

    #include 
    
    struct Student {
        char name[50];
        int age;
    };
    
    int main() {
        FILE *file;
        struct Student student;
        
        // 打开一个二进制文件以供读取
        file = fopen("students.dat", "rb");
        
        if (file == NULL) {
            printf("无法打开文件\n");
            return 1;
        }
        
        // 从文件中读取结构体数据
        if (fread(&student, sizeof(struct Student), 1, file) == 1) {
            printf("姓名:%s\n年龄:%d\n", student.name, student.age);
        } else {
            printf("读取数据时发生了错误或到达文件末尾\n");
        }
        
        // 关闭文件
        fclose(file);
        
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    二进制输出函数 fwrite

    fwrite 函数用于将二进制数据写入指定的输出流。下面是有关 fwrite 函数的详细信息:

    函数原型:

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

    参数:

    • ptr:指向要写入的数据的指针。
    • size:每个数据项的字节数。
    • count:要写入的数据项数量。
    • stream:一个指向 FILE 结构的指针,表示要写入数据的输出流。

    返回值:

    • fwrite 返回实际成功写入的数据项数量。如果写入成功,该值等于 count 参数;如果写入失败,该值可能小于 count

    示例用法:

    #include 
    
    struct Student {
        char name[50];
        int age;
    };
    
    int main() {
        FILE *file;
        struct Student student = {"Alice", 25};
        
        // 打开一个二进制文件以供写入
        file = fopen("students.dat", "wb");
        
        if (file == NULL) {
            printf("无法打开文件\n");
            return 1;
        }
        
        // 将结构体数据写入文件
        if (fwrite(&student, sizeof(struct Student), 1, file) == 1) {
            printf("数据成功写入文件\n");
        } else {
            printf("写入数据时发生了错误\n");
        }
        
        // 关闭文件
        fclose(file);
        
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    总之,二进制输入函数 fread 允许你从输入流中读取二进制数据,而二进制输出函数 fwrite 允许你将二进制数据写入输出流。这对于处理二进制文件、存储复杂数据结构和进行数据传输非常有用。要特别注意的是,在二进制输入输出中,数据以其原始二进制形式进行读取和写入,不会进行字符编码或解码。

    对比一组函数:

    scanf/fscanf/sscanf
    printf/fprintf/sprintf
    
    • 1
    • 2

    这一组函数包括 scanffscanfsscanf 用于输入,以及 printffprintfsprintf 用于输出。它们都用于格式化输入和输出,但在用法上有一些重要的区别。

    输入函数:scanffscanfsscanf

    1. scanf

      • 用法:scanf 从标准输入中读取数据,通常用于从键盘输入。
      • 示例:scanf("%d", &number);
    2. fscanf

      • 用法:fscanf 从指定的输入流中读取数据,可以用于读取文件等。
      • 示例:fscanf(file, "%d", &number);
    3. sscanf

      • 用法:sscanf 从字符串中解析数据,将字符串作为输入源。
      • 示例:sscanf(inputString, "%d", &number);

    输出函数:printffprintfsprintf

    1. printf

      • 用法:printf 将格式化的输出写入标准输出(通常是屏幕)。
      • 示例:printf("The number is: %d\n", number);
    2. fprintf

      • 用法:fprintf 将格式化的输出写入指定的输出流,通常是文件。
      • 示例:fprintf(file, "The number is: %d\n", number);
    3. sprintf

      • 用法:sprintf 将格式化的输出写入字符串缓冲区,将字符串作为输出源。
      • 示例:sprintf(outputString, "The number is: %d", number);

    对比和使用场景:

    • scanf 用于从标准输入读取用户输入,通常用于控制台程序,但要注意输入验证,以防止错误输入。

    • fscanf 用于从文件或其他输入流中读取数据,适用于读取文件内容或其他非键盘输入。

    • sscanf 用于从字符串中解析数据,通常用于处理字符串中的特定格式数据。

    • printf 用于将格式化的输出写入标准输出,用于向控制台输出信息。

    • fprintf 用于将格式化的输出写入文件或其他输出流,适用于将信息写入文件。

    • sprintf 用于将格式化的输出写入字符串缓冲区,可用于构建字符串。

    选择哪个函数取决于你的需求和输入输出的来源和去向。要确保格式化字符串与实际数据类型匹配,以防止错误或异常。此外,要小心处理格式化字符串中的特殊字符,以防止潜在的安全问题。

    sprintf和sscanf的用处:

    sprintfsscanf 是C语言中非常有用的函数,它们分别用于将数据格式化为字符串和从字符串中解析数据。下面分别介绍它们的用处:

    sprintf 的用处:

    sprintf 用于将格式化的数据转化为字符串,将其存储在一个字符数组中。具体用途如下:

    1. 构建字符串:你可以使用 sprintf 来构建字符串,将各种数据类型(整数、浮点数、字符串等)按照特定的格式组合成一个字符串。这在生成日志消息、报告、邮件内容等文本时非常有用。
    int value = 42;
    char message[50];
    sprintf(message, "The value is: %d", value);
    // message 变量现在包含 "The value is: 42" 这个字符串
    
    • 1
    • 2
    • 3
    • 4
    1. 将数据格式化为字符串:你可以使用 sprintf 来将数据格式化为字符串,以便将其输出或保存到文件中。
    double price = 19.99;
    char formattedPrice[20];
    sprintf(formattedPrice, "Price: $%.2lf", price);
    // formattedPrice 变量现在包含 "Price: $19.99" 这个字符串
    
    • 1
    • 2
    • 3
    • 4
    1. 将多个值组合为一个字符串:你可以使用 sprintf 将多个值组合到一个字符串中,以便以特定的格式输出或记录。
    int year = 2023;
    int month = 9;
    int day = 15;
    char date[15];
    sprintf(date, "%d-%02d-%02d", year, month, day);
    // date 变量现在包含 "2023-09-15" 这个字符串
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    sscanf 的用处:

    sscanf 用于从一个字符串中解析数据,将其按照特定的格式提取并存储到变量中。具体用途如下:

    1. 从字符串中提取数据:你可以使用 sscanf 从字符串中提取数据,这对于处理包含特定格式的字符串非常有用。例如,你可以解析日期字符串并将其存储为年、月和日的整数。
    char dateStr[] = "2023-09-15";
    int year, month, day;
    sscanf(dateStr, "%d-%d-%d", &year, &month, &day);
    // year 变量现在包含 2023,month 变量包含 9,day 变量包含 15
    
    • 1
    • 2
    • 3
    • 4
    1. 解析复杂数据sscanf 可用于解析包含多个数据项的字符串,甚至可以处理更复杂的数据结构。例如,你可以解析CSV格式的数据行并将其存储为不同的变量。
    char csvLine[] = "John,Doe,30";
    char firstName[50], lastName[50];
    int age;
    sscanf(csvLine, "%[^,],%[^,],%d", firstName, lastName, &age);
    // firstName 变量现在包含 "John",lastName 变量包含 "Doe",age 变量包含 30
    
    • 1
    • 2
    • 3
    • 4
    • 5
    1. 数据验证和转换sscanf 还可用于验证输入字符串是否符合预期的格式,以及将数据从字符串中转换为适当的数据类型。这在处理用户输入或文件中的数据时很有用。
    char userInput[50];
    int integerValue;
    if (sscanf(userInput, "%d", &integerValue) == 1) {
        // 用户输入的字符串成功转换为整数
    } else {
        // 用户输入的字符串无法转换为整数
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    总之,sprintf 用于将数据格式化为字符串,而 sscanf 用于从字符串中解析数据。它们是C语言中强大的工具,可用于处理和操作字符串和数据。

    总结:

    最直观的例子是:当我们做前后端传值的时候,前端的数据可能会以字符串的格式传回数据,这个时候我们就可以用到sscanf将字符串数据转换为格式化的数据,注意:这里的字符串中的数据必须以空格分割,要不然转换不了!
    下面举一个代码的例子:

    #include 
    
    int main() {
        // 假设前端传递的字符串数据
        char dataFromFrontend[] = "John 30 175.5";
    
        char name[50];
        int age;
        double height;
    
        // 使用 sscanf 解析字符串数据
        int result = sscanf(dataFromFrontend, "%s %d %lf", name, &age, &height);
    
        if (result == 3) {
            printf("解析成功:\n");
            printf("姓名:%s\n", name);
            printf("年龄:%d\n", age);
            printf("身高:%.2lf\n", height);
        } else {
            printf("解析失败\n");
        }
    
        return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    四.文本文件和二进制文件:

    根据数据的组织形式,数据文件被称为文本文件或者二进制文件。
    数据在内存中以二进制的形式存储,如果不加转换的输出到外存,就是二进制文件。
    如果要求在外存上以ASCII码的形式存储,则需要在存储前转换。以ASCII字符的形式存储的文件就是文本文件。

    一个数据在内存中是怎么存储的呢?

    字符一律以ASCII形式存储,数值型数据既可以用ASCII形式存储,也可以使用二进制形式存储。
    如有整数10000,如果以ASCII码的形式输出到磁盘,则磁盘中占用5个字节(每个字符一个字节),而二进制形式输出,则在磁盘上只占4个字节(VS2013测试)。

    在这里插入图片描述
    在这里插入图片描述
    测试代码:

    #include 
    int main()
    {
    int a = 10000;
    FILE* pf = fopen("test.txt", "wb");
    fwrite(&a, 4, 1, pf);//二进制的形式写到文件中
    fclose(pf);
    pf = NULL;
    return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    最后

    十分感谢你可以耐着性子把它读完,如有错误,请告知,万分感谢,也祝各位读者技术越来越优秀,都有美好的未来和offer
    在这里插入图片描述

    最后如果觉得我写的还不错,请不要忘记点赞✌,收藏✌,加关注✌哦(。・ω・。)

    愿我们一起加油,奔向更美好的未来,愿我们从懵懵懂懂的一枚菜鸟逐渐成为大佬。加油,为自己点赞!

  • 相关阅读:
    怎样做终端安全防御?
    数据集笔记:上海摩拜共享单车
    计算机网络基础
    如何使用Docker安装最新版本的Redis并设置远程访问(含免费可视化工具)
    ESP32C3 PWM输出
    UE4 回合游戏项目 18- 退出战斗
    导入jdk源码并进行使用
    力扣20-有效的括号——栈实现
    驱动——platform驱动总线三种匹配方式
    websocket链接断开服务器报错java.io.EOFException解决办法
  • 原文地址:https://blog.csdn.net/m0_68865259/article/details/133232500