【C语言标准库函数】标准输入输出函数详解[6]:字符文件读取写入

发布于:2025-02-13 ⋅ 阅读:(10) ⋅ 点赞:(0)

目录

一、字符文件写入函数

1.1. fputc函数

1.1.1. fputc函数简介

1.1.2. 使用场景

1.1.3. 注意事项

1.1.4. 示例

1.2. fputs函数

1.2.1. fputs函数简介

1.2.2. 使用场景

1.2.3. 注意事项

1.2.4. 示例

二、字符文件读取函数

2.1. fgetc函数

2.1.1. 函数简介

2.1.2. 使用场景

2.1.3. 注意事项

2.1.4. 示例

2.2. fgets()函数

2.2.1. 函数简介

2.2.2. 使用场景

2.2.3. 注意事项

2.2.4. 示例

三、文件读取函数fread、fscanf、fgets、fgetc总结

3.1. fread

3.2. fscanf

3.3. fgets

3.4. fgetc

3.5. 对比总结表

四、文件读取函数fwrite、fprintf、fputs、fputc总结

4.1. fwrite

4.2. fprintf

4.3. fputs

4.4. fputc

4.5. 对比总结表


在C语言中,字符文件的读取和写入是通过一组特定的标准库函数来实现的。这些函数允许程序以字符为单位处理文件内容,适用于文本文件的逐字符处理或二进制文件的低级操作。

一、字符文件写入函数

1.1. fputc函数

1.1.1. fputc函数简介

函数原型:

int fputc(int char, FILE *stream);
  • 功能:fputc函数是C语言标准库中的一个函数,全称为file output character,即文件输出字符函数。它的主要功能是将一个字符写入到指定的文件流中。
  • 参数
    • char:要写入的字符(虽然参数是int类型,但只有低8位被用作字符)。
    • stream:指向FILE对象的指针,该对象标识了要写入字符的流。
  • 返回值
    • 成功时,返回写入的字符。
    • 如果发生错误,则返回EOF

1.1.2. 使用场景

fputc函数的使用场景非常广泛,主要包括但不限于以下几个方面:

  • 文件写入:当需要将单个字符写入到文件中时,可以使用fputc函数。这对于生成日志文件、配置文件或任何需要字符级别操作的文件来说非常有用。
  • 字符处理:在处理字符数据时,如果需要逐个字符地写入到文件中,fputc函数是一个很好的选择。它可以与循环结构结合使用,以处理字符串或字符数组。
  • 标准输出重定向:在某些情况下,可能需要将标准输出(如printf函数的输出)重定向到文件中。虽然fputc本身不直接支持这种重定向,但可以通过修改文件指针来实现类似的效果。

1.1.3. 注意事项

在使用fputc函数时,需要注意以下几点:

  • 文件打开方式:在调用fputc之前,必须确保文件已经以适当的模式(如写入、追加等)打开,并且文件指针是有效的。
  • 字符编码:fputc函数写入的是字节,而不是字符。在处理多字节字符编码(如UTF-8)的文件时,需要特别注意字符的边界和编码方式。如果需要写入多字节字符,可能需要使用其他函数(如fwrite)或手动处理字符编码。
  • 错误处理:fputc函数在写入失败时会返回EOF。因此,在调用fputc后,应该检查其返回值以确定是否成功写入字符。如果需要更详细的错误信息,可以结合使用ferror函数。
  • 资源管理:在写入文件后,应使用fclose函数关闭文件,以释放相关资源。

1.1.4. 示例

以下是一个使用fputc函数向文件写入字符串的示例程序:

#include <stdio.h>  
  
int main() {  
    FILE *fp;  
    char *str = "Hello, World!";  
    int i = 0;  
  
    // 打开文件  
    fp = fopen("output.txt", "w");  
    if (fp == NULL) {  
        perror("Error opening file");  
        return -1;  
    }  
  
    // 逐字符写入文件  
    while (str[i] != '\0') {  
        fputc(str[i], fp);  
        i++;  
    }  
  
    // 关闭文件  
    fclose(fp);  
  
    return 0;  
}

