【C/C++】详解不同场景下的文件读写操作

2024-05-13 21:12

本文主要是介绍【C/C++】详解不同场景下的文件读写操作,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

🔗 运行环境:C/C++

🚩 撰写作者:左手の明天

🥇 精选专栏:《python》

🔥  推荐专栏:《算法研究》

🔐#### 防伪水印——左手の明天 ####🔐

💗 大家好🤗🤗🤗,我是左手の明天!好久不见💗

💗今天分享C/C++——不同场景下的文件读写操作💗

📆  最近更新:2024 年 05 月 13 日,左手の明天的第 330 篇原创博客

📚 更新于专栏:C/C++入门与进阶

🔐#### 防伪水印——左手の明天 ####🔐


目录

1、文件模式

1.1 文本模式

1.2 二进制模式

2、文件读写操作函数

2.1 读写操作函数

2.2 文件使用模式

3、写入数据到文件

4、从文件中读取数据

5、在文件中移动读取位置

6、获取当前读取位置

7、文件读取每一行字符串赋值给不同的人

7.1 解决方案1:使用fgets()函数

7.2 解决方案2:使用fgetc()函数

7.3 解决方案3:使用fscanf()函数

7.4 解决方案4:使用 POSIX 的 getline() 函数

7.5 注意

8、文件读取每一行字符串赋值给结构体

8.1 解决方案1:使用fgets()和sscanf()

8.2 解决方案2:使用fgets()和strtok()

9、工程实例


1、文件模式

C把文件看作是一系列的连续的字节,每个字节都能被单独读取。

C提供两种文件模式:文本模式和二进制模式。首先要区分文本内容和二进制内容,文本文件格式和二进制文件格式,及文件的文本模式和二进制模式。

1.1 文本模式

文本内容:如果文件最初使用的是二进制编码的字符(如ASCII码)表示文本,该文件就是文本文件,其中包含文本内容。

1.2 二进制模式

二进制内容:如果文件中的二进制值代表机器语言代码或数值数据,图片或者音乐编码,该文件就是二进制文件,其中包含二进制内容。

2、文件读写操作函数

2.1 读写操作函数

在C语言中,文件的读写操作主要是通过以下几个函数来实现的:

  1. fopen():打开一个文件

  2. fclose():关闭一个文件

  3. fread():读取文件中的数据

  4. fwrite():写入数据到文件中

  5. fseek():设置文件的读取位置

  6. ftell():获取文件的当前读取位置 

2.2 文件使用模式

文件使用方式       含义                                        如果指定文件不存在
" r " (只读)      为了输入数据,打开一个已经存在的文本文件        出错
" w " (只写)      为了输出数据,打开一个文本文件                 建立一个新的文件
" a " (追加)      向文本文件尾部添加数据                        建立一个新的文件
" rb "  (只读)    为了输入数据,打开一个二进制文件               出错
" wb "  (只写)    为了输出数据,打开一个二进制文件               建立一个新的文件
" ab "  (追加)    向一个二进制文件尾部添加数据                  出错
" r+ "  (读写)    为了读写,打开一个文本文件                    出错
" w+ "  (读写)    为了读写,建立一个新的文本文件                 建立一个新的文件
" a+ "  (读写)    打开一个文件,在文件尾部进行读写               建立一个新的文件
" rb+ " (读写)    打开一个二进制文件(读写)                     出错
" wb+ " (读写)    建立一个新的二进制文件(读写)                 建立一个新的文件
" ab+ " (读写)    打开一个二进制文件,在文件尾部进行读和写        建立一个新的文件

3、写入数据到文件

#include <stdio.h>int main() {FILE *fp = fopen("test.txt", "w"); // 以写入模式打开文件if(fp == NULL) {printf("Failed to open file\n");return -1;}char str[] = "Hello, World!";fwrite(str, sizeof(char), sizeof(str), fp); // 将字符串写入文件fclose(fp); // 关闭文件return 0;}

4、从文件中读取数据

