【北京迅为】《iTOP-3588开发板开发板系统编程手册》第3章 标准IO

RK3588是一款低功耗、高性能的处理器,适用于基于arm的PC和Edge计算设备、个人移动互联网设备等数字多媒体应用,RK3588支持8K视频编解码,内置GPU可以完全兼容OpenGLES 1.1、2.0和3.2。RK3588引入了新一代完全基于硬件的最大4800万像素ISP,内置NPU,支持INT4/INT8/INT16/FP16混合运算能力,支持安卓12和、Debian11、Build root、Ubuntu20和22版本登系统。了解更多信息可点击迅为官网   

【粉丝群】824412014

【实验平台】:迅为RK3588开发板

【内容来源】《iTOP-3588开发板系统编程手册》

【全套资料及网盘获取方式】联系淘宝客服加入售后技术支持群内下载

【视频介绍】:【强者之芯】 新一代AIOT高端应用芯片 iTOP -3588人工智能工业AI主板


第3章 标准IO

标准IO(Standard I/O)是一种抽象层,用于在程序和底层操作系统I/O接口之间提供一个标准化的、可移植的I/O接口。标准IO提供了对文件、终端、套接字等不同类型的I/O设备的统一访问接口。标准IO主要包括以下三个文件流:

stdin:标准输入流,通常关联着键盘输入。

stdout:标准输出流,通常关联着控制台显示器。

stderr:标准错误流,通常关联着控制台显示器,用于输出错误信息。

标准IO提供了一组函数来读写这三个文件流,包括fopen()、fclose()、fread()、fwrite()、fseek()等。

标准IO的主要优点是:

  1. 与底层的系统调用相比,标准IO函数更加容易使用和掌握,可以大大降低编程的难度。
  2. 标准IO函数可以自动进行缓冲,从而提高IO效率。缓冲可以是全缓冲、行缓冲或无缓冲,可以通过setvbuf()函数进行设置(关于缓存相关的知识会在第五章进行讲解)。
  3. 标准IO函数是可移植的,可以在不同的操作系统上使用相同的代码进行编译和运行。

标准IO也有一些缺点:

  1. 标准IO函数的效率相对较低,因为需要进行多次函数调用和缓冲区的复制。
  2. 标准IO函数有时不能提供足够的控制力,比如无法直接控制文件描述符或进行底层的操作。

下面就跟随我一起进入标准IO的学习吧。

3.1 FILE指针

FILE指针是C语言中用来处理文件的重要概念,它指向文件中的某个位置,可以用来进行文件的读取和写入操作。在C语言中,所有的文件I/O操作都通过FILE结构体来实现,FILE指针则是指向这个结构体的指针。

使用FILE指针进行文件操作的基本流程如下:

  1. 打开文件:使用fopen函数打开文件,并返回一个FILE指针,该指针指向打开的文件。
  2. 对文件进行读写操作:可以使用fscanf、fprintf等函数对文件进行读写操作。
  3. 关闭文件:使用fclose函数关闭文件,释放资源,并将FILE指针设置为NULL。

会在接下来的几个小节中对打开文件、关闭文件、文件的读写等相关C语言库函数进行讲解。

3.2打开文件

本小节代码在配套资料“iTOP-3588开发板\03_【iTOP-RK3588开发板】指南教程\03_系统编程配套程序\08”目录下,如下图所示:

学习前的疑问:

1.打开文件要使用哪个C语言库函数?

2.fopen()函数要怎样进行使用?

fopen()是C库函数中用来打开文件的函数,所使用的头文件和函数原型,如下所示:

所需头文件

函数原型

1

#include <stdio.h>

FILE *fopen(const char *pathname, const char *mode);

fopen 的返回值是 FILE 类型的文件流,当它的值不为 NULL 时表示正常,后续的 fread、fwrite 等函数可通过文件流访问对应的文件。

fopen()函数两个参数含义如下所示:

参数名称

参数含义

pathname

字符串类型,用于标识需要打开或创建的文件路径和文件名。

2

mode

该参数是一个字符串类型,用于指定文件的打开方式

常用的mode参数如下:

标志

用途

"r"

以只读方式打开,文件指针位于文件的开头

"r+"

以可读、可写方式打开文件。

"w"

以只写方式打开文件,如果参数 path 指定的文件存在,将文件长度截断为 0;如果指定文件不存在则创建该文件。

"w+"

