30天精通Linux系统编程-----第2天:标准I/O (建议收藏)

本文详细介绍了C语言标准输入输出库(stdio.h)中的各种函数,包括文件操作(如fopen、fclose、fread、fwrite、fflush、fseek)和字符流操作(如fgetc、putc、fgets、gets),以及格式化输入输出函数(printf、scanf、fprintf、sscanf)。通过示例演示了如何在实际编程中使用这些函数进行文件操作和数据读写。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

1.什么是标准I/O

2.标准I/O库函数

2.1 fopen,fclose函数

2.2 fread ,fwrite函数

2.3 fflush函数

2.4 fseek函数

2.5 fgetc,getc,getchar函数

2.6 fputc,putc,putchar函数

2.7 fgets,gets函数

demo


1.什么是标准I/O

        标准 I/O 库是一个 C 语言库,提供了一组函数和数据结构,用于进行标准输入(stdin)、标准输出(stdout)和标准错误(stderr)的操作,以及对文件进行 I/O 操作。这个库通常被称为 <stdio.h>,它提供了一种高级抽象的接口,使得程序员可以方便地进行输入和输出操作,而无需关心底层的系统调用和文件描述符

2.标准I/O库函数

         在启动程序时,有3个文件流是自动打开的。它们是stain、stdout和stderr。它们都是在staio.h头文件里定义的,分别代表着标准输入、标准输出和标准错误输出,与底层文件描述符0、1和2相对应。

2.1 fopen,fclose函数
FILE *fopen(const char *filename, const char *mode);
  • 参数:filename 是文件名,mode 是打开文件的模式(例如 "r" 表示只读,"w" 表示只写)。
  • 返回值:返回指向文件的指针,如果打开文件失败,则返回 NULL。
  • 功能:打开一个文件,并返回一个文件指针,后续可以使用该文件指针进行读写操作。

打开模式

  • "r"或"rb":以只读方式打开。
  • "w"或"wb":以写方式打开,并把文件长度截短为零。
  • "a"或"ab":以写方式打开,新内容追加在文件尾。
  • "r+"或"rb+"或"r+b":以更新方式打开(读和写)。
  • "w+"或"wb+"或"w+b":以更新方式打开,并把文件长度截短为零。
  • "a+"或"ab+"或"a+b":以更新方式打开,新内容追加在文件尾。

int fclose(FILE *stream);
  • 参数:stream 是指向要关闭的文件的指针。
  • 返回值:成功关闭文件返回 0,如果发生错误则返回 EOF。
  • 功能:关闭一个打开的文件,并释放与该文件相关的资源。

2.2 fread ,fwrite函数
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
  • 参数:ptr 是要读取数据的缓冲区指针,size 是每个数据项的大小,nmemb 是要读取的数据项数目,stream 是指向要读取的文件的指针。
  • 返回值:返回实际读取的数据项数目,如果发生错误或到达文件尾部,则返回值可能小于 nmemb
  • 功能:从指定文件中读取数据到指定的缓冲区中。
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
  • 参数:ptr 是要写入的数据的缓冲区指针,size 是每个数据项的大小,nmemb 是要写入的数据项数目,stream 是指向要写入的文件的指针。
  • 返回值:返回实际写入的数据项数目,如果发生错误,则返回值可能小于 nmemb
  • 功能:将指定缓冲区中的数据写入到指定文件中。
2.3 fflush函数
int fflush(FILE *stream);
  • 参数:stream 是指向要刷新的流的指针。如果为 NULL,则刷新所有输出流。
  • 返回值:如果成功,则返回 0;如果出现错误,则返回 EOF。
  • 功能:刷新输出流的缓冲区,将缓冲区中的数据立即写入到文件中。
2.4 fseek函数
int fseek(FILE *stream, long int offset, int whence);
  • 参数:stream 是指向要设置位置的文件的指针,offset 是相对于 whence 的偏移量,whence 是指定偏移量的基准位置(SEEK_SET 表示文件开头,SEEK_CUR 表示当前位置,SEEK_END 表示文件末尾)。
  • 返回值:如果成功,则返回 0;如果出现错误,则返回非 0 值。
  • 功能:将文件的位置指针设置到指定位置。
2.5 fgetc,getc,getchar函数
int fgetc(FILE *stream);
  • 参数:stream 是指向要读取字符的文件的指针。
  • 返回值:返回读取的字符,如果到达文件末尾或者发生错误,则返回 EOF。
  • 功能:从指定文件中读取一个字符。
int getc(FILE *stream);
  • 参数:stream 是指向要读取字符的文件的指针。
  • 返回值:返回读取的字符,如果到达文件末尾或者发生错误,则返回 EOF。
  • 功能:从指定文件中读取一个字符。

int getchar(void);
  • 参数:无。
  • 返回值:返回读取的字符,如果到达文件末尾或者发生错误,则返回 EOF。
  • 功能:从标准输入流 stdin 中读取一个字符。

