当前位置: 首页 > news >正文

将文件读入C中的字符数组

当您使用 C 编程语言时,您可能会遇到一些需要将文件读入字符数组的问题,例如分析每个字符的频率,或者将所有句子的每个起始词从小写转换为大写,反之亦然。该解决方案非常简单,但对于不太了解文件读取或写入的人来说可能并不那么简单。因此,在这篇文章中,您可以逐步学习如何在 C 中将文件读入字符数组。

在 C 中打开文件

在 C 语言中打开文件的最简单和最流行的方法是使用以下格式的“fopen”函数:

file = fopen(file_name, "open_mode"); //open the "file-name" file and store the file pointer in the variable 'file'

“fopen”函数的模式参数指定打开文件的模式。该模式可以是以下之一:

  • “ r ”:打开文件进行读取。
  • “ w ”:将文件截断为零长度或创建一个用于写入的文件。
  • “ a ”:追加到文件或创建一个文件(如果不存在)进行写入。
  • “ r+ ”:打开文件进行读写。
  • “ w+ ”:将文件截断为零长度或创建一个用于读写的文件。
  • “ a+ ”:追加到文件或创建文件以供读写。

但由于某种原因,该文件可能无法正常打开。为了在发生此类情况时做好准备,您应该始终检查“fopen”函数的返回值,以确保在尝试读取或写入文件之前已成功打开文件。像这样:

// If 'fopen' returns NULL,  print an error message and exit the program 
if (file == NULL) {printf("Error: Failed to open file '%s'.\n", file_name);return 1;
}

逐字符读取文件内容

在读取文件之前,您必须有一个字符数组来存储文件内容。让我们这样做吧

char buffer[1000]; //Initialize a char array named 'buffer' with size of 1000

现在,是时候使用“fgetc”读取文件了。该函数每次调用都会读取文件中的一个字符,如果重复调用,它将读取后续的每个字符,直到结束。因此,我们可以使用 while 循环来使过程变得更容易。

int i = 0, c; //c is the intermediate variable, i is the increment variable
while ((c = fgetc(file)) != EOF) {//Read contents until it reach the end of the filebuffer[i] = c;i++;
}

上面的示例假设文件仅包含 ASCII 字符,并且文件大小小于 1000 个字符。

可调整大小的缓冲区

我们之前定义的缓冲区数组最多包含 1000 个字符。但在许多情况下,文件大小远大于此。我们可以通过将缓冲区变成可调整大小的缓冲区来解决这个问题。您可以通过 C 标准库提供的“malloc”、“realloc”和“realloc”函数使用动态内存分配。

char *buffer = NULL; // initialize buffer to NULL
int buffer_size = 0;
/*Open the file here*/
// Read file character by character
int c, i = 0;
while ((c = fgetc(file)) != EOF) {// If buffer is full, resize itif (i >= buffer_size) {buffer_size += 1000; // increase buffer size by 1000 bytesbuffer = realloc(buffer, buffer_size); // resize bufferif (buffer == NULL) {printf("Error: Memory allocation failed.\n");return 1;}}buffer[i] = c;i++;
}

我们在上面的代码片段中使用“realloc”函数,这被证明是有用的,因为文件大小通常是事先未知的。对于“malloc”和“calloc”函数,它们可用于将指定大小的内存块分配给变量。在此示例中,您可以像下面这样使用:

buffer = (char*)malloc(1000); //is the same as define char buffer[1000]

在此示例中,您可能不需要使用“malloc”和“calloc”。我们稍后会再次见到他们。

文件包含非 ASCII 字符

在 C 中,字符串表示为字节序列,这些字节的解释取决于字符编码。如果文件包含非 ASCII 字符,则需要使用支持这些字符的字符编码,例如 UTF-8 或 UTF-16。

对于这个问题,您应该使用可以处理多字节字符的函数,例如“fgetwc”和“fgetws”。这些函数一次分别读取一个宽字符 (wchar_t) 或一个宽字符串 (wchar_t*)。

以下是对代码的一些修改,以使其在文件包含非 ASCII 字符时正常工作:

wchar_t buffer[100];
// Open file for reading
file = fopen(filename, "r,ccs=UTF-8");
// Read file contents
wchar_t c;
int i = 0;
while ((c = fgetwc(file)) != WEOF) {buffer[i] = c;i++;
}

