文件操作(二、scanf/fscanf/sscanf​与printf/fprintf/sprintf​、fseek与ftell与rewind、feof)

2023-12-20 16:20

本文主要是介绍文件操作(二、scanf/fscanf/sscanf​与printf/fprintf/sprintf​、fseek与ftell与rewind、feof),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

 一、scanf/fscanf/sscanf​与printf/fprintf/sprintf​的对比

二、fseek与ftell与rewind

三、feof

1. 文本文件读取是否结束,判断返回值是否为 EOF ( fgetc ),或者 NULL ( fgets )例如:

2. 二进制文件的读取结束判断,判断返回值是否小于实际要读的个数。例如:

四、文件缓冲区​


书接上文:

文件操作(一、fgets和fputs、fscanf和fprintf、fread 和 fwrite、fopen和fclose、fgetc和fputc)-CSDN博客

 一、scanf/fscanf/sscanf​与printf/fprintf/sprintf​的对比

struct S
{char name[20];int age;float score;
};int main()
{struct S s = { "zhangsan", 20, 85.5f };struct S tmp = { 0 };char arr[100] = { 0 };sprintf(arr, "%s %d %f", s.name, s.age, s.score);printf("%s\n", arr);sscanf(arr, "%s %d %f", tmp.name, &(tmp.age), &(tmp.score));// 使用sscanf函数从arr数组中按照"%s %d %f"的格式读取数据,并分别赋值给tmp结构体的三个成员  printf("%s %d %f\n", tmp.name, tmp.age, tmp.score);// 打印tmp结构体的三个成员的值,以验证是否成功从arr数组中读取了数据  return 0;
}

二、fseek与ftell与rewind

fseek​
根据文件指针的位置和偏移量来定位文件指针。

int fseek ( FILE * stream, long int offset, int origin );

ftell​

返回文件指针相对于起始位置的偏移量

long int ftell ( FILE * stream );

rewind

让文件指针的位置回到文件的起始位置

void rewind ( FILE * stream );

int main()
{FILE* pf = fopen("data.txt", "r");if (pf == NULL){perror("fopen");return 1;}fseek(pf, 0, SEEK_END);//读文件//int ch = fgetc(pf);//printf("%c\n", ch);//ch = fgetc(pf);//printf("%c\n", ch);//ch = fgetc(pf);//printf("%c\n", ch);//ch = fgetc(pf);//printf("%c\n", ch);int n = ftell(pf);printf("%d\n", n);//fseek(pf, -4, SEEK_CUR);//向后偏移4个字符//fseek(pf, -6, SEEK_END);//向后偏移6个字符//fseek(pf, 1, SEEK_CUR);//向前偏移一个字符//ch = fgetc(pf);////printf("%c\n", ch);fclose(pf);pf = NULL;return 0;
}

三、feof

被错误使用的 feof ​
牢记:在文件读取过程中,不能用feof函数的返回值直接来判断文件的是否结束。
feof 的作用是:当文件读取结束的时候,判断是读取结束的原因是否是:遇到文件尾结束。

1. 文本文件读取是否结束,判断返回值是否为 EOF ( fgetc ),或者 NULL ( fgets )
例如:

  • fgetc 判断是否为 EOF .

  • fgets 判断返回值是否为 NULL .

2. 二进制文件的读取结束判断,判断返回值是否小于实际要读的个数。
例如:

  • fread判断返回值是否小于实际要读的个数

文本文件的例子:

int main(void)
{int c; // 注意:int,非char,要求处理EOF​FILE* fp = fopen("test.txt", "r");if(!fp) {perror("File opening failed");return EXIT_FAILURE;// 返回失败状态码,通常定义为1,表示程序异常退出}//fgetc 当读取失败的时候或者遇到文件结束的时候,都会返回EOF​while ((c = fgetc(fp)) != EOF) // 标准C I/O读取文件循环​// 使用fgetc函数从fp指向的文件中逐个字符地读取内容。fgetc函数返回读取到的字符,或者在读取失败或 遇到文件结束时返回EOF{ putchar(c);// 使用putchar函数将读取到的字符输出到标准输出}//判断是什么原因结束的​if (ferror(fp))// 检查循环结束的原因。使用ferror函数检查是否在读取文件时发生了错误,使用feof函数检查是否已经到达 了文件末尾puts("I/O error when reading");else if (feof(fp))puts("End of file reached successfully");fclose(fp);
}

二进制文件的例子:

enum { SIZE = 5 };
int main(void)
{double a[SIZE] = { 1.,2.,3.,4.,5. };FILE* fp = fopen("test.bin", "wb"); // 必须用二进制模式​fwrite(a, sizeof * a, SIZE, fp); // 写 double 的数组​// 使用fwrite函数将数组a的内容写入到文件中。sizeof *a得到数组中一个元素的大小,SIZE表示元素            的数量。fclose(fp);double b[SIZE];fp = fopen("test.bin", "rb");/ 使用fopen函数以二进制写模式("wb")打开一个名为"test.bin"的文件,返回的文件指针存储在fp中。size_t ret_code = fread(b, sizeof * b, SIZE, fp); // 读 double 的数组​// 使用fread函数从文件中读取数据到数组b中。sizeof *b得到数组中一个元素的大小,SIZE表示元素        的数量。  // fread函数返回实际读取到的元素数量,存储在ret_code中。if (ret_code == SIZE) {puts("Array read successfully, contents: ");for (int n = 0; n < SIZE; ++n) printf("%f ", b[n]);putchar('\n');}else { //判断是什么原因结束的if (feof(fp))// 如果已经到达文件末尾,说明文件内容不足,提前结束。printf("Error reading test.bin: unexpected end of file\n");else if (ferror(fp)) // 如果发生了其他I/O错误。{perror("Error reading test.bin");}}fclose(fp);
}