#include <stdio.h>int main() {FILE *fp = fopen("test.txt", "r"); // 以读取模式打开文件if(fp == NULL) {printf("Failed to open file\n");return -1;}char str[20];fread(str, sizeof(char), sizeof(str), fp); // 读取文件内容printf("%s", str); // 打印读取的内容fclose(fp); // 关闭文件return 0;
}

5、在文件中移动读取位置

#include <stdio.h>int main() {FILE *fp = fopen("test.txt", "r"); // 以读取模式打开文件if(fp == NULL) {printf("Failed to open file\n");return -1;}char str[20];fread(str, sizeof(char), sizeof(str), fp); // 读取文件的前部分内容fseek(fp, 0, SEEK_SET); // 将读取位置移动到文件开头fread(str, sizeof(char), sizeof(str), fp); // 再次读取文件的全部内容printf("%s", str); // 打印读取的内容fclose(fp); // 关闭文件return 0;
}

6、获取当前读取位置

#include <stdio.h>int main() {FILE *fp = fopen("test.txt", "r"); // 以读取模式打开文件if(fp == NULL) {printf("Failed to open file\n");return -1;}char str[20];fread(str, sizeof(char), sizeof(str), fp); // 读取文件内容long position = ftell(fp); // 获取当前读取位置printf("Current file position: %ld\n", position);fclose(fp); // 关闭文件return 0;
}

以上代码提供了文件的基本写入和读取操作,并展示了如何在文件中移动读取位置以及如何获取当前的读取位置。在实际应用中,可能需要添加错误检查和处理,以确保文件操作的正确性和稳健性。

7、文件读取每一行字符串赋值给不同的人

在C语言中,可以使用各种方法来读取文件中的每一行并将其赋值给不同的人。以下是一些可能的解决方案:

7.1 解决方案1:使用fgets()函数

#include <stdio.h>
#include <stdlib.h>#define MAX_NAME_LENGTH 100int main() {FILE *file = fopen("names.txt", "r"); // 打开包含名字的文件if (file == NULL) {perror("Error opening file");return EXIT_FAILURE;}char line[MAX_NAME_LENGTH];int person = 1; // 假设我们从第一个人开始while (fgets(line, sizeof(line), file) != NULL) {// 移除换行符size_t len = strlen(line);if (len > 0 && line[len-1] == '\n') {line[len-1] = '\0';}// 根据person变量的值,将名字分配给不同的人// 这里只是打印出来,实际应用中可能需要其他逻辑printf("将名字 '%s' 分配给人#%d\n", line, person);// 更新person的值person++;}fclose(file); // 关闭文件return EXIT_SUCCESS;
}

这个代码假设有一个文件names.txt,里面包含了一行行的名字。程序会逐行读取这些名字,并将它们输出,就好像它们被分配给了不同的人。可以根据你的具体需求来修改分配逻辑。

7.2 解决方案2:使用fgetc()函数

#include <stdio.h>
#include <stdlib.h>int main() {FILE *file = fopen("file.txt", "r");if (file == NULL) {printf("Failed to open file\n");return 1;}int ch;while ((ch = fgetc(file)) != EOF) {printf("%c", (char)ch);}fclose(file);return 0;
}

7.3 解决方案3:使用fscanf()函数

#include <stdio.h>
#include <stdlib.h>int main() {FILE *file = fopen("file.txt", "r");if (file == NULL) {printf("Failed to open file\n");return 1;}char buffer[1024];while (fscanf(file, "%s", buffer) != EOF) {printf("%s\n", buffer);}fclose(file);return 0;
}

7.4 解决方案4:使用 POSIX 的 getline() 函数

#include <stdio.h>
#include <stdlib.h>int main() {FILE *file = fopen("file.txt", "r");if (file == NULL) {printf("Failed to open file\n");return 1;}char *line = NULL;size_t len = 0;ssize_t read;while ((read = getline(&line, &len, file)) != -1) {printf("Retrieved line of length %zu:\n", read);printf("%s", line);   }fclose(file);if (line)free(line);return 0;}

7.5 注意