首先使用fopen函数以写入模式打开文件"output.txt"。然后,使用一个while循环和fputc函数逐字符地将字符串"Hello, World!"写入到文件中。注意,循环的条件是字符串的当前字符不是空字符('\0'),这是C语言中字符串的结束标志。最后,使用fclose函数关闭文件。

1.2. fputs函数

1.2.1. fputs函数简介

函数原型:

int fputs(const char *str, FILE *stream)
  • 函数功能:fputs函数是C语言标准库中的一个函数,用于向指定的文件流中写入一个字符串(不包括空字符'\0')。
  • 参数:
    • str是指向要写入文件的字符串的指针;
    • stream是指向FILE对象的指针,该对象标识了要被写入字符串的流。
  • 返回值:
    • 如果成功写入字符串,文件的位置指针会自动后移,并且函数返回一个非负整数(通常是成功写入的字符数,但具体值依赖于实现,并不总是字符数)。
    • 如果发生错误,则返回EOF(符号常量,其值为-1)。

1.2.2. 使用场景

fputs函数的使用场景主要包括但不限于以下几个方面:

  • 文件写入:当需要将一个字符串写入到文件中时,fputs是一个直接且高效的选择。它特别适用于不需要处理字符串中每个字符的场景。
  • 日志记录:在软件开发中,经常需要将日志信息写入到文件中以便后续分析。fputs函数可以方便地用于此目的,因为它能够一次性写入整个日志字符串。
  • 配置文件生成:在生成配置文件时,fputs函数可以用来写入配置项的值,特别是当配置项的值是字符串时。

1.2.3. 注意事项

在使用fputs函数时,需要注意以下几点:

  • 文件打开方式:在调用fputs之前,必须确保文件已经以适当的模式(如写入、追加等)打开,并且文件指针是有效的。
  • 字符串结束符:fputs函数不会自动写入字符串结束符'\0'到文件中。因此,在读取由fputs写入的字符串时,需要知道字符串的实际长度或使用其他方式来确定字符串的结束位置。
  • 错误处理:fputs函数在发生错误时会返回EOF。因此,在调用fputs后,应该检查其返回值以确定是否成功写入字符串。如果需要更详细的错误信息,可以结合使用ferror函数。
  • 资源管理:在写入文件后,应使用fclose函数关闭文件,以释放相关资源。
  • 换行符:在不同的操作系统中,换行符的表示可能不同(如Windows中的'\r\n'和Unix/Linux中的'\n')。因此,在跨平台编写代码时,需要注意换行符的使用。

1.2.4. 示例

以下是一个使用fputs函数向文件写入字符串的示例程序:

#include <stdio.h>  
  
int main() {  
    FILE *fp;  
    char str[] = "Hello, World!\n";  
  
    // 打开文件  
    fp = fopen("output.txt", "w");  
    if (fp == NULL) {  
        perror("Error opening file");  
        return -1;  
    }  
  
    // 向文件写入字符串  
    fputs(str, fp);  
  
    // 关闭文件  
    fclose(fp);  
  
    return 0;  
}

首先使用fopen函数以写入模式打开文件"output.txt"。然后,使用fputs函数将字符串"Hello, World!\n"写入到文件中。最后,使用fclose函数关闭文件。运行该程序后,文件"output.txt"中将包含字符串"Hello, World!",并且由于字符串末尾包含换行符'\n',所以文件中该字符串后会有一个换行。

二、字符文件读取函数

2.1. fgetc函数

2.1.1. 函数简介

fgetc 函数是 C 语言标准库中的一个函数,用于从指定的文件流中读取下一个字符(一个无符号字符),并将其作为 int 类型的值返回。这个返回值之所以是 int 类型,是为了能够表示所有可能的字符值以及一个特殊的错误或文件结束指示符 EOFEOF 通常定义为 -1,但这是一个在 char 类型范围之外的值,因此使用 int 类型来接收 fgetc 的返回值是必要的。