另外,请确保输入和输出流设置为正确的编码,以正确显示或操作字符。在 MacOS 和 Linux 等 Unix 操作系统上,为了确保输出编码为 UTF-8,您可以使用 'setlocale' 函数:

#include 
int main()
{setlocale(LC_ALL, "en_US.utf8");// your code herereturn 0;
}

在 Windows 上,您可以使用 '_setmode' 和 '_O_U8TEXT' 函数将输出编码设置为 UTF-8:

#include  //_O_U8TEXT
#include  //_setmode()
int main()
{_setmode(_fileno(stdout), _O_U8TEXT);// your code herereturn 0;
}

以下是包含越南语单词“Xin chào!”的文件示例 (Hello) 带重音符号(非 ASCII 字符),以 UTF-8 编码保存:

Xin chào!

这是我们的程序在在线 C 编译器上运行后的输出:

Xin chào!...Program finished with exit code 0
Press ENTER to exit console.

读取整个文件内容

如果您不熟悉 C,那么您可以跳过此步骤,但我仍然建议将其作为高级练习来阅读。我想介绍另一种方法来解决“如何在 C 中将文件读入字符数组”问题。新的思路是不再逐个字符地读取文件,而是整体读取文件,在读取之前确定文件大小。这是一个更复杂的解决方案,但也更有效。

首先,您应该定义常用变量:用于打开文件的文件指针和用于包含字符数组的缓冲区。请记住,您还需要文件大小:

FILE *fp;
long file_size;
char *buffer;

然后就可以打开文件来读取:

fp = fopen("example.txt", "r");

要了解文件的大小,可以使用“ftell”函数。它将告诉文件指针中当前位置的字节位置:
current_byte = ftell(fp);

但是等等,文件读取总是从文件的开头开始。没问题,“fseek”函数会将读取控件移动到文件中的不同位置:

fseek(fp, 0, SEEK_END);

您现在可以正确获取文件大小。之后,我们再次将读取控件设置为开头,开始读取文件内容:

file_size = ftell(fp);
rewind(fp); move the control to the file's beginning// Allocate memory for the char array
buffer = (char*) malloc(file_size + 1);

这里“malloc”函数的使用非常简单:分配内存来创建一个未初始化的 char 数组,其大小为 (file_size+1) 乘以 1 字节(char 类型的大小)。

如果您想使用“calloc”函数,请按以下步骤操作:

buffer = (char*) calloc(file_size + 1, sizeof(char));

“malloc”和“calloc”之间的主要区别在于,“malloc”仅分配内存而不初始化其内容,而“calloc”既分配内存又将内存初始化为零。使用“calloc”的主要优点是分配的内存已经被清零,如果您打算稍后将 char 数组用作字符串,这会很有帮助。

// Read the file into the char array
fread(buffer, file_size, 1, fp);

创建缓冲区后,您可以使用“fread”函数读取整个文件,该函数获取文件指针、要读取的每个元素的大小、要读取的元素的数量以及目标数组。

// Add a null terminator at the end of the char array
buffer[file_size] = '\0';

您可能想知道为什么需要为“缓冲区”分配额外的字节。为什么不只是(file_size)而是(file_size + 1)?在这里,将在 char 数组的末尾添加 null 终止符,以指示字符串的结束。实际上,如果您唯一的任务是将文件读入数组,那么这一步是不必要的。但稍后如果您想将此数组打印为字符串,那么这是一个要求。C 中的字符串被定义为将最后一个字符作为空终止符“\0”。

清理你的代码

您已经打开并使用了该文件,因此请记住随后将其关闭。只需使用“fclose”函数来释放您分配的“文件”指针变量。

fclose(file);

谈到释放指针,还记得用来存储字符的“缓冲区”数组吗?如果您将其定义为已分配的内存(指针),那么最好立即释放它以避免内存泄漏。

free(buffer);

以下是您的解决方案的概述:

