将文件读入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;
}

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

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

相关文章

MVVM 模式与 MVC 模式:构建高效应用的选择

🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云…

世岩清上:什么是元宇宙

元宇宙是一个虚拟的数字世界,它是一种全新的互联网形式,是一个可以提供身临其境体验的虚拟世界。元宇宙融合了现实和虚拟,允许用户在这个数字空间中自由探索、创造和交互。 元宇宙的概念源于科幻小说和电影,它最早出现在1992年的…

【SQL SERVER】定时任务

oracle是定时JOB,sqlserver是创建作业,通过sqlserver代理实现 先看SQL SERVER代理得服务有没有开 选择计算机右键——>管理——>服务与应用程序——>服务——>SQL server 代理 然后把SQL server 代理(MSSQLSERVER)启…

开源vs闭源,大模型的未来在哪一边?

开源和闭源,两种截然不同的开发模式,对于大模型的发展有着重要影响。开源让技术共享,吸引了众多人才加入,推动了大模的创新。而闭源则保护了商业利益和技术优势,为大模型的商业应用提供了更好的保障。 那么&#xff0c…

Vue3+java开发组队功能

Vue3java开发系统组队功能 需求分析 创建用户可以创建一个队伍(一个房间队长),设置队伍人数,队伍名称(标题),描述,超时时间。搜索加入,用户可以加入未满的队伍&#xf…

github新建项目

参考链接:Github上建立新项目超详细方法过程 在这里新建一个repositories 接下来就选择相关的信息: 然后create a new就行了 接下来需要创建文件:(同时通过upload上传文件) 每次最多上传100个文件,然后保…

OpenGL笔记:纹理的初次使用

说明 纹理的代码写完后,一直出不来结果,原因是没有设置GL_TEXTURE_MIN_FILTER, 它的默认值为GL_NEAREST_MIPMAP_LINEAR, 因为这里我还没用到Mipmap,所以使用这个默认值,结果是错误的,关于mipma…

软著项目推荐 深度学习二维码识别

文章目录 0 前言2 二维码基础概念2.1 二维码介绍2.2 QRCode2.3 QRCode 特点 3 机器视觉二维码识别技术3.1 二维码的识别流程3.2 二维码定位3.3 常用的扫描方法 4 深度学习二维码识别4.1 部分关键代码 5 测试结果6 最后 0 前言 🔥 优质竞赛项目系列,今天…

正点原子linux应用编程——提高篇1

在之前的入门篇学习中,都是直接在Ubuntu中进行验证的,对于嵌入式Linux系统来说,也是可以直接移植的,只需要使用嵌入式硬件平台对应的交叉编译工具编译应用程序即可运行。 在嵌入式Linux系统中,编写的应用程序通常需要…

Prometheus的详细部署

普罗米修斯下载网址: Download | Prometheus 准备两台机器: 192.168.58.152 prometheus 192.168.58.142 node_exporter 关闭防火墙和selinux: [rootlocalhost ~]# setenforce 0 && systemctl stop firewalld[rootlocalhost ~]# seten…

nginx https 一个端口代理多个前端项目

打包修改 !!!注意:第一个location root 调用的项目不用修改 打包路径,直接用 ‘/’,其他项目或者需加 /mobile 路径 worker_processes 1; events {worker_connections 1024; } http {include mime.…

K8S集群中PLEG问题排查

一、背景 k8s集群排障真的很麻烦 今天集群有同事找我,节点报 PLEG is not healthy 集群中有的节点出现了NotReady,这是什么原因呢? 二、kubernetes源码分析 PLEG is not healthy 也是一个经常出现的问题 POD 生命周期事件生成器 先说下PL…

for for in for of 的区别

for是JavaScript中最基本的循环语句,它可以用于遍历数组和对象中的元素,语法如下: for (初始化; 判断条件; 增量) {// 循环体 }其中,初始化是循环开始前执行的语句,判断条件是判断循环是否可以继续的条件,…

Pybullet -------[ 1 ]

1. p.addUserDebugText() 这个函数允许在仿真环境中动态添加文本,用于调试和可视化。你可以指定文本的内容、位置、颜色、大小等属性。 p.addUserDebugText(text, textPosition, textColorRGB[1,1,1], textSize1, lifeTime0, parentObjectUniqueId0,parentLinkInde…

机器视觉双目测宽仪具体有什么优势?

双目测宽仪是机器视觉原来制造而成的智能宽度检测设备,广泛应用于板材类产品的宽度检测。通过测宽仪的使用,实时了解产品宽度品质,进行超差提示,减少废品的生产。 双目测宽仪优势 测量软件界面显示:产品规格、标称宽…

MATLAB算法实战应用案例精讲-【图像处理】FPGA

目录 前言 算法原理 FPGA 是什么 FPGA的定义以及和GPU的类比 FPGA 有什么用 1)通信领域

Android控件全解手册 - 任意View缩放平移工具-源码

Unity3D特效百例案例项目实战源码Android-Unity实战问题汇总游戏脚本-辅助自动化Android控件全解手册再战Android系列Scratch编程案例软考全系列Unity3D学习专栏蓝桥系列ChatGPT和AIGC 👉关于作者 专注于Android/Unity和各种游戏开发技巧,以及各种资源分…

详细介绍如何使用 PaddleOCR 进行光学字符识别-(含源码及讲解)

阅读巨大的文档可能会非常累并且非常耗时。您一定见过许多软件或应用程序,只需单击图片即可从文档中获取关键信息。这是通过一种称为光学字符识别 (OCR) 的技术来完成的。光学字符识别是近年来人工智能领域的重点研究之一。光学字符识别是通过理解和分析图像的基本模式来识别图…

竞赛选题 题目:基于机器视觉的图像矫正 (以车牌识别为例) - 图像畸变校正

文章目录 0 简介1 思路简介1.1 车牌定位1.2 畸变校正 2 代码实现2.1 车牌定位2.1.1 通过颜色特征选定可疑区域2.1.2 寻找车牌外围轮廓2.1.3 车牌区域定位 2.2 畸变校正2.2.1 畸变后车牌顶点定位2.2.2 校正 7 最后 0 简介 🔥 优质竞赛项目系列,今天要分享…

yolov8-pose姿势估计,站立识别

系列文章目录 基于yolov8-pose的姿势估计模式,实现站姿,坐姿,伏案睡姿识别,姿态动作识别接口逻辑作参考。本文以学习交流,分享,欢迎留言讨论优化。 yoloPose-姿势动作识别 系列文章目录前言一、环境安装二、使用yolov8-pose1.导入模型,预测图像三.姿势动作识别之站立总…