函数原型:

int fgetc(FILE *stream);
  • 参数:stream:指向 FILE 对象的指针,该对象标识了要从中读取字符的文件流。
  • 返回值:

    • 成功时,返回读取到的字符的 ASCII 码值(转换为 int 类型)。
    • 如果到达文件末尾(EOF),则返回 EOF
    • 如果发生读取错误,也可能返回 EOF,但此时可以通过检查 ferror(stream) 或 feof(stream) 来区分这两种情况。不过,通常的做法是在循环中直接检查返回值是否为 EOF

2.1.2. 使用场景

fgetc 函数的使用场景非常广泛,主要包括但不限于以下几个方面:

  • 逐字符读取文件:当需要逐个处理文件中的字符时,可以使用 fgetc 函数。例如,实现文件的逐字符复制、查找文件中的特定字符或字符串等。
  • 大文件处理:在处理大文件时,一次性将整个文件加载到内存中可能不现实或效率低下。使用 fgetc 可以逐字符读取文件,从而显著降低内存消耗。
  • 字符串处理:虽然 fgetc 主要用于文件操作,但在某些情况下,也可以将其用于字符串处理,特别是当需要逐个访问字符串中的字符时。

2.1.3. 注意事项

在使用 fgetc 函数时,需要注意以下几点:

  • 文件打开方式:在调用 fgetc 之前,必须确保文件已经以适当的模式(如只读、读写等)打开,并且文件指针是有效的。
  • EOF 检测fgetc 在读取到文件末尾或发生错误时会返回 EOF。因此,在使用 fgetc 时,需要检查返回值是否为 EOF,以判断是否已经到达文件末尾或发生了错误。然而,仅检查 EOF 并不足以区分文件结束和读取错误,通常还需要结合 feof 和 ferror 函数进行判断。
  • 字符编码fgetc 读取的是字节,而不是字符。在处理多字节字符编码(如 UTF-8)的文件时,需要特别注意字符的边界和编码方式。
  • 资源管理:在读取文件后,应使用 fclose 函数关闭文件,以释放相关资源。

2.1.4. 示例

以下是一个使用 fgetc 函数逐字符读取文件并打印到控制台的示例程序:

#include <stdio.h>  
  
int main() {  
    FILE *fp;  
    int ch;  
  
    // 打开文件  
    fp = fopen("example.txt", "r");  
    if (fp == NULL) {  
        perror("Error opening file");  
        return -1;  
    }  
  
    // 逐字符读取文件  
    while ((ch = fgetc(fp)) != EOF) {  
        putchar(ch); // 将读取到的字符输出到控制台  
    }  
  
    // 关闭文件  
    fclose(fp);  
  
    return 0;  
}

首先使用 fopen 函数以只读模式打开文件 "example.txt"。然后,使用一个 while 循环和 fgetc 函数逐字符读取文件内容,直到到达文件末尾(即 fgetc 返回 EOF)。在循环体内,使用 putchar 函数将读取到的字符输出到控制台。最后,使用 fclose 函数关闭文件。

2.2. fgets()函数

2.2.1. 函数简介

函数原型: 

char *fgets(char *str, int n, FILE *stream);
  • 函数功能:fgets是C语言标准库中的一个函数,用于从指定的文件流中读取一行数据,并将其存储在指定的字符数组中。
  • 参数:
    • str是指向字符数组的指针,用于存储读取的字符串;
    • n是最大读取的字符数(包括结尾的空字符'\0');
    • stream是指向FILE对象的指针,指定从哪个流读取数据。
  • 返回值:
    • 成功时,fgets返回指向str的指针;
    • 如果到达文件末尾或发生错误,则返回NULL。

2.2.2. 使用场景