四、文件缓冲区​

ANSIC 标准采用“缓冲文件系统”处理的数据文件的,所谓缓冲文件系统是指系统自动地在内存中为
程序中每一个正在使用的文件开辟一块“文件缓冲区”。从内存向磁盘输出数据会先送到内存中的缓
冲区,装满缓冲区后才一起送到磁盘上。如果从磁盘向计算机读入数据,则从磁盘文件中读取数据输
入到内存缓冲区(充满缓冲区),然后再从缓冲区逐个地将数据送到程序数据区(程序变量等)。缓
冲区的大小根据C编译系统决定的。​

//VS2019 WIN11环境测试​
int main()
{FILE*pf = fopen("test.txt", "w");fputs("abcdef", pf);//先将代码放在输出缓冲区​printf("睡眠10秒-已经写数据了,打开test.txt文件,发现文件没有内容\n");Sleep(10000);printf("刷新缓冲区\n");fflush(pf);//刷新缓冲区时,才将输出缓冲区的数据写到文件(磁盘)​//注:fflush 在高版本的VS上不能使用了​printf("再睡眠10秒-此时,再次打开test.txt文件,文件有内容了\n");Sleep(10000);fclose(pf);//注:fclose在关闭文件的时候,也会刷新缓冲区​pf = NULL;return 0;
}

因为有缓冲区的存在,C语言在操作文件的时候,需要做刷新缓冲区或者在文件操作结束的时候关闭文件。
如果不做,可能导致读写文件的问题。

今天就先到这了!!!

近期寒潮来袭,还请大家注意防寒(本人已经中招了o(╥﹏╥)o)

看到这里了还不给博主扣个:
⛳️ 点赞☀️收藏 ⭐️ 关注!

你们的点赞就是博主更新最大的动力!
有问题可以评论或者私信!!!

这篇关于文件操作(二、scanf/fscanf/sscanf​与printf/fprintf/sprintf​、fseek与ftell与rewind、feof)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/516660

相关文章

hdu 2093 考试排名(sscanf)

模拟题。 直接从教程里拉解析。 因为表格里的数据格式不统一。有时候有"()",有时候又没有。而它也不会给我们提示。 这种情况下,就只能它它们统一看作字符串来处理了。现在就请出我们的主角sscanf()! sscanf 语法: #include int sscanf( const char *buffer, const char *format, ... ); 函数sscanf()和

动手学深度学习【数据操作+数据预处理】

import osos.makedirs(os.path.join('.', 'data'), exist_ok=True)data_file = os.path.join('.', 'data', 'house_tiny.csv')with open(data_file, 'w') as f:f.write('NumRooms,Alley,Price\n') # 列名f.write('NA

线程的四种操作

所属专栏:Java学习        1. 线程的开启 start和run的区别: run:描述了线程要执行的任务,也可以称为线程的入口 start:调用系统函数,真正的在系统内核中创建线程(创建PCB,加入到链表中),此处的start会根据不同的系统,分别调用不同的api,创建好之后的线程,再单独去执行run(所以说,start的本质是调用系统api,系统的api

Java IO 操作——个人理解

之前一直Java的IO操作一知半解。今天看到一个便文章觉得很有道理( 原文章),记录一下。 首先,理解Java的IO操作到底操作的什么内容,过程又是怎么样子。          数据来源的操作: 来源有文件,网络数据。使用File类和Sockets等。这里操作的是数据本身,1,0结构。    File file = new File("path");   字

MySQL——表操作

目录 一、创建表 二、查看表 2.1 查看表中某成员的数据 2.2 查看整个表中的表成员 2.3 查看创建表时的句柄 三、修改表 alter 3.1 重命名 rename 3.2 新增一列 add 3.3 更改列属性 modify 3.4 更改列名称 change 3.5 删除某列 上一篇博客介绍了库的操作,接下来来看一下表的相关操作。 一、创建表 create

封装MySQL操作时Where条件语句的组织

在对数据库进行封装的过程中,条件语句应该是相对难以处理的,毕竟条件语句太过于多样性。 条件语句大致分为以下几种: 1、单一条件,比如:where id = 1; 2、多个条件,相互间关系统一。比如:where id > 10 and age > 20 and score < 60; 3、多个条件,相互间关系不统一。比如:where (id > 10 OR age > 20) AND sco

PHP7扩展开发之流操作

前言 啥是流操作?简单来讲就是对一些文件,网络的IO操作。PHP已经把这些IO操作,封装成流操作。这节,我们将使用PHP扩展实现一个目录遍历的功能。PHP示例代码如下: <?phpfunction list_dir($dir) {if (is_dir($dir) === false) {return;} $dh = opendir($dir);if ($dh == false) {ret

浙大数据结构:树的定义与操作

四种遍历 #include<iostream>#include<queue>using namespace std;typedef struct treenode *BinTree;typedef BinTree position;typedef int ElementType;struct treenode{ElementType data;BinTree left;BinTre

浙大数据结构:04-树7 二叉搜索树的操作集

这道题答案都在PPT上,所以先学会再写的话并不难。 1、BinTree Insert( BinTree BST, ElementType X ) 递归实现,小就进左子树,大就进右子树。 为空就新建结点插入。 BinTree Insert( BinTree BST, ElementType X ){if(!BST){BST=(BinTree)malloc(sizeof(struct TNo

hibernate修改数据库已有的对象【简化操作】

陈科肇 直接上代码: /*** 更新新的数据并并未修改旧的数据* @param oldEntity 数据库存在的实体* @param newEntity 更改后的实体* @throws IllegalAccessException * @throws IllegalArgumentException */public void updateNew(T oldEntity,T newEntity