文件追加模式:编写一个程序,向一个已存在的文件末尾追加内容。

知识点

  • 文件打开模式

    • "r":只读;文件须存在。

    • "w":写入;清空或新建。

    • "a":追加;文件末尾写入。

    • "a+":读/写追加。

  • 追加(Append)机制

    • "a" 模式下,每次写入自动定位到末尾,无须 fseek(fp, 0, SEEK_END)

    • 安全地在不改变已有数据的前提下增加内容。

  • 行缓冲 I/O

    • fgets 安全读取带换行的一行,防止缓冲区溢出;

    • fputs 直接写入字符串,不会再自动添加换行。

  • 命令行参数处理

    • argc/argv 获取用户输入的文件名;

    • fprintf(stderr, …) 打印使用说明。

  • 错误处理

    • 检查 fopenfgetsfputsfclose 的返回值;

    • 使用 perror 打印系统错误信息。

  • 文件指针自动截断 vs 追加

    • 区分 "w"(截断)和 "a"(追加)的不同,用 a 保留原有数据。

通过本练习,你将掌握文件追加模式的使用方法,以及在实际项目中如何安全、可靠地向已有文件追加新内容。

题目描述
编写一个 C 程序,实现向一个已存在的文本文件末尾追加内容,要求:

  1. 程序从命令行接收一个文件名参数;

  2. 追加模式打开该文件;

  3. 提示用户输入多行文本,以单独一行只含 . 结束;

  4. 将每行文本追加到文件末尾;

  5. 追加完毕后,重新打开文件并显示追加后的全部内容;

  6. 全过程需对文件操作的返回值做错误检查,并添加充分注释;

  7. 在文末总结本程序涉及的知识点。

#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;}

代码讲解

  1. 命令行参数

    int main(int argc, char *argv[])

    • argc 为参数个数,argv[0] 是程序名,argv[1] 应为目标文件名。

    • if (argc!=2) 检查用户是否正确提供了一个参数。

  2. 追加模式打开

    FILE *fp = fopen(filename, "a");

    • 模式 "a":写操作总是从文件末尾开始,不会破坏原有内容;

    • 若文件不存在,"a" 会创建新文件(要注意,本题要求文件已存在,可在打开后检查文件是否为空或在打开前用 access() 验证存在性)。

  3. 读取并追加

    while (fgets(buffer, sizeof buffer, stdin)) { if (strcmp(buffer, ".\n")==0 || strcmp(buffer,".")==0) break; fputs(buffer, fp); }

    • fgets 从标准输入读取一行,保留末尾 \n

    • 遇到单独一行 . 立刻停止;

    • fputs 写入至追加流,无需再 fseek——"a" 模式自动定位末尾。

  4. 关闭流与错误检查

    if (fclose(fp) == EOF) perror("关闭追加流失败");

    • fclose刷新缓冲区并释放资源;

    • 始终检查返回值,捕获磁盘 I/O 错误。

  5. 重新打开并显示内容

    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);
  • 参数

    1. char *s —— 目标缓冲区地址,函数会把读到的字符写到 s[0]

    2. int size —— 缓冲区大小,最多读入 size-1 个字符,保证有空间存放终止符 '\0'

    3. 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);
  • 参数

    1. const char *s —— 要写入的 C 字符串的地址。

    2. 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

    • 输出:stdoutstderr、文件流 fp

  • 替代函数

    • 输入:fgetcgetcgets(已废弃)、getline(POSIX 扩展);

    • 输出:putsprintffprintffwrite

掌握这些函数及其参数后,你就能灵活地在控制台、文件或其他 I/O 流之间进行文本读写了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/913853.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/913853.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

OneCode框架事件基础模型架构深度剖析与代码实现

一、整体架构概览 作为OneCode框架的事件核心模块&#xff0c;构建了一套跨浏览器、多终端兼容的事件驱动架构。该架构采用分层设计思想&#xff0c;从底层事件捕获到高层事件模拟&#xff0c;形成了完整的事件生命周期管理体系。整体架构可分为五个核心层次&#xff1a;事件捕…