2.6 fputc,putc,putchar函数
int fputc(int c, FILE *stream);
  • 参数:c 是要写入的字符,stream 是指向要写入字符的文件的指针。
  • 返回值:如果成功,则返回写入的字符 c;如果出现错误,则返回 EOF。
  • 功能:将一个字符写入到指定文件中。
int putc(int c, FILE *stream);
  • 参数:c 是要写入的字符,stream 是指向要写入字符的文件的指针。
  • 返回值:如果成功,则返回写入的字符 c;如果出现错误,则返回 EOF。
  • 功能:将一个字符写入到指定文件中。
int putchar(int c);
  • 参数:c 是要写入的字符。
  • 返回值:如果成功,则返回写入的字符 c;如果出现错误,则返回 EOF。
  • 功能:将一个字符写入到标准输出流 stdout 中。
2.7 fgets,gets函数
char *fgets(char *s, int n, FILE *stream);
  • 参数:s 是指向用于存储读取的字符串的缓冲区的指针,n 是要读取的最大字符数,stream 是指向要读取的文件的指针。
  • 返回值:如果成功,则返回 s;如果到达文件末尾或者发生错误,则返回 NULL。
  • 功能:从指定文件中读取一行文本,包括换行符,然后将其存储到指定的缓冲区中。
char *gets(char *s);
  • 参数:s:是一个指向字符数组的指针,用于存储读取的字符串。这个字符数组必须足够大,以容纳输入的字符串,否则可能会发生缓冲区溢出。
  • 返回值:如果成功读取一行字符串,则返回指向字符串的指针,即返回值为 s;如果发生错误或者到达文件末尾,则返回 NULL。
  • 功能:从标准输入流 stdin 中读取一行字符串,并将其存储到指定的字符数组中。
2.8 printf,fprintf,sprintf函数
int printf(const char *format, ...);

  • 参数:
    • format:格式字符串,包含了要输出的文本以及指示如何格式化变量的控制字符。
    • ...:可变数量的参数,与格式字符串中的格式控制符匹配。
  • 返回值:返回输出的字符数(不包括字符串末尾的 null 字符),如果发生错误则返回负值。
  • 功能:将格式化的数据输出到标准输出设备(通常是终端)。
int fprintf(FILE *stream, const char *format, ...);
  • 参数:
    • stream:文件指针,指向要写入的文件。
    • format:格式字符串,包含了要输出的文本以及指示如何格式化变量的控制字符。
    • ...:可变数量的参数,与格式字符串中的格式控制符匹配。
  • 返回值:返回输出的字符数(不包括字符串末尾的 null 字符),如果发生错误则返回负值。
  • 功能:将格式化的数据输出到指定文件流中。
int sprintf(char *str, const char *format, ...);
  • 参数:
    • str:目标字符串的指针,用于存储格式化后的数据。
    • format:格式字符串,包含了要输出的文本以及指示如何格式化变量的控制字符。
    • ...:可变数量的参数,与格式字符串中的格式控制符匹配。
  • 返回值:返回写入到字符串中的字符数(不包括字符串末尾的 null 字符),如果发生错误则返回负值。
  • 功能:将格式化的数据写入到字符串中,而不是输出到文件或标准输出。
2.9 scanf,fscanf,sscanf函数
int scanf(const char *format, ...)
  • 参数:
    • format:格式字符串,包含了指示如何读取输入数据的格式控制符。
    • ...:可变数量的参数,用于接收读取的数据,参数的类型和数量要与格式字符串中的格式控制符匹配。
  • 返回值:返回成功读取并赋值的参数数目,如果没有成功匹配到任何参数,则返回 0。如果发生错误或者到达文件结束位置,则返回 EOF。
  • 功能:从标准输入流(通常是键盘)中读取格式化的数据。

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

  1. 格式字符串:scanf 函数的第一个参数是格式字符串,用于指定输入的格式。在格式字符串中,可以包含转换说明符(例如 %d%c%s 等)以及任何需要匹配的字符(例如空格、逗号等)。

  2. 输入变量:scanf 函数的后续参数是要接收输入值的变量的地址。这些变量必须是已经声明过的,并且类型要与对应的转换说明符相匹配。

  3. 空白字符:在格式字符串中,空白字符(空格、制表符、换行符等)通常用来分隔输入项。空白字符会在 scanf 函数执行时自动跳过。

  4. 输入缓冲区:scanf 函数从标准输入中读取字符时,会根据格式字符串中的转换说明符逐个读取字符,直到匹配整个格式字符串或遇到无法匹配的字符为止。输入的字符会存储在输入缓冲区中,直到被 scanf 函数读取完毕。

  5. 错误处理:scanf 函数返回成功读取并匹配的输入项数量。如果成功,返回值将是非负数,如果发生错误或到达输入流的末尾,返回值将是 EOF。因此,在使用 scanf 函数后,应该检查返回值以确保输入成功。

  6. 输入时的空白字符:scanf 函数在读取非字符串数据时会忽略输入项之间的空白字符。但是在读取字符串时,输入项之间的空白字符会被视为字符串的一部分。因此,在读取字符串之前,应该确保输入缓冲区中没有残留的空白字符,可以在格式字符串中使用空白字符(如空格或换行符)来跳过这些空白字符。