以可读、可写方式打开文件,如果参数 path 指定的文件存在,将文件长度截断为 0;如果指定文件不存在则创建该文件。

"a"

以只写方式打开文件,打开以进行追加内容(在文件末尾写入),如果文件不存在则创建该文件。

"a+"

以可读、可写方式打开文件,以追加方式写入 (在文件末尾写入),如果文件不存在则创建该文件。

至此关于fopen()函数的相关讲解就完成了,下面进行相应的实验。

实验要求:

通过C语言库函数fopen(),创建一个可读可写名称为test的文件

实验步骤:

首先进入到ubuntu的终端界面输入以下命令来创建demo08_fopen.c文件,如下图所示:

vim demo08_fopen.c

然后向该文件中添加以下内容:

#include<stdio.h>

int main(int argc,char *argv[])
{
    FILE *fp;          // 定义文件指针变量
    int ret;           // 定义返回值变量

    fp = fopen("test", "w+");  // 打开文件 test,以读写方式打开
    if (fp == NULL)    // 如果文件打开失败,fp 的值为 NULL
    {
        perror("File open error\r\n");  // 打印错误信息
    }
    printf("File open success\r\n");   // 如果文件打开成功,则打印成功信息

    return 0;   // 程序正常结束
}

上述内容中,第8行调用了标准IO库函数fopen(),第一个参数为要打开或者创建的文件名称,第二个参数为w+,代表如果文件不存在就创建,存在或者创建成功之后以可读可写的方式打开文件。

保存退出之后,使用以下命令对demo08_fopen.c进行编译,编译完成如下图所示:

gcc -o demo08_fopen demo08_fopen.c

然后使用命令“./demo08_fopen”来运行,运行成功如下图所示:

可以看到程序运行成功之后,test文件就被创建成功了,然后再使用“ls -l”命令查看文件属性,如下图所示:

可以看到test文件的属性为可读可写,至此关于fopen函数的实验就完成了。

3.3关闭文件

本小节代码在配套资料“iTOP-3588开发板\03_【iTOP-RK3588开发板】指南教程\03_系统编程配套程序\09”目录下,如下图所示:

学习前的疑问:

1.关闭文件要使用哪个C语言库函数呢?

2.fclose()函数要怎样进行使用?

fclose()函数用于关闭已经打开的文件指针,所使用的头文件和函数原型,如下所示:

所需头文件

函数原型

1

#include <stdio.h>

int close((FILE *stream);

fclose函数返回0表示成功关闭文件,返回EOF表示关闭失败。fclose函数会将所有的缓冲区中的数据写入文件中,关闭文件并释放相应的资源。如果在写入数据时发生错误,fclose函数会返回EOF并设置相应的错误标志。

fclose()函数参数含义如下所示:

参数名称

参数含义

stream

FILE 类型指针。

至此关于fclose()函数的相关讲解就完成了,下面进行相应的实验。

实验要求:

创建一个可读可写名为test的文件,使用fopen函数打开文件之后使用fclose()函数对打开的文件流进行关闭。

实验步骤:

首先进入到ubuntu的终端界面输入以下命令来创建demo09_fclose.c文件,如下图所示:

vim demo09_fclose.c

然后向该文件中添加以下内容:

#include <stdio.h>

int main(int argc, char *argv[])
{
	FILE *fp; // 定义文件指针变量
	int ret;
	fp = fopen("test", "w+");  // 打开文件
	if(fp == NULL)
	{
		perror("文件打开失败\n");  // 打开文件失败,输出错误信息
	}
	printf("文件打开成功\n");

	ret = fclose(fp);  // 关闭文件
	if(ret != 0)
	{
		perror("文件关闭失败\n");  // 关闭文件失败,输出错误信息
	}
	printf("文件关闭成功\n");

	return 0;
}

相较于3.2小节的实验代码,只是多了第14行标准IO函数fclose(),用来关闭文件流,随后对fclose()函数的返回值进行判断。

保存退出之后,使用以下命令对demo09_close.c进行编译,编译完成如下图所示:

gcc -o demo09_fclose demo09_fclose.c

然后使用命令“./demo09_fclose”来运行,运行成功如下图所示: 

可以看到程序运行成功之后,test文件被创建成功了,且打开文件和关闭文件的信息也成功打印,至此关于fclose()函数实验就完成了。

3.4读文件

本小节代码在配套资料“iTOP-3588开发板\03_【iTOP-RK3588开发板】指南教程\03_系统编程配套程序\10”目录下,如下图所示:

学习前的疑问:

1.读取文件要使用哪个C语言库函数呢?

2.fread()函数要怎样进行使用?

fread()函数从文件中读取数据,所使用的头文件和函数原型,如下所示:

所需头文件

函数原型

1

#include <stdio.h>

size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);