#include 
#include int main() {FILE *file;char filename[] = "example.txt";char *buffer = NULL; // initialize buffer to NULLint buffer_size = 0;int i = 0;//Open file for readingfile = fopen(filename, "r");//Check if file opened successfullyif (file  == NULL) {printf("Error: Failed to open file '%s'.\n", filename);return 1;}// Read file character by characterint c;while ((c = fgetc(file)) != EOF) {// If buffer is full, resize itif (i >= buffer_size) {buffer_size += 1000; // increase buffer size by 1000 bytesbuffer = realloc(buffer, buffer_size); // resize bufferif (buffer == NULL) {printf("Error: Memory allocation failed.\n");return 1;}}buffer[i] = c;i++;}// Close filefclose(file);// Print the character arrayprintf("%s", buffer);// Free the dynamically allocated bufferfree(buffer);return 0;
}

相关文章:

将文件读入C中的字符数组

当您使用 C 编程语言时,您可能会遇到一些需要将文件读入字符数组的问题,例如分析每个字符的频率,或者将所有句子的每个起始词从小写转换为大写,反之亦然。该解决方案非常简单,但对于不太了解文件读取或写入的人来说可能…...

不小心删除了短信,如何在 Android 上恢复已删除的短信

不小心删除了文字消息在 Android 手机上使用可能会是一种令人痛苦的体验。这些消息可能包含有价值的信息、珍贵的回忆或重要的细节。幸运的是,您可以探索多种方法来恢复这些丢失的消息。在本文中,我们将深入研究可用于检索已删除短信的选项,并…...

Java电子招投标采购系统源码-适合于招标代理、政府采购、企业采购、等业务的企业

项目说明 随着公司的快速发展,企业人员和经营规模不断壮大,公司对内部招采管理的提升提出了更高的要求。在企业里建立一个公平、公开、公正的采购环境,最大限度控制采购成本至关重要。符合国家电子招投标法律法规及相关规范,以及审…...

springBoot的实现原理;SpringBoot是什么;使用SpringBoot的核心功能;springBoot核心注解以及核心配置文件

文章目录 springBootspringBoot的实现原理什么是 Spring Boot?SpringBoot是什么为什么要使用springBootSpring Boot的核心功能Spring Boot 主要有如下优点: SpringBoot启动过程-流程Spring Boot 的核心注解是哪个?什么是 JavaConfig&#xff…...

logback-spring.xml详解

《springboot使用logback日志框架超详细教程》文中,filter中最重要的两个过滤器LevelFilter(日志级别精确匹配)、ThresholdFilter(阈值过滤) 的描述非常准确: springboot使用logback日志框架超详细教程_sp…...

【Python】nn.BCEWithLogitsLoss函数详解

nn.BCEWithLogitsLoss() 是 PyTorch 中一个用于二元分类问题的损失函数,它结合了 Sigmoid 层(将输出映射到 [0,1] 范围内)和 Binary Cross Entropy(BCE)损失。这可以避免在正向和反向传播过程中可能出现梯度爆炸或梯度…...

【C++】日期类的实现

在上篇博客中我们已经学习了C中的运算符重载,我们说,操作符只能对于内置类型进行操作,对自定义类型我们需要自己定义函数去实现一系列的操作 那么这篇博客我们就专门把日期这个类单独拿出来写一下它都有哪些有意义的可以重载的运算符&#xf…...

带残差连接的ResNet18

目录 1 模型构建 1.1 残差单元 1.2 残差网络的整体结构 2 没有残差连接的ResNet18 2.1 模型训练 2.2 模型评价 3 带残差连接的ResNet18 3.1 模型训练 3.2 模型评价 4 与高层API实现版本的对比实验 总结 残差网络(Residual Network,ResNet)…...

【深入解析git和gdb:版本控制与调试利器的终极指南】

【本节目标】 1. 掌握简单gdb使用于调试 2. 学习 git 命令行的简单操作, 能够将代码上传到 Github 上 1.Linux调试器-gdb使用 1.1.背景 程序的发布方式有两种,debug模式和release模式release模式不可被调试,debug模式可被调试Linux gcc/g出来的二进制…...

CGAN原理讲解与源码

1.CGAN原理 生成器,输入的是c和z,z是随机噪声,c是条件,对应MNIST数据集,要求规定生成数字是几。 输出是生成的虚假图片。 生成器生成的图片被判别器认为是真实图片,那么标签就是1 其实判别器模型输出的是…...