在所有这些示例中,都假设文件名为"file.txt",并且文件存在于程序可以访问的同一目录中。如果文件位于不同的目录或者你想要指定不同的文件名,你需要更改"file.txt"为你的文件路径。另外,所有这些示例都假设文件中的每一行都不会超过1024个字符(包括null终止符)。如果你的文件中的行可能会非常长,你需要使用动态内存分配来读取这些行。

8、文件读取每一行字符串赋值给结构体

在C语言中,可以使用fgets()函数从文件中逐行读取字符串,然后使用sscanf()函数或者strtok()函数来解析每一行的内容,并将其存储到结构体中。

8.1 解决方案1:使用fgets()和sscanf()

#include <stdio.h>
#include <stdlib.h>typedef struct {char name[256];int age;
} Person;int main() {FILE *file = fopen("data.txt", "r");if (file == NULL) {printf("Failed to open file\n");return 1;}Person person;char line[256];while (fgets(line, sizeof(line), file)) {sscanf(line, "%s %d", person.name, &person.age);printf("Name: %s, Age: %d\n", person.name, person.age);}fclose(file);return 0;}

8.2 解决方案2:使用fgets()和strtok()

#include <stdio.h>
#include <string.h>
#include <stdlib.h>typedef struct {char name[256];int age;
} Person;int main() {FILE *file = fopen("data.txt", "r");if (file == NULL) {printf("Failed to open file\n");return 1;}Person person;char line[256];char *token;while (fgets(line, sizeof(line), file)) {token = strtok(line, " ");strcpy(person.name, token);token = strtok(NULL, " ");person.age = atoi(token);printf("Name: %s, Age: %d\n", person.name, person.age);}fclose(file);return 0;}
在这两个例子中,我们都假设文件"data.txt"的内容是这样的:

John Doe 30

Jane Smith 25

每一行包括姓名和年龄,并用空格分开。这两个例子都将文件中的每一行读取出来,然后将其赋值给Person结构体。

注意:这两个例子都没有进行错误检查,在实际使用时应该添加错误检查。例如,在调用fopen()、fgets()、sscanf()、strtok()以及atoi()时都可能出错,并且在出错时应该有恰当的处理方式。

9、工程实例

从键盘输入若干行字符,输入后把他们存储到一磁盘文件中。在从该文件中读出这些数据,将其中的小写字母转换成大写字母后在屏幕上输出。