调用成功时返回读取到的数据项数目(数据项数目并不等于实际读取的字节数,除非参数size 等于 1);如果发生错误或到达文件末尾,则 fread()返回的值将小于参数 nmemb,那么到底发生了错误还是到达了文件末尾,fread()并不能对此进行区分,具体是哪一种情况,此时可以使用 ferror()或 feof()函数来判断(这两个函数会在3.7小节进行讲解)。

fread()函数参数含义如下所示:

参数名称

参数含义

ptr

fread()将读取到的数据存放在参数 ptr 指向的缓冲区中

2

size

fread()从文件读取 nmemb 个数据项,每一个数据项的大小为 size 个字节,所以总共读取的数据大小为 nmemb * size 个字节

3

nmemb

参数 nmemb 指定了读取数据项的个数

4

stream

FILE 指针

至此关于fread()函数的相关讲解就完成了,下面进行相应的实验。

实验要求:

读取test文件中的内容,并打印出来。

实验步骤:

首先进入到ubuntu的终端界面输入以下命令来创建demo10_fread.c文件,如下图所示:

vim demo10_fread.c

然后向该文件中添加以下内容: 

#include<stdio.h>

int main(int argc,char *argv[])
{
	FILE *fp; //定义文件指针变量
	int ret; //定义返回值变量
	char buffer[1024] = {0}; //定义字符数组变量,并初始化为0
	fp = fopen("test", "r+"); //打开文件,以读写方式打开,若文件不存在则创建文件
	if(fp == NULL) //判断文件是否打开成功
	{
		perror("File open error\n"); //输出错误信息
		return -1; //返回错误代码
	}
	fread(buffer, sizeof(char), sizeof(buffer), fp); //从文件中读取数据到buffer数组中
	printf("buffer = %s\n", buffer); //输出buffer数组中的数据
	ret = fclose(fp); //关闭文件
	if(ret != 0) //判断文件是否关闭成功
	{
		perror("File close error\n"); //输出错误信息
		return -2; //返回错误代码
	}
	printf("File close success\n"); //输出文件关闭成功信息
	return 0; //返回正常代码
}

上述内容相较于3.3小节实验,添加了第14行和第15行内容,第14行使用了fread()函数对文件test进行数据的读取,并将读到的数据写入了buffer缓冲区 中,第11行对buffer内容进行打印。

保存退出之后,使用以下命令对demo10_fread.c进行编译,编译完成如下图所示:

gcc -o demo10_fread demo10_fread.c

然后使用命令“vim test”创建test文件,并添加以下内容:

hello world!!

添加完成如下图所示:

然后使用命令“./demo10_fread”来运行,运行成功如下图所示:

可以看到已经test文件中的“hello world!!”数据就被打印了出来,数据读取完成之后,文件流被关闭了。

至此关于fread()函数的实验就完成了。

3.5写文件

本小节代码在配套资料“iTOP-3588开发板\03_【iTOP-RK3588开发板】指南教程\03_系统编程配套程序\11”目录下,如下图所示:

学习前的疑问:

1.读取文件要使用哪个C语言库函数呢?

2.fwrite()函数要怎样进行使用?

fwrite()函数从文件中读取数据,所使用的头文件和函数原型,如下所示:

所需头文件

函数原型

1

#include <stdio.h>

size_t fwrite(const void *ptr, size_t size, size_t count, FILE *stream); 

调用成功时返回写入的数据项的数目(数据项数目并不等于实际写入的字节数,除非参数 size 等于 1);如果发生错误,则 fwrite()返回的值将小于参数 nmemb(或者等于 0)。由此可知,库函数 fread()、fwrite()中指定读取或写入数据大小的方式与系统调用 read()、write()不同,前者通过nmemb(数据项个数)*size(每个数据项的大小)的方式来指定数据大小,而后者则直接通过一个 size 参数指定数据大小。

fwrite()函数参数含义如下所示:

参数名称

参数含义

ptr

fread()将读取到的数据存放在参数 ptr 指向的缓冲区中

2

size

fread()从文件读取 nmemb 个数据项,每一个数据项的大小为 size 个字节,所以总共读取的数据大小为 nmemb * size 个字节