fgets函数的使用场景非常广泛,主要包括以下几个方面:

  • 文本文件读取:fgets函数特别适用于逐行读取文本文件的内容,如读取配置文件、日志文件等。
  • 用户输入处理:在交互式程序中,fgets函数可以用来从标准输入(stdin)读取用户输入的命令或数据,特别是当需要处理包含空格的字符串时。
  • 安全读取:由于fgets函数允许指定最大读取长度,因此它可以有效防止缓冲区溢出等安全问题。

2.2.3. 注意事项

在使用fgets函数时,需要注意以下几点:

  • 缓冲区大小:确保目标字符数组足够大,以容纳预期输入的最大长度加上终止符'\0'。如果输入的数据超过了指定的长度,fgets函数会在达到最大长度时停止读取,并在字符串末尾添加'\0'。
  • 换行符处理:fgets函数会将换行符(如果有的话)也读取到字符串中。如果需要在后续处理中去除换行符,可以使用strchr等函数查找并替换。
  • 返回值检查:在使用fgets函数后,应该检查其返回值以确定是否成功读取数据。如果返回NULL,可能是到达文件末尾或发生错误。可以通过feof和ferror函数进一步判断具体原因。
  • 文件打开状态:在调用fgets函数之前,必须确保文件已经以适当的模式(如读取模式)打开,并且文件指针是有效的。

2.2.4. 示例

以下是一个使用fgets函数从标准输入读取一行字符串的示例程序:

#include <stdio.h>  
  
int main() {  
    char str[100];  
    printf("请输入一行字符串: ");  
    if (fgets(str, sizeof(str), stdin) != NULL) {  
        // 去除换行符(如果存在)  
        char *newline = strchr(str, '\n');  
        if (newline != NULL) {  
            *newline = '\0';  
        }  
        printf("你输入的字符串是: %s\n", str);  
    } else {  
        printf("读取失败\n");  
    }  
    return 0;  
}

fgets函数从标准输入读取最多99个字符(包括结尾的空字符'\0')的字符串,并将其存储在str数组中。然后,程序检查是否读取到了换行符,并将其替换为字符串结束符'\0',以去除换行符。最后,程序输出用户输入的字符串。

三、文件读取函数fread、fscanf、fgets、fgetc总结

在C语言中,freadfscanffgetsfgetc是用于文件读取的四个重要函数,它们在使用场景和优势上各有不同。

3.1. fread

使用场景

  • 主要用于从文件中读取二进制数据或大块文本数据。
  • 适用于需要高效读取大量数据的场景,如图像处理、音频视频文件处理等。

优势

  • 可以一次性读取多个数据项,提高数据读取效率。
  • 允许指定读取的数据项大小、数量和缓冲区,灵活性高。
  • 不进行格式转换,直接读取二进制数据,适合处理非文本文件。

3.2. fscanf

使用场景

  • 从文件中按照指定格式读取数据。
  • 适用于需要读取具有特定格式的数据文件的场景,如读取配置文件、数据库文件等。

优势

  • 支持格式化输入,可以读取各种类型的数据,如整数、浮点数、字符串等。
  • 使用灵活,可以根据需要定义读取的格式。
  • 允许读取时跳过不需要的数据,实现数据的精确提取。

3.3. fgets

使用场景

  • 主要用于从文件中读取一行文本数据。
  • 适用于逐行处理文本文件的场景,如读取日志文件、源代码文件等。

优势

  • 读取一行数据时,会自动包含换行符(如果存在)。
  • 允许指定读取的最大字符数,防止缓冲区溢出。
  • 读取的字符串以null字符'\0'结尾,方便后续处理。

3.4. fgetc

使用场景

  • 用于从文件中读取单个字符。
  • 适用于需要逐个字符处理文件的场景,如文件内容分析、字符统计等。

优势

  • 逐个字符读取,灵活性强。
  • 可以轻松实现文件的逐行读取(通过循环读取直到换行符或文件末尾)。
  • 读取到的字符可以直接以ASCII码值的形式进行处理。