int fscanf(FILE *stream, const char *format, ...);
  • 参数:
    • stream:文件指针,指向要读取的文件。
    • format:格式字符串,包含了指示如何读取输入数据的格式控制符。
    • ...:可变数量的参数,用于接收读取的数据,参数的类型和数量要与格式字符串中的格式控制符匹配。
  • 返回值:返回成功读取并赋值的参数数目,如果没有成功匹配到任何参数,则返回 0。如果发生错误或者到达文件结束位置,则返回 EOF。
  • 功能:从指定文件流中读取格式化的数据。

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

  1. 文件指针:fscanf 函数的第一个参数是一个指向已打开文件的指针。这个文件指针必须是通过 fopen 或类似函数打开的,且必须处于可读取状态。

  2. 格式字符串:fscanf 函数的第二个参数是格式字符串,用于指定从文件中读取的格式。格式字符串中可以包含转换说明符(例如 %d%c%s 等)以及任何需要匹配的字符。

  3. 输入变量:fscanf 函数的后续参数是要接收从文件中读取到的值的变量的地址。这些变量必须是已经声明过的,并且类型要与对应的转换说明符相匹配。

  4. 空白字符:与 scanf 函数类似,fscanf 函数在读取非字符串数据时会忽略输入项之间的空白字符。但是在读取字符串时,输入项之间的空白字符会被视为字符串的一部分。因此,在读取字符串之前,应该确保文件指针处于正确的位置,以避免读取到意外的空白字符。

  5. 错误处理:fscanf 函数返回成功读取并匹配的输入项数量。如果成功,返回值将是非负数,如果发生错误或到达文件的末尾,返回值将是 EOF。因此,在使用 fscanf 函数后,应该检查返回值以确保读取成功。

  6. 字符串长度:当使用 %s 转换说明符读取字符串时,fscanf 函数会根据空白字符(如空格、制表符、换行符等)来确定字符串的结束位置。因此,在读取字符串时,应该确保字符串的长度不会超过目标变量的大小,以避免缓冲区溢出的情况。

int sscanf(const char *str, const char *format, ...);
  • 参数:
    • str:要读取的字符串。
    • format:格式字符串,包含了指示如何读取输入数据的格式控制符。
    • ...:可变数量的参数,用于接收读取的数据,参数的类型和数量要与格式字符串中的格式控制符匹配。
  • 返回值:返回成功读取并赋值的参数数目,如果没有成功匹配到任何参数,则返回 0。如果发生错误,则返回 EOF。
  • 功能:从指定的字符串中读取格式化的数据。

demo
#include <stdio.h>

int main() {
    char write[] = "Hello world";
    FILE* f = fopen("test.txt", "w+");
    fwrite(write, sizeof(char), sizeof(write) - 1, f); // 写入数据到文件
    printf("Write data:%s\n", write); // 输出写入的数据到控制台
    
    char readbuf[1024];
    fseek(f, 0, SEEK_SET);
    size_t num = fread(readbuf, 1, sizeof(readbuf) - 1, f); // 从文件读取数据
    if (num == 0)
        printf("Error reading from file.\n");
    else
        readbuf[num] = '\0';
    printf("Read data:%s\n", readbuf); // 输出读取的数据到控制台

    fseek(f, 0, SEEK_SET);
    int retc = fgetc(f); // 从文件读取一个字符
    if (retc == EOF)
        printf("End of file.\n");
    else
        printf("Read char:%c from fgetc\n", (char)retc);

    int retc2 = getc(f); // 从文件读取一个字符
    if (retc2 == EOF)
        printf("End of file.\n");
    else
        printf("Read char:%c from getc\n", (char)retc2);

    printf("Echo(please echo a char.):");
    char retc3 = getchar(); // 从标准输入读取一个字符
    printf("Read char:%c from getchar\n", retc3);

    int n;
    char c;
    printf("please echo an int and a char:"); // 提示用户输入一个整数和一个字符
    scanf("%d %c", &n, &c); // 从标准输入读取一个整数和一个字符
    printf("Read data:%d %c from scanf\n", n, c); // 输出读取的整数和字符到控制台
    
    char c2;
    fscanf(f, " %c", &c2); // 从文件读取一个字符
    printf("Read data:%c from fscanf\n", c2);

    const char *str = "Shenzhen";
    char arr[128];
    sscanf(str, "%s", arr); // 从字符串中读取数据
    printf("Read data:%s from sscanf\n", arr); 

    fclose(f);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值