3

nmemb

参数 nmemb 指定了读取数据项的个数

4

stream

FILE 指针

至此关于fwrite()函数的相关讲解就完成了,下面进行相应的实验。

实验要求:

本代码所要实现的目标为创建一个可以读写名为test的文件,并写入字符“hello world”。

实验步骤:

首先进入到ubuntu的终端界面输入以下命令来创建demo11_fwrite.c文件,如下图所示:

vim demo11_fwrite.c

然后向该文件中添加以下内容  

#include<stdio.h>

int main(int argc,char *argv[])
{
	FILE *fp; //定义文件指针变量
	int ret; //定义返回值变量
	char buffer[11] = {"hello world"}; //定义字符数组变量,并初始化为"hello world"
	fp = fopen("test", "a"); //打开文件,以追加写入方式打开,若文件不存在则创建文件
	if(fp == NULL) //判断文件是否打开成功
	{
		perror("File open error\r\n"); //输出错误信息
		return -1; //返回错误代码
	}
	fwrite(buffer, sizeof(char), sizeof(buffer), fp); //将buffer数组中的数据写入文件中
	printf("buffer = %s\n", buffer); //输出buffer数组中的数据
	ret = fclose(fp); //关闭文件
	if(ret != 0) //判断文件是否关闭成功
	{
		perror("File close error\r\n"); //输出错误信息
		return -2; //返回错误代码
	}
	printf("File close success\r\n"); //输出文件关闭成功信息
	return 0; //返回正常代码
}

上述内容相较于3.3小节实验,添加了第14行和第15行内容,第15行使用了fwrite()函数将缓冲区buffer[]中的内容写入到test文件中,第15行对buffer缓冲区中的数据进行打印。

保存退出之后,使用以下命令对demo11_fwrite.c进行编译,编译完成如下图所示:

gcc -o demo11_fwrite demo11_fwrite.c

然后使用命令“./demo11_fwrite”来运行,运行成功如下图所示:   

可以看到test文件已经被成功创建了,然后使用以下命令对test文件进行查看,如下图所示:

cat test

可以看到“hello world”已经被写入test文件了。至此,关于fwrite()函数的相关实验就完成了。

3.6 fseek

和2.6小节lseek系统调用的作用相同,在C语言库函数中使用fseek函数设置文件指针的位置,在本小节将对fseek函数进行讲解。

本小节代码在配套资料“iTOP-3588开发板\03_【iTOP-RK3588开发板】指南教程\03_系统编程配套程序\12”目录下,如下图所示:

 fseek()函数用于设置文件读写位置偏移量,所使用的头文件和函数原型,如下所示:

所需头文件

函数原型

1

#include <stdio.h>

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

fseek函数返回0表示设置成功,返回非0值表示设置失败。

fseek()函数参数含义如下所示:

参数名称

参数含义

1

stream

要设置读写位置的文件指针

2

offset

相对于whence参数指定的位置的偏移量

3

whence

指定偏移量的起始位置。

至此关于fseek()函数的相关讲解就完成了,下面进行相应的实验。

实验要求:

测试fseek函数移动文件读写位置的功能。

实验步骤:

首先进入到ubuntu的终端界面输入以下命令来创建demo12_fseek.c文件,如下图所示:

vim demo12_fseek.c

然后向该文件中添加以下内容: 

#include <stdio.h>

int main(int argc,char *argv[])
{
	FILE *fp; //定义文件指针变量
	int ret; //定义返回值变量
	char buffer[1024] = {0}; //定义字符数组变量,并初始化为0
	fp = fopen("test", "r+"); //以读写方式打开文件,若文件不存在则创建文件
	if(fp == NULL) //判断文件是否打开成功
	{
		perror("File open error\r\n"); //输出错误信息
		return -1; //返回错误代码
	}

	fseek(fp, 5, SEEK_SET); //将文件指针指向文件的第6个字节处
	fread(buffer, sizeof(char), sizeof(buffer), fp); //从文件中读取数据到buffer数组中
	printf("buffer = %s\n", buffer); //输出buffer数组中的数据

	ret = fclose(fp); //关闭文件
	if(ret != 0) //判断文件是否关闭成功
	{
		perror("File close error\r\n"); //输出错误信息
		return -2; //返回错误代码
	}

	printf("File close success\r\n"); //输出文件关闭成功信息
	return 0; //返回正常代码
}

