文件追加模式:编写一个程序,向一个已存在的文件末尾追加内容。
知识点
文件打开模式
"r"
:只读;文件须存在。"w"
:写入;清空或新建。"a"
:追加;文件末尾写入。"a+"
:读/写追加。
追加(Append)机制
"a"
模式下,每次写入自动定位到末尾,无须fseek(fp, 0, SEEK_END)
;安全地在不改变已有数据的前提下增加内容。
行缓冲 I/O
fgets
安全读取带换行的一行,防止缓冲区溢出;fputs
直接写入字符串,不会再自动添加换行。
命令行参数处理
argc
/argv
获取用户输入的文件名;fprintf(stderr, …)
打印使用说明。
错误处理
检查
fopen
、fgets
、fputs
、fclose
的返回值;使用
perror
打印系统错误信息。
文件指针自动截断 vs 追加
区分
"w"
(截断)和"a"
(追加)的不同,用a
保留原有数据。
通过本练习,你将掌握文件追加模式的使用方法,以及在实际项目中如何安全、可靠地向已有文件追加新内容。
题目描述
编写一个 C 程序,实现向一个已存在的文本文件末尾追加内容,要求:
程序从命令行接收一个文件名参数;
以追加模式打开该文件;
提示用户输入多行文本,以单独一行只含
.
结束;将每行文本追加到文件末尾;
追加完毕后,重新打开文件并显示追加后的全部内容;
全过程需对文件操作的返回值做错误检查,并添加充分注释;
在文末总结本程序涉及的知识点。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>#define MAX_LEN 1024 //每行最大长度int main(int argc, char *argv[])
{if(argc != 2){fprintf(stderr,"用法:%s <已存在的文件名>\n",argv[0]);return EXIT_FAILURE;}const char *filename = argv[1];char buffer[MAX_LEN];//1.以“追加”模式打开文件//“a”只写追加,目标自动移动到文件末尾//若需要既读又写可用“a”FILE *fp = fopen(filename,"a");if(!fp){perror("打开文件追加失败");return EXIT_FAILURE;}//2.读取用户输入并追加到文件末尾printf("请输入要追加的内容(单独一行“.”结束):\n");while (1){if(!fgets(buffer,sizeof buffer,stdin)){perror("读取标准输入失败");fclose(fp);return EXIT_FAILURE;}//检测结束标志if(strcmp(buffer,".\n") == 0 || strcmp(buffer,".") == 0){break;}//将改行写入文件if(fputs(buffer,fp) == EOF){perror("写入文件失败");fclose(fp);return EXIT_FAILURE;}}//3.关闭追加if(fclose(fp) == EOF){perror("关闭追加流失败");return EXIT_FAILURE;}//4.重新以只读模式打开文件,显示全部内容fp = fopen(filename,"r");if(!fp){perror("打开文件读取失败");return EXIT_FAILURE;}printf("\n-------------追加后的文件内容-----------------\n");while(fgets(buffer,sizeof buffer,fp)){fputs(buffer,stdout);}printf("------------------------------------------------\n");if(fclose(fp) == EOF){perror("关闭读取流失败");return EXIT_FAILURE;}return EXIT_SUCCESS;}
代码讲解
命令行参数
int main(int argc, char *argv[])
argc
为参数个数,argv[0]
是程序名,argv[1]
应为目标文件名。if (argc!=2)
检查用户是否正确提供了一个参数。
追加模式打开
FILE *fp = fopen(filename, "a");
模式
"a"
:写操作总是从文件末尾开始,不会破坏原有内容;若文件不存在,
"a"
会创建新文件(要注意,本题要求文件已存在,可在打开后检查文件是否为空或在打开前用access()
验证存在性)。
读取并追加
while (fgets(buffer, sizeof buffer, stdin)) { if (strcmp(buffer, ".\n")==0 || strcmp(buffer,".")==0) break; fputs(buffer, fp); }
fgets
从标准输入读取一行,保留末尾\n
;遇到单独一行
.
立刻停止;fputs
写入至追加流,无需再fseek
——"a"
模式自动定位末尾。
关闭流与错误检查
if (fclose(fp) == EOF) perror("关闭追加流失败");
fclose
会刷新缓冲区并释放资源;始终检查返回值,捕获磁盘 I/O 错误。
重新打开并显示内容
fp = fopen(filename, "r"); while (fgets(buffer, sizeof buffer, fp)) fputs(buffer, stdout);
用
"r"
模式只读打开;再次用
fgets
/fputs
按行显示全部文本。
char buffer[MAX_LEN];
fgets(buffer, sizeof buffer, stdin);
功能
从指定的输入流(这里是标准输入stdin
)读取一行文本(或最多size–1
个字符),并把它存入buffer
。如果遇到换行符也会读入并存储在buffer
中,最后在末尾自动加上'\0'
。原型
char *fgets(char *s, int size, FILE *stream);
参数
char *s
—— 目标缓冲区地址,函数会把读到的字符写到s[0]
…int size
—— 缓冲区大小,最多读入size-1
个字符,保证有空间存放终止符'\0'
。FILE *stream
—— 要读取的文件流,stdin
表示标准输入。
返回值
成功时返回
s
;遇到 EOF 或发生错误时返回
NULL
。
相关/替代函数
fgets(buffer, n, fp)
:从任意FILE *fp
(文件)中读取。不要用已废弃的
gets
(不安全,会缓冲区溢出)。如果只想读一个字符,可用
int c = fgetc(stream);
。
fputs(buffer, fp);
功能
将以'\0'
结尾的字符串buffer
写入到指定的输出流fp
。不会自动添加换行符。原型
int fputs(const char *s, FILE *stream);
参数
const char *s
—— 要写入的 C 字符串的地址。FILE *stream
—— 目标文件流,可以是任何通过fopen
打开的文件,或标准输出stdout
、标准错误stderr
。
返回值
写入成功时返回 非负值(通常是字符数或任意非
EOF
)。失败时返回
EOF
。
相关/替代函数
puts(buffer)
:等价于fputs(buffer, stdout)
,并在末尾自动加'\n'
。fprintf(fp, "%s", buffer)
:更灵活,可混合格式化。fwrite(buffer, 1, strlen(buffer), fp)
:二进制写入。
while (fgets(buffer, sizeof buffer, fp)) {…
}
功能
和第 1 条完全相同,只不过这里stream
不是stdin
,而是你自己打开的文件流fp
。
用它可以逐行读取整个文件。常见用法
FILE *fp = fopen("file.txt", "r"); while (fgets(buffer, sizeof buffer, fp)) {// buffer 中包含一整行文本(包括换行符)process(buffer);//伪代码/示例里的占位符,意思是对刚读入的这一行文本做一些处理 } fclose(fp);
其他输入流
fgets(buffer, size, stdin)
:从键盘读行fgets(buffer, size, pipe_fp)
:从管道读行fgets(buffer, size, socket_fp)
(如果你把 socket 包装成 FILE*)
fputs(buffer, stdout);
功能
把字符串写到标准输出。等同于printf("%s", buffer)
,但比printf
略高效,因为无需解析格式串。常见用法
puts(buffer); // 自动加 '\n'
fputs(buffer, stdout); // 不加 '\n'
相关输出流
fputs(buffer, stderr)
:输出到标准错误,一般用于打印错误或日志。fputs(buffer, fp)
:输出到用户打开的任意文件流。
小结
fgets
:按行(或按长度)从一个FILE *
读字符串,保留'\n'
并自动加'\0'
。fputs
:把一个 C 字符串写入一个FILE *
,不附加'\n'
。常见流:
输入:
stdin
、文件流fp
;输出:
stdout
、stderr
、文件流fp
。
替代函数:
输入:
fgetc
、getc
、gets
(已废弃)、getline
(POSIX 扩展);输出:
puts
、printf
、fprintf
、fwrite
。
掌握这些函数及其参数后,你就能灵活地在控制台、文件或其他 I/O 流之间进行文本读写了。