Spring for Apache Pulsar->Reactive Support->Message Production

好消息&#xff1a;Spring for Apache Pulsar这两天刚刚升到2.0.0版本1. ReactivePulsarTemplate在Pulsar生产者端&#xff0c;Spring Boot自动配置提供了一个ReactivePulsarTemplate用于发布记录。该模板实现了一个名为ReactivePulse Operations的接口&#xff0c;并提供了通过…

AtCoder Beginner Contest 413

比赛链接如下&#xff1a;Denso Create Programming Contest 2025&#xff08;AtCoder Beginner Contest 413&#xff09; - AtCoder A - Content Too Large Problem Statement Takahashi has N items and one bag. The size of the i-th (1≤i≤N) item is Ai​, and the si…

Java学习---JVM(1)

JVM&#xff0c;即Java虚拟机&#xff0c;其是Java程序的运行环境&#xff0c;是Java技术的核心组成部分&#xff0c;本次就JVM的自动内存管理详细展开&#xff1a;JVM的内存区域分为2大类&#xff0c;即线程私有的和线程共享的&#xff0c;前者分为3大块&#xff0c;虚拟机栈、…

Qt去噪面板搭建

建立单选互斥性面板用于选择噪声属性// 创建去噪面板 QWidget* noisePanel new QWidget(); QVBoxLayout* mainLayout new QVBoxLayout(noisePanel); mainLayout->setContentsMargins(10, 10, 10, 10); mainLayout->setSpacing(15);// 去噪方法选择组QGroupBox* methodG…

无需公网IP的文件交互:FileCodeBox容器化部署技术解析

文章目录 前言1.Docker部署2.简单使用演示3. 安装cpolar内网穿透4. 配置公网地址5. 配置固定公网地址 前言 在数字化办公需求日益增长的今天&#xff0c;文件传输已成为职场协作的高频刚需。传统共享方式却饱受诟病&#xff1a;"需要安装哪些臃肿客户端&#xff1f;免费版…

1. http 有哪些版本,你是用的哪个版本,怎么查看

http 有哪些版本&#xff0c;你是用的哪个版本&#xff0c;怎么查看 总结&#xff1a;http 版本有 0.9/1.0/1.1/2.0/3.0&#xff0c;我们常用的是 1.1 和 2.0&#xff0c;使用 window.chrome.loadTimes() 获取 http 版本。 常见的 HTTP 版本 HTTP/0.9&#xff1a;最初的版本&am…

C# IIncrementalGenerator干点啥

生成器项目 得基于.Net Stander 2.0 重要&#xff1a;<IsRoslynComponent>true</IsRoslynComponent>、<IncludeBuildOutput>false</IncludeBuildOutput>、 <PackageReference Include"Microsoft.CodeAnalysis" Version"4.14.0&q…

在徐州网络中服务器租用与托管的优势

一、高性价比&#xff1a;徐州万恒提供多种配置的服务器供租用&#xff0c;满足不同企业和个人的业务需求&#xff0c;无论是初创企业追求低成本高效能&#xff0c;还是对性能有严苛要求的大型项目&#xff0c;都能找到合适的服务器型号&#xff0c;以极具竞争力的价格获取强大…

学习软件测试的第十四天(移动端)

一.常用的abd命令有哪些1.什么是 ADB&#xff1f;通俗解释&#xff1a; ADB 就像一个桥梁&#xff0c;让电脑能控制连接的手机&#xff0c;比如安装APP、抓日志、重启设备等。专业术语总结&#xff1a; ADB&#xff08;Android Debug Bridge&#xff09;是 Android SDK 提供的命…

04-ES6

let和const命令ES6中新增了let命令&#xff0c;用来声明变量&#xff0c;用法类似与varlet和var的不同&#xff1a;1、不存在变量提升 console.log(a); //Cannot access a before initializationlet a 100;2、同一个作用域不能重复定义同一个名称var c 20;let c 30;c…