上述内容和3.4小节的相比只是多了第15行的内容,将读写指针偏移了五个字节。然后使用fread()函数进行数据读取,并打印读取到的内容。

保存退出之后,使用以下命令对demo12_fseek.c进行编译,编译完成如下图所示:

gcc -o demo12_fseek demo12_fseek.c

然后使用命令“vim test”创建test文件,并添加以下内容:

hello world!!

添加完成如下图所示:

 然后使用命令“./demo12_fseek”来运行,运行成功如下图所示:

可以看到程序运行成功之后,只会打印第五个字节之后的字符“world!!”,证明文件读写指针发生了变化,至此关于feek()函数相关的实验就完成了。

3.7 perror

经过了前面12个实验,大家会发现每个实验代码中都会有perror函数,用来进行错误信息的输出。perror是一个标准C库函数,其作用是将当前errno的值作为参数,输出对应的错误信息到标准错误输出(stderr)上。perror函数可以帮助我们快速定位程序运行时出现的错误,便于进行调试和排错。

perror函数的函数原型如下:

所需头文件

函数原型

1

#include <stdio.h>

void perror(const char *s);

其中,参数s是一个字符串,表示我们希望在输出错误信息前输出的一段文本,通常是一些提示信息或者函数名。如果s为NULL,则只输出错误信息而不添加前缀。

perror函数的使用非常简单,只需要在程序中调用它即可,以判断fopen函数返回值为例,perror的使用如下所示:

1 

2 

3 

4 

5 

6 

7 

8 

9

10

11

12

13

14

#include <stdio.h>

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

{

FILE *fp; //定义文件指针变量

fp = fopen("test", "a"); //以追加写入方式打开文件,若文件不存在则创建文件

if(fp == NULL) //判断文件是否打开成功

{

perror("File open error\r\n"); //输出错误信息

return -1; //返回错误代码

}

return 0; //返回正常代码

}

如果fopen函数调用失败,首先会打印“File open error”,然后会打印系统定义的错误信息,由于在之后的小节中仍旧会使用该函数,就不在此进行具体实验了。

3.8检查和复位状态

在调用 fread()进行文件数据读取时,如果返回值小于参数 nmemb 所指定的值,表示发生了错误或者已经到了文件末尾(文件结束 end-of-file),但 fread()无法具体确定是哪一种情况,在本小节将学习两个函数对该问题进行解决。

3.8.1 feof()函数 

feof()函数实验代码在配套资料“iTOP-3588开发板\03_【iTOP-RK3588开发板】指南教程\03_系统编程配套程序\13”目录下,如下图所示:

feof()函数是C标准库中的一个函数,用于判断文件指针所指向的文件是否已经到达文件结尾。所使用的头文件和函数原型,如下所示:

所需头文件

函数原型

1

#include <stdio.h>

 int feof(FILE *stream);

如果 end-of-file 标志被设置了,则调用 feof()函数将返回一个非零值,如果 end-of-file 标志没有被设置,则返回 0。当文件的读写位置移动到了文件末尾时,end-of-file 标志将会被设置。

feof()函数参数含义如下所示:

参数名称

参数含义

stream

FILE 指针

至此关于fread()函数的相关讲解就完成了,下面进行相应的实验。

实验要求:

使用feof()函数,分别测试读写位置移动到文件末尾和没有移动到文件末尾两种情况。

实验步骤:

首先进入到ubuntu的终端界面输入以下命令来创建demo13_feof.c文件,如下图所示:

vim demo13_feof.c

然后向该文件中添加以下内容: 

1 

2 

3 

4 

5 

6 

7 

8 

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

#include <stdio.h>

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

{

    FILE *fp;                     // 声明一个文件指针变量

    int ret;                      // 声明一个整型变量用于保存函数返回值

    char buffer[20] = {0};        // 声明一个大小为20的字符数组,用于存储从文件中读取的内容

    fp = fopen("test", "r+");     // 打开名为“test”的文件,使用“读写”模式

    if (fp == NULL)               // 如果文件指针为空,说明打开文件失败

    {

        perror("File open error\r\n");   // 输出错误信息

        return -1;                // 返回-1,表示程序运行失败

    }

    fread(buffer, sizeof(char), sizeof(buffer), fp);  // 从文件中读取数据,并存储到buffer数组中

    printf("buffer = %s\n", buffer);  // 输出从文件中读取的内容

    if (feof(fp))                // 判断文件指针是否已经移动到文件末尾

    {

        printf("Moved to end of file\r\n");  // 如果是,输出相应的提示信息

    }

    else                          // 否则说明还没有到文件末尾或者读取文件出错

    {

        printf("Not moved to end of file or error occurred\r\n");  // 输出相应的提示信息

    }

    ret = fclose(fp);            // 关闭文件

    if (ret != 0)                // 如果关闭文件失败,返回-2

    {

        perror("File close error\r\n");     // 输出错误信息

        return -2;

    }

    printf("File close success\r\n");  // 输出文件关闭成功的提示信息

    return 0;                    // 返回0,表示程序运行成功

}