#include <stdio.h>
#include<stdlib.h>struct node
{int data;struct node *next;
} ;typedef  struct  node  LNode;  
typedef  struct  node * LinkList;  
void CreateHeadList (LinkList  L);   
void OutputList(LinkList L);       
void DestroyList(LinkList  L);  void main()
{LinkList  head;          //定义一个LinkList 型的变量headif( ( head =(LNode *) malloc( sizeof(LNode) ) )==NULL)  {  printf("申请空间失败!");  exit(0);  }  head ->next=NULL;      //新建了一个空的单链表headCreateHeadList ( head);     //用头插法输入数据创建各结点OutputList(head);         //输出以head为头的链表各结点的值DestroyList (head);        //销毁以head为头的链表各结点
}/*定义头插法创建带头结点的单链表的函数*/
void CreateHeadList(LinkList  L)  
{	LNode *p;int  x, flag=-1;  scanf("%d",&x);while (x != flag){  if( ( p =(LNode *) malloc( sizeof(LNode) ) )==NULL)  {  printf("申请空间失败!");  exit(0);  }  p->data=x;      //x的数据类型为int型p->next=L->next;  L->next=p;  scanf("%d",&x);}  
} /*定义输出带头结点的单链表的函数*/
void OutputList(LinkList  head)  
{struct node *p;p=head->next ;           //取得链表的头指针while(p!=NULL)    //只要p指向的结点非空{printf("%d\t",p->data);       //p->data数据类型为int型p=p->next;                 //p指向该结点的下一个结点}printf("\n");
} /*定义销毁带头结点的单链表的函数*/
void  DestroyList (LinkList  head) 
{struct node  *p, *q;p=head;              //取得链表的头指针while(p!=NULL)       //只要p指向的结点非空{q=p->next;        //将p的下一个结点的地址保存在q中free(p);           //释放p指向的结点p=q;              }
}

这篇关于【C/C++】详解不同场景下的文件读写操作的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


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

相关文章

LiteFlow轻量级工作流引擎使用示例详解

《LiteFlow轻量级工作流引擎使用示例详解》:本文主要介绍LiteFlow是一个灵活、简洁且轻量的工作流引擎,适合用于中小型项目和微服务架构中的流程编排,本文给大家介绍LiteFlow轻量级工... 目录1. LiteFlow 主要特点2. 工作流定义方式3. LiteFlow 流程示例4. LiteF

CSS3中的字体及相关属性详解

《CSS3中的字体及相关属性详解》:本文主要介绍了CSS3中的字体及相关属性,详细内容请阅读本文,希望能对你有所帮助... 字体网页字体的三个来源:用户机器上安装的字体,放心使用。保存在第三方网站上的字体,例如Typekit和Google,可以link标签链接到你的页面上。保存在你自己Web服务器上的字

MySQL存储过程之循环遍历查询的结果集详解

《MySQL存储过程之循环遍历查询的结果集详解》:本文主要介绍MySQL存储过程之循环遍历查询的结果集,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录前言1. 表结构2. 存储过程3. 关于存储过程的SQL补充总结前言近来碰到这样一个问题:在生产上导入的数据发现

MyBatis ResultMap 的基本用法示例详解

《MyBatisResultMap的基本用法示例详解》在MyBatis中,resultMap用于定义数据库查询结果到Java对象属性的映射关系,本文给大家介绍MyBatisResultMap的基本... 目录MyBATis 中的 resultMap1. resultMap 的基本语法2. 简单的 resul

从基础到进阶详解Pandas时间数据处理指南

《从基础到进阶详解Pandas时间数据处理指南》Pandas构建了完整的时间数据处理生态,核心由四个基础类构成,Timestamp,DatetimeIndex,Period和Timedelta,下面我... 目录1. 时间数据类型与基础操作1.1 核心时间对象体系1.2 时间数据生成技巧2. 时间索引与数据

Mybatis Plus Join使用方法示例详解

《MybatisPlusJoin使用方法示例详解》:本文主要介绍MybatisPlusJoin使用方法示例详解,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,... 目录1、pom文件2、yaml配置文件3、分页插件4、示例代码:5、测试代码6、和PageHelper结合6

一文全面详解Python变量作用域

《一文全面详解Python变量作用域》变量作用域是Python中非常重要的概念,它决定了在哪里可以访问变量,下面我将用通俗易懂的方式,结合代码示例和图表,带你全面了解Python变量作用域,需要的朋友... 目录一、什么是变量作用域?二、python的四种作用域作用域查找顺序图示三、各作用域详解1. 局部作

Python主动抛出异常的各种用法和场景分析

《Python主动抛出异常的各种用法和场景分析》在Python中,我们不仅可以捕获和处理异常,还可以主动抛出异常,也就是以类的方式自定义错误的类型和提示信息,这在编程中非常有用,下面我将详细解释主动抛... 目录一、为什么要主动抛出异常?二、基本语法:raise关键字基本示例三、raise的多种用法1. 抛

Java SWT库详解与安装指南(最新推荐)

《JavaSWT库详解与安装指南(最新推荐)》:本文主要介绍JavaSWT库详解与安装指南,在本章中,我们介绍了如何下载、安装SWTJAR包,并详述了在Eclipse以及命令行环境中配置Java... 目录1. Java SWT类库概述2. SWT与AWT和Swing的区别2.1 历史背景与设计理念2.1.

C++作用域和标识符查找规则详解

《C++作用域和标识符查找规则详解》在C++中,作用域(Scope)和标识符查找(IdentifierLookup)是理解代码行为的重要概念,本文将详细介绍这些规则,并通过实例来说明它们的工作原理,需... 目录作用域标识符查找规则1. 普通查找(Ordinary Lookup)2. 限定查找(Qualif