3.5. 对比总结表

函数名 使用场景 优势
fread 读取二进制数据或大块文本数据 高效读取多个数据项,灵活性高,适合处理非文本文件
fscanf 按照指定格式读取数据 支持格式化输入,读取类型多样,灵活性强
fgets 读取一行文本数据 包含换行符,防止缓冲区溢出,字符串处理方便
fgetc 读取单个字符 逐个字符处理,灵活性强,适合字符统计和分析

在选择使用哪个函数时,应根据具体的文件类型、数据格式和处理需求来决定。例如:

  • 对于二进制文件,通常选择fread
  • 对于需要按照特定格式读取数据的文件,可以选择fscanf
  • 对于逐行处理的文本文件,fgets是一个不错的选择;
  • 而对于需要逐个字符处理的场景,则可以使用fgetc

四、文件读取函数fwrite、fprintf、fputs、fputc总结

在C语言中,fwritefprintffputsfputc是用于文件写入的四个重要函数,它们在使用场景和优势上各有不同。

4.1. fwrite

使用场景

  • 主要用于将二进制数据或大块数据写入文件。
  • 适用于需要高效写入大量数据的场景,如图像处理、音频视频文件保存等。

优势

  • 直接将内存中的数据块写入文件,不进行任何字符转换或格式化,因此写入效率高。
  • 允许指定写入的数据项大小、数量和文件指针,提供了高度的灵活性。
  • 写入的数据保持其在内存中的原始格式,适用于二进制文件的处理。

4.2. fprintf

使用场景

  • 主要用于将格式化的数据以文本形式写入文件。
  • 适用于需要将数据以特定格式(如数字、字符串等)保存到文件中的场景,如配置文件、日志文件等。

优势

  • 支持格式化输出,可以灵活地将数据转换为文本字符串,并按指定格式写入文件。
  • 适用于需要数据以人类可读形式保存的场景。
  • 类似于printf函数,但可以将输出重定向到文件。

4.3. fputs

使用场景

  • 主要用于向文件中写入一个字符串(不包括结尾的空字符'\0')。
  • 适用于写入单行文本或少量文本数据的场景。

优势

  • 写入字符串时不需要指定长度,因为函数会自动在字符串末尾添加'\0'(但实际上不会写入文件)。
  • 操作简单,直接传入字符串和文件指针即可。
  • 适用于简单的文本文件写入操作。

4.4. fputc

使用场景

  • 主要用于向文件中写入一个字符。
  • 适用于需要逐个字符写入文件的场景,如字符计数、特定字符替换等。

优势

  • 逐个字符写入,提供了极高的灵活性。
  • 可以轻松地实现文件的逐字符处理或修改。
  • fgetc函数配合使用时,可以实现文件的逐字符读取和写入操作。

4.5. 对比总结表

以下是这四个函数在使用场景和优势上的对比总结:

函数名 使用场景 优势
fwrite 写入二进制数据或大块数据 高效、灵活,保持数据原始格式
fprintf 写入格式化文本数据 支持格式化输出,数据以人类可读形式保存
fputs 写入单行或少量文本数据 操作简单,适用于简单文本文件写入
fputc 写入单个字符 逐字符写入,提供高度灵活性

在选择使用哪个函数时,应根据具体的文件类型、数据格式和处理需求来决定。

  • 对于二进制文件或需要高效写入大量数据的场景,fwrite是更好的选择;
  • 对于需要格式化文本输出的场景,fprintf更为合适;
  • 对于简单的文本文件写入或少量文本数据的写入,fputs可能更为便捷;
  • 而对于需要逐字符处理文件的场景,fputc则提供了高度的灵活性。

C语言标准库中的输入输出函数为程序提供了丰富的数据交换手段,包括标准输入输出和文件输入输出。掌握这些函数对于C语言编程至关重要,它们使得数据的输入、处理和输出变得更加高效和灵活。