上述代码在3.4小节中的实验基础上添加了17-24行feof()函数的判断,通过修改buffer[]缓冲区大小,测试读写位置移动到文件末尾和没有移动到文件末尾两种情况。

保存退出之后,使用以下命令对demo13_feof.c进行编译,编译完成如下图所示:

gcc -o demo13_feof demo13_feof.c

然后使用命令“vim test”创建test文件,并添加以下内容:

hello world!!

添加完成如下图所示:

然后使用命令“./demo13_feof”来运行,运行成功如下图所示: 

可以看到程序运行成功之后,会打印“Moved to end of file”证明读写指针已经移动到了文件的末尾,如果我们将第6行的buffer值进行修改,修改为10,再次运行对应的可执行文件之后,打印信息如下图所示:

可以看到上图的打印信息为“Not moved to end of file or error occurred”,证明读写指针并没有到达文件末尾,至此feof()函数就测试成功了。

3.8.2 ferror()函数 

ferror()函数实验代码在配套资料“iTOP-3588开发板\03_【iTOP-RK3588开发板】指南教程\03_系统编程配套程序\14”目录下,如下图所示:

ferror()函数是C标准库中的一个函数,如果错误标志被设置了,则ferror()函数会被调用,用于检查文件流的错误状态。所使用的头文件和函数原型,如下所示:

所需头文件

函数原型

1

#include <stdio.h>

int ferror(FILE *stream); 

如果错误标志被设置了则返回1,否则返回0。

ferror()函数参数含义如下所示:

参数名称

参数含义

stream

FILE 指针

至此关于fread()函数的相关讲解就完成了,下面进行相应的实验。

实验要求:

测试ferror()函数。

实验步骤:

首先进入到ubuntu的终端界面输入以下命令来创建demo14_ferror.c文件,如下图所示:

vim demo14_ferror.c

然后向该文件中添加以下内容 

#include <stdio.h>

int main(int argc, char *argv[])
{
    FILE *fp;                     // 声明一个文件指针变量
    int ret, num;                 // 声明整型变量用于保存函数返回值和读取的字符数
    char buffer[1024] = {0};      // 声明一个大小为1024的字符数组,用于存储从文件中读取的内容
    fp = fopen("test", "r+");     // 打开名为“test”的文件,使用“读写”模式
    if (fp == NULL)               // 如果文件指针为空,说明打开文件失败
    {
        perror("File open error\r\n");   // 输出错误信息
        return -1;                // 返回-1,表示程序运行失败
    }
    num = fread(buffer, sizeof(char), sizeof(buffer), fp);  // 从文件中读取数据,并存储到buffer数组中
    printf("buffer = %s\n", buffer);  // 输出从文件中读取的内容
    if (ferror(fp))              // 判断文件读取过程中是否出错
    {
        printf("Error to read the file\r\n");  // 如果有错误,输出相应的提示信息
    }
    else                          // 如果没有错误,说明读取文件成功
    {
        printf("No error in reading\r\n");    // 输出相应的提示信息
    }
    ret = fclose(fp);            // 关闭文件
    if (ret != 0)                // 如果关闭文件失败,返回-2
    {
        perror("File close error\r\n");     // 输出错误信息
        return -2;
    }
    printf("File close success\r\n");  // 输出文件关闭成功的提示信息
    return 0;                    // 返回0,表示程序运行成功
}

保存退出之后,使用以下命令对demo14_ferror.c进行编译,编译完成如下图所示:

gcc -o demo14_ferror demo14_ferror.c

然后使用命令“vim test”创建test文件,并添加以下内容:

hello world!!

添加完成如下图所示:

 然后使用命令“./demo14_ferror”来运行,运行成功如下图所示:

可以看到程序运行成功之后,会打印“No error in reading”证明读写没有错误,至此我们的feof()函数就测试成功了。