基于GeographicLib实现测站地平坐标系(东北天)转地心固定坐标系XYZ

一、概述主要内容&#xff1a;本文基于GeographicLib开源库&#xff0c;实现了一个地理空间坐标转换功能&#xff0c;主要用于根据观测站的位置和目标的相对方位信息&#xff0c;计算目标在地球坐标系中的绝对位置。输入&#xff1a;观测站的经纬度坐标(纬度、经度、海拔高度)和…

若依框架去掉Redis

这篇文章全是按照我的实战操作来的&#xff0c;本文一是记录一下这个过程&#xff0c;二是帮助更多的人少走弯路。 接下来我们看实战&#xff1a;第一步毋庸置疑&#xff0c;就是找到配置文件application.yml里面大redis配置部分&#xff0c;直接注释掉 注意这里的data:这是否注…

【会员专享数据】2013-2024年我国省市县三级逐日SO₂数值数据(Shp/Excel格式)

之前我们分享过2013-2024年全国范围逐日SO₂栅格数据&#xff08;可查看之前的文章获悉详情&#xff09;!该数据来源于韦晶博士、李占清教授团队发布在国家青藏高原科学数据中心网站上的中国高分辨率高质量近地表空气污染物数据集。很多小伙伴拿到数据后反馈栅格数据不太方便使…

TCP SYN、UDP、ICMP之DOS攻击

一、实验背景 Dos攻击是指故意的攻击网络协议实现的缺陷或直接通过野蛮手段残忍地耗尽被攻击对象的资源&#xff0c;目的是让目标计算机或网络无法提供正常的服务或资源访问&#xff0c;使目标系统服务系统停止响应甚至崩溃。 二、实验设备 1.一台靶机Windows主机 2.增加一个网…

Ntfs!LfsUpdateLfcbFromRestart函数分析之根据Ntfs!_LFS_RESTART_AREA初始化Ntfs!_LFCB

第一部分&#xff1a;LfsUpdateLfcbFromRestart( ThisLfcb,FileSize,DiskRestartArea,FirstRestar1: kd> p Ntfs!LfsRestartLogFile0x317: f71fc8dd e820e5ffff call Ntfs!LfsUpdateLfcbFromRestart (f71fae02) 1: kd> t Ntfs!LfsUpdateLfcbFromRestart: f71fae0…

Qt开发:QtConcurrent介绍和使用

文章目录一、QtConcurrent 简介二、常用功能分类2.1 异步运行一个函数&#xff08;无返回值&#xff09;2.2 异步运行一个带参数的函数&#xff08;有返回值&#xff09;2.3 绑定类成员函数2.4 容器并行处理&#xff08;map&#xff09;三、线程池控制四、取消任务五、典型应用…

企业数据开发治理平台选型:13款系统优劣对比

本文将深入对比13款主流的数据指标管理平台&#xff1a;1.网易数帆&#xff1b; 2.云徙科技&#xff1b; 3.数澜科技&#xff1b; 4.用友数据中台&#xff1b; 5.龙石数据中台&#xff1b; 6.SelectDB&#xff1b; 7.得帆云 DeHoop 数据中台&#xff1b; 8.Talend&#xff1b; …

Java JDK 下载指南

Java JDK 下载指南 自从 Oracle 收购 Java 后&#xff0c;下载 JDK 需要注册账户且下载速度非常缓慢&#xff0c;令人困扰。 解决方案&#xff1a; 华为云提供了便捷的 JDK 下载镜像&#xff0c;访问速度快且无需注册&#xff1a; https://repo.huaweicloud.com/java/jdk/ 高…

QT数据交互全解析:JSON处理与HTTP通信

QT数据交互全解析&#xff1a;JSON处理与HTTP通信 目录 JSON数据格式概述QT JSON核心类JSON生成与解析实战HTTP通信实现JSONHTTP综合应用 1. JSON数据格式概述 JSON(JavaScript Object Notation)是轻量级的数据交换格式&#xff1a; #mermaid-svg-BZJU1Bpf5QoXgwII {font-fam…