C#实体类与XML互转以及List和DataTable转XML的使用

引言 在C#开发中,数据的存储和传输是非常常见的需求。使用XML作为数据格式有很多优点,例如可读性强、易于解析等。而实体类、List和DataTable是表示数据模型的常用方式。本文将介绍如何在C#中实现实体类、List和DataTable与XML之间的相互转换&#xff0c…...

uniapp的vue3的模版的setup函数内使用uniapp内置方法

vue2使用方式直接在method同级使用就行,但是在vue3的setup函数内直接使用会报错,本人找了好久,发现vue3需要导入uniapp模块才能使用,具体如下 使用uniapp上拉加载更多方法 <script>import {onReachBottom} from dcloudio/uni-apponReachBottom(() > {console.log(&qu…...

UI自动化的基本知识

一、UI自动化测试介绍 1、什么是自动化测试 概念&#xff1a;由程序代替人工进行系统校验的过程 1.1自动化测试能解决的问题&#xff1f; 回归测试 (冒烟测试) 针对之前老的功能进行测试 通过自动化的代码来实现。 针对上一个版本的问题的回归 兼容性测试 web实例化不同的浏…...

python实现C++简易自动压行

突发奇想&#xff0c;想要将自己的c压行之后交上去。但是苦于手动压行效率太低&#xff0c;在网上搜索压行网站没有找到&#xff0c;突然发现压行不就是检查检查去个换行符吗。于是心血来潮&#xff0c;用python实现了一个简易压行程序。 首先&#xff0c;宏定义等带#的文件不…...

京东数据分析(京东大数据采集):2023年线上珍珠市场销售数据采集

在珠宝首饰市场&#xff0c;从黄金到钻石&#xff0c;如今年轻人的新风潮又转向了珍珠。珍珠热潮并非刚刚兴起&#xff0c;早在前两年&#xff0c;抖音、快手等短视频台的珍珠开蚌直播内容&#xff0c;就掀起了一波珍珠热潮。 此后&#xff0c;随着珍珠饰品被越来越多社交平台的…...

亚信科技AntDB数据库与库瀚存储方案完成兼容性互认证

近日&#xff0c;亚信科技AntDB数据库与苏州库瀚信息科技有限公司自主研发的RISC-V数据库存储解决方案进行了产品兼容测试。经过双方团队的严格测试&#xff0c;亚信科技AntDB数据库与库瀚数据库存储解决方案完全兼容、运行稳定。除高可用性测试外&#xff0c;双方进一步开展TP…...

现代C++之万能引用、完美转发、引用折叠

现代C之万能引用、完美转发、引用折叠 0.导语1.问题引入2.引入万能引用3.万能引用出现场合4.理解左值与右值4.1 精简版4.2 完整版4.3 生命周期延长4.4 生命周期延长应用5.区分万能引用6.表达式的左右值性与类型无关7.引用折叠和完美转发7.1 引用折叠之本质细节7.2 示例与使用7.…...

ELK日志收集系统-filbeat

filebeat日志收集工具 elk&#xff1a;filebeat日志收集工具和logstash相同 filebeat是一个轻量级的日志收集工具&#xff0c;所使用的系统资源比logstash部署和启动时使用的资源要小的多 filebeat可以运行在非Java环境&#xff0c;它可以代理logstash在非java环境上收集日志…...

Python小知识

个人学习笔记&#xff0c;用于记录使用过程中好用的技巧、好用的库。 1 小知识 1.1 相对路径 1.2 打包Exe文件 命令&#xff1a; pyinstaller -F main.py其中-F&#xff1a;覆盖之前打包的文件 mian.py&#xff1a;需要打包的Python文件 PS&#xff1a;使用pyinstaller 5.1…...

如何在Ubuntu系统上安装Redis

Redis的下载 Redis安装包分为windows版和Linux版当前示例中介绍的是Linux版本Linux的下载地址&#xff1a;Index of /releases/ (redis.io)本次下载的压缩包为&#xff1a;redis-6.2.14.tar.gzRedis的安装 将压缩包通过ssh远程工具上传到Linux服务器中解压压缩包 tar -zxvf red…...

最强 AI Coding Agent 架构深度解构

在技术领域&#xff0c;我们常常被那些闪耀的、可见的成果所吸引。今天&#xff0c;这个焦点无疑是大语言模型技术。它们的流畅对话、惊人的创造力&#xff0c;让我们得以一窥未来的轮廓。然而&#xff0c;作为在企业一线构建、部署和维护复杂系统的实践者&#xff0c;我们深知…...

Windows效率神器PowerToys终极指南:30+免费工具快速提升工作效率

Windows效率神器PowerToys终极指南&#xff1a;30免费工具快速提升工作效率 【免费下载链接】PowerToys Microsoft PowerToys is a collection of utilities that supercharge productivity and customization on Windows 项目地址: https://gitcode.com/GitHub_Trending/po/…...

面试官: 秒杀库存扣减策略(答案深度解析)持续更新

秒杀库存扣减策略 —— 面试官真正想听的深度解析⚠️ 注意&#xff1a;面试官问“秒杀库存扣减”&#xff0c;绝不是想听你背概念&#xff0c;而是考察你是否真正踩过坑、权衡过取舍、理解系统本质。下面我用真实项目视角&#xff0c;带你一层层拆解。一、为什么库存扣减是秒杀…...

如何免费解锁Spotify高级功能:5分钟完成广告拦截终极指南

如何免费解锁Spotify高级功能&#xff1a;5分钟完成广告拦截终极指南 【免费下载链接】BlockTheSpot Video, audio & banner adblock/skip for Spotify 项目地址: https://gitcode.com/gh_mirrors/bl/BlockTheSpot 你是否厌倦了在享受音乐时被频繁的广告打断&#x…...

机器人跟随算法

REF&#xff1a;基于多机器人路径规划与编队控制的优化研究1. 基础模型RRT&#xff08;快速随机树&#xff09;算法&#xff1a;模拟树的生长过程&#xff0c;起始点为树的根节点&#xff0c;在环境中随机采样作为树的叶节点&#xff0c;从最近节点到目标点的方向上&#xff0c…...

Ozon运营5大核心场景,Captain AI全功能精准赋能

做Ozon运营,不少卖家会遇到这样的场景:选品时纠结不定,不清楚哪类产品适配市场、合规且有盈利空间;新品上架后缺乏有效推广思路,流量难以提升;财税申报流程复杂,担心操作失误引发违规;物流方案选择困难,难以平衡成本与时效;对账时面对俄语账单无从下手,无法清晰掌握…...

Laravel缓存、队列、邮件、文件系统等服务的驱动配置

Laravel核心服务通过驱动机制实现可插拔扩展&#xff0c;缓存、队列、邮件、文件系统均需在config文件和.env中配置对应驱动及参数。在 Laravel 应用中&#xff0c;缓存、队列、邮件和文件系统等核心服务均通过驱动&#xff08;Driver&#xff09;机制实现可插拔式扩展。每个服…...

VBA-JSON终极指南:在Excel中轻松处理JSON数据的完整教程

VBA-JSON终极指南&#xff1a;在Excel中轻松处理JSON数据的完整教程 【免费下载链接】VBA-JSON JSON conversion and parsing for VBA 项目地址: https://gitcode.com/gh_mirrors/vb/VBA-JSON 你是否经常需要在Excel中处理来自API的JSON数据&#xff1f;或者需要将Excel…...

实测Qwen3智能字幕生成效果:高精度时间戳对齐,剪辑无缝衔接

实测Qwen3智能字幕生成效果&#xff1a;高精度时间戳对齐&#xff0c;剪辑无缝衔接 1. 效果展示与核心价值 1.1 为什么选择Qwen3字幕生成工具 在视频制作过程中&#xff0c;字幕时间轴对齐是最耗时的工作之一。传统手动对齐方式不仅效率低下&#xff0c;而且很难达到毫秒级精…...

拉曼激光雷达 L0 级数据 Python处理和可视化实现,结果分析

4 个通道产品逐图分析 左上&#xff1a;532P 通道&#xff08;532 nm 平行偏振通道&#xff09; 产品类型 &#xff1a;532 nm 弹性散射平行偏振原始信号&#xff08;L0 级&#xff09; 物理含义 &#xff1a;接收 532 nm 激光与大气分子、气溶胶、云粒子发生弹性散射后&#…...