3.8.3 clearerr()函数 

当调用 feof()或 ferror()校验这些标志后,通常需要清除这些标志,避免下次校验时使用到的是上一次设置的值,此时可以手动调用 clearerr()函数清除标志。  

clearerr()函数所使用的头文件和函数原型,如下所示:

所需头文件

函数原型

1

#include <stdio.h>

void clearerr(FILE *stream); 

此函数类型为void,没有返回值,所以函数调用总是会成功。

clearerr()函数参数含义如下所示:

参数名称

参数含义

stream

FILE 指针

至此,关于clearerr()函数的讲解就完成了。由于clearerr()函数的使用较为简单,只要在 feof()或 ferror()函数后调用clearerr()函数即可,所以本小节不再进行相应的测试。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

蓝桥杯复习笔记

文章目录 gridflexhtml表格合并单元格 表单表单元素input类型 select h5文件上传拖拽apiweb Storage css块元素和行内元素转换positionfloat溢出显示隐藏外边距过渡和动画动画变形选择器属性选择伪类选择器 css3边框圆角边框阴影渐变text-overflow与word-wrap jsdom操作documen…

STL容器之unordered_set类

文章目录 STL容器之unordered_set类1、unordered系列关联式容器2、unordered_set2.1、unordered_set介绍2.2、unordered_set的使用2.2.1、unordered_set的常见构造2.2.2、unordered_set的迭代器2.2.3、unordered_set的容量2.2.4、unordered_set的增删查2.2.5、unordered_set的桶…

C++--this指针

this 指针是一个隐含于每一个成员函数中的特殊指针。它是指向一个正操作该成员函数的对象。当对一个对象调用成员函数时&#xff0c;编译程序先将对象的地址赋予this指针&#xff0c;然后调用成员函数。每次成员函数存取数据成员时&#xff0c;C编译器将根据 this 指针所指向的…

由于找不到msvcp100.dll,无法继续执行代码要如何处理?正确的msvcp100.dll修复

由于找不到msvcp100.dll,无法继续执行代码要如何处理&#xff1f;其实要处理这种dll文件丢失的问题&#xff0c;还是比较简单的&#xff0c;只要我们了解清楚这个msvcp100.dll文件&#xff0c;那么就可以快速的解决&#xff0c;好了&#xff0c;废话不多说&#xff0c;我们一起…

证件照小于30kb怎么弄?这个工具三步搞定

当我们需要将照片上传到各种平台时&#xff0c;常常会遇到图片文件大小限制的问题。无论是社交媒体平台还是工作需求&#xff0c;如果照片文件过大&#xff0c;系统会提示上传失败或无法上传。想要解决的这个问题&#xff0c;可以选择将图片压缩指定大小&#xff0c;比如图片压…

git操作码云(gitee)创建仓库到上传到远程仓库

想必有的小伙伴在为上传到码云远程仓库而感到烦恼吧&#xff01;本篇为大家详细讲解实现过程&#xff0c;跟着我的步伐一步一步来。 我就当大家已经注册好了码云 一、在码云上需要的操作 接下来我们需要使用到 git 了 二、git 上的操作 到了咋们的git了&#xff0c;开整 首…

代码浅析Point-LIO

0. 简介 对于最近出来的Point-LIO(鲁棒高带宽激光惯性里程计)&#xff0c;本人还是非常该兴趣的&#xff0c;为此花了一些时间重点分析了Point-LIO的代码&#xff0c;并研究了它相较于Fast-LIO2的区别 1. laserMapping.cpp 第一部分就是实现对激光雷达视场角的图像分割。首先…

Python学习从0到1 day24 第二阶段 SQL ① SQL基础语法

还是会再见的 —— 24.4.10 MySQL基础及常用操作博主已整理在了两个专栏中&#xff0c;具体查看博主两个专栏的文章 ① Mysql数据库 ② 深入学习MySQL数据库 DDL —— 数据库管理 DDL —— 数据表管理 DML 数据操作语言 数据插入 INSERT 数据删除 DELETE 数据更新 UPDATE 注意…

短剧在线搜索PHP网站源码

源码简介 短剧在线搜索PHP网站源码&#xff0c;自带本地数据库500数据&#xff0c;共有6000短剧视频&#xff0c;与短剧猫一样。 搭建环境 PHP 7.3 Mysql 5.6 安装教程 1.上传源码到网站目录中 2.修改【admin.php】中&#xff0c; $username ‘后台登录账号’; $passwor…

Vue-Router入门

现在的前后端分离项目&#xff0c;后端只管数据传递&#xff0c;视图跳转的活交由前端来干了&#xff0c;vue-router就是专门来干这个活的&#xff0c;它可以让页面跳转到指定组件 组件是可复用的 Vue 实例, 把一些公共的模块抽取出来&#xff0c;然后写成单独的的工具组件或者…

tdesign坑之EnhancedTable树形结构默认展开所有行

⚠️在官方实例中&#xff0c;树形结构的表格提供了2种方法控制展开全部节点&#xff1a; 一是通过配置属性tree.defaultExpandAll为true代表默认展开全部节点&#xff08;仅默认情况有效&#xff09;&#xff1b; 二是使用组件实例方法expandAll()可以自由控制树形结构的展开…

从零开始学Python(五)面向对象

&#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 接下来看看由辉辉所写的关于Python的相关操作吧 目录 &#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 一.类的定义 二.魔法方法 1.概念 2.常…

Bert基础(十二)--Bert变体之知识蒸馏原理解读

B站视频&#xff1a;https://www.bilibili.com/video/BV1nx4y1v7F5/ 白话知识蒸馏 在前面&#xff0c;我们了解了BERT的工作原理&#xff0c;并探讨了BERT的不同变体。我们学习了如何针对下游任务微调预训练的BERT模型&#xff0c;从而省去从头开始训练BERT的时间。但是&#…

物联网实验

实验1 基于ZStack光敏传感器实验 1.实验目的 我们通过上位机发指令给协调器&#xff0c;协调器把串口接收到的指令通过Zigbee协议无线发送给带有光敏传感器的终端节点&#xff0c;获取到数据以后把数据返回给上位机&#xff0c;实现无线获取数据的目的。 2.实验设备 硬件&a…

企业鸿蒙原生应用元服务备案实操包名公钥签名信息

一、鸿蒙应用/元服务如何查询包名&#xff1f; 登录 AppGallery Connect &#xff0c;点击“我的应用”&#xff0c;输入应用名称可查询到需要备案的鸿蒙应用/元服务包名。 二、鸿蒙应用/元服务如何获取公钥和签名信息&#xff1f; &#xff08;1&#xff09;登录 AppGaller…

【IC验证】类的一些问题

1、句柄悬空 在声明句柄和创建对象以后&#xff0c;句柄是悬空的&#xff0c;在仿真没开始时内容为null。但是对于结构体和module的例化&#xff0c;仿真开始之前变量就给了一个不确定的值&#xff08;32hxxxx&#xff09; 但是对于放在initial块里面的&#xff0c;在仿真之前…

龙蜥社区「人人都可以参与开源」——体验开源成为“开源人“

龙蜥社区「人人都可以参与开源」体验开源——让更多的人了解开源&#xff01; 龙蜥社区开源概述&#xff1a;龙蜥社区开源的探索过程:龙蜥社区收获总结:AtomGit评测:服务设计上:功能结构上:安全设计上: AtomGit测评总结: 龙蜥社区开源概述&#xff1a; 在追求技术的路上少不了…

【智能算法】人工电场算法(AEFA)原理及实现

目录 1.背景2.算法原理2.1算法思想2.2算法过程 3.结果展示4.参考文献 1.背景 2019年&#xff0c;A Yadav等人受库伦定律和运动定律启发&#xff0c;提出了人工电场算法&#xff08;Artificial Electric Field Algorithm&#xff0c;AEFA&#xff09;。 2.算法原理 2.1算法思…

二维相位解包理论算法和软件【全文翻译- DCT相位解包裹(5.3.2)】

5.3.2 基于 DCT 的方法 在本节中,我们将详细介绍如何通过 DCT 算法解决非加权最小二乘相位解缠问题,而不是通过FFT.我们将使用公式 5.53 所定义的二维余弦变换。我们开发的算法等同于 FFT 方法 2(第 5.3.1 节)。与 FFT 方法 I 等价的 DCT 算法也可以推导出来,但我们将其作…

selenium 如何获取 session 指定的数据

代码核心在于这几个部分&#xff1a; 其一&#xff1a;使用元素定位来获取页面上指定需要抓取的关键字&#xff1b; 其二&#xff1a;将页面上定位得到的数据永久存储到本地文件中。 具体来梳理一下从访问URL开始到爬取数据整个流程下来的各个节点我们都做了哪些工作。 我们来看…