C语言——文件操作(超全超详细)

news2024/11/26 22:22:44

C语言——文件操作

1. 什么是文件

磁盘上的文件是文件

但是在程序设计中,我们一般谈的文件有两种:程序文件、数据文件(从文件功能的角度来分类的)

1.1 程序文件

包括源程序文件(后缀为.c),目标文件(windows环境后缀为.obj),可执行程序(Windows环境后缀为.exe)

1.2 数据文件

文件的内容不一定是程序,而是程序运行时读写的数据,比如程序运行需要从中读取数据的文件,或者输出内容的文件

数据文件又分为文本文件和二进制文件

1.2.1 文本文件和二进制文件

数据在内存中以二进制的形式存储,如果不加转换的输出到外存,就是二进制文件

如果要求在外存上以ASCII码形式存储,则需要在存储前转换。以ASCII字符的形式存储的文件就是文本文件

例如对于整数10000,如果以ASCII码的形式输出到磁盘,则磁盘中占用5个字节(每个字符占一个字节),而二进制形式输出,则在磁盘上只占4个字节,如图所示

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-p0yl5SyM-1689748214043)(C:/Users/HUASHUO/AppData/Roaming/Typora/typora-user-images/image-20230716095024607.png)]

1.2.2 为什么要有文本文件

可能有小伙伴会问:文本文件只是二进制二进制文件的特殊形式,为什么要特殊照顾文本文件呢?

  1. 文本文件符合人类的阅读习惯、应用场景多,可以让人类简化操作
  2. 保障数据读写的真实意图,这样能在不同的系统里有较好的兼容性
  3. 可以有换行的概念‘\n’,字符有合法范围因此文件结束符可以特殊

1.3 文件名

一个文件对应一个唯一的文件标识(即文件名)

同一路径下不可能出现同名文件

文件名包含3部分:文件路径 + 文件名主干 + 文件后缀,例如:
注:文件名中不一定包含后缀名

文件路径又分为绝对路径和相对路径:

1.3.4 绝对路径和相对路径

文件的绝对路径是指从根目录开始到文件的完整路径,包括所有的目录层级。例如,Windows系统中的绝对路径可能是:“C:\Users\username\Documents\file.txt”

**相对路径是指相对于当前工作目录或者其他已知目录的路径。相对路径不包含根目录,而是使用特定的标识符来表示路径的位置关系。**例如,如果当前工作目录是"/home/username/Documents",那么相对路径"file.txt"表示文件位于当前工作目录下的文件"file.txt"。

在相对路径中,还可以使用特殊的标识符来表示位置关系。例如,"…“表示父级目录,”."表示当前目录。因此,如果当前工作目录是"/home/username/Documents",那么相对路径"…/file.txt"表示文件位于父级目录下的文件"file.txt"。

需要注意的是,相对路径是相对于当前工作目录或其他已知目录的路径,所以在不同的环境中可能会有不同的结果。因此,在编写代码或指定文件路径时,最好使用绝对路径来确保准确性和可移植性


2. C语言中的流

什么是流?

在C语言中,“流”(stream)是一种用于输入和输出数据的抽象概念。它是一种数据的传输方式,可以将数据从一个地方传送到另一个地方。在C语言中,输入流和输出流是通过一组标准库函数来实现的,这些函数允许程序从键盘或文件中读取数据,或者将数据写入到屏幕或文件中

C语言中的流可以分为标准流(standard streams)文件流(file streams)

注:C语言中操作流的主要函数是标准I/O库中的stdio.h头文件中定义的函数。

2.1 标准流

我们需要清楚,C语言程序,只要运行起来,就会默认打开3个流(标准流)

标准输入流(stdin):用于读取输入数据,默认情况下是键盘输入。
标准输出流(stdout):用于向终端或命令行窗口输出数据。
标准错误流(stderr):用于输出错误信息。

2.2 文件流

C语言中的文件流是一种用于在程序中读取和写入文件的流。通过文件流,可以在C程序中打开文件,从文件中读取数据或将数据写入文件中。这样可以有效地处理大量数据、持久性存储以及与文件系统的交互。


本次,我们重点讨论文件流

3. 文件指针

每个被使用的文件都在内存中开辟了一个相应的文件信息区,用来存放文件的相关信息(如文件的名字,文件状态及文件当前的位置等)。这些信息是保存在一个结构体变量中的。该结构体类型是由系统声明的,取名FILE

我们一般都是用过一个FILE的指针来维护这个FILE结构的变量,例如:

FILE* pf;	//文件指针变量

可以通过这个FILE指针pf来找到与这个文件对应的文件信息区


4. 文件的打开和关闭

在使用文件之前应该打开文件,使用完之后应该关闭文件

ANSIC规定用fopen来打开文件,用fclose来关闭文件

FILE * fopen ( const char * filename, const char * mode );	//打开文件
int fclose ( FILE * stream );	//关闭文件

打开方式mode如下:

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

注1:当文件打开失败出错时,会返回一个空指针,因此我们一定要在打开文件之后,对文件指针进行有效性检查
注2:对于打开进行更新的文件(包含“+”号的文件),允许输入和输出操作,在写入操作之后的读取操作之前,应刷新(fflush)或重新定位流(fseek,fsetpos,rewind)流应在读取操作之后的写入操作之前重新定位(fseek、fsetpos、rewind)(只要该操作未到达文件末尾)

例如:

#include<stdio.h>

int main()
{
    //此时该路径下没有名为data.txt的文件,因此会打开失败
	FILE* fp = fopen("data.txt", "r");
	if (NULL == fp)
	{
		perror("fopen");
		return 1;
	}

	fclose(fp);
	fp = NULL;

	return;
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YaOsfnMR-1689748214044)(C:/Users/HUASHUO/AppData/Roaming/Typora/typora-user-images/image-20230718153848882.png)]

#include<stdio.h>

int main()
{
    //用写的方式打开文件,如果文件不存在,会在该路径底下创建一个新的名为data.txt的文件
	FILE* fp = fopen("data.txt", "w");
	if (NULL == fp)
	{
		perror("fopen");
		return 1;
	}

	fclose(fp);
	fp = NULL;

	return;
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Uk2vLp1I-1689748214044)(C:/Users/HUASHUO/AppData/Roaming/Typora/typora-user-images/image-20230718154042168.png)]

在上面我们使用的都是与执行文件相同路径底下的文件,如果是其他路径的文件又该如何打开呢?

有两种方法:

方法一:使用相对路径

例如我们要打开Work_7.18.c上一级目录中,文件夹Debug中的名为data.txt的文件:

#include<stdio.h>

int main()
{
	FILE* fp = fopen("..\\Debug\\data.txt", "r");
    /*
    	..表示Work_7.18.c文件的上一级目录
    	Debug为该目录底下的文件夹
    */
    
	if (NULL == fp)
	{
		perror("fopen");
		return 1;
	}
	else
	{
		printf("SUCCESS\n");
	}

	fclose(fp);
	fp = NULL;

	return;
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oDPcA80s-1689748214044)(C:/Users/HUASHUO/AppData/Roaming/Typora/typora-user-images/image-20230718161248006.png)]

方法二:绝对路径

例如,我们要打开桌面上的名为data.txt的文件

#include<stdio.h>

int main()
{
	FILE* fp = fopen("C:\\Users\\HUASHUO\\Desktop\\data.txt", "r");
	if (NULL == fp)
	{
		perror("fopen");
		return 1;
	}
	else
	{
		printf("SUCCESS\n");
	}

	fclose(fp);
	fp = NULL;

	return;
}

注:本来,文件地址为"C:\Users\HUASHUO\Desktop\data.txt",但为了和转义字符做区分,应该在每一个反斜杠后面再加一个反斜杠:“C:\\Users\\HUASHUO\\Desktop\\data.txt”


5. 文件输入和文件输出的概念

可能有许多小伙伴会认为,文件的输入就是将数据写到文件里,文件的输出就是将文件的内容读取出来,然而事实却恰恰相反

文件输入(File Input)文件输入是指将外部文件中的数据读取到程序中进行处理的过程。

文件输出(File Output):是指将程序中的数据写入到外部文件中的过程。

我们也可以画一个图来表示这个关系:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9FhHZhaV-1689748214045)(C:/Users/HUASHUO/AppData/Roaming/Typora/typora-user-images/image-20230718190228428.png)]


6. 文件的顺序读写

6.1 顺序读写的函数

功能函数名适用于
字符输入函数fgetc所有输入流
字符输出函数fputc所有输出流
文本输入函数fgets所有输入流
文本输出函数fputs所有输出流
格式化输入函数fscanf所有输入流
格式化输出函数fprintf所有输出流
二进制输入fread文件
二进制输出fwrite文件

6.1.1 fgetc

int fgetc ( FILE * stream );
  • 返回文件指针当前指向的字符,然后文件指针向后移动一位
  • 如果文件指针位于文件末尾,那么就返回EOF,并为流设置 (feof) 的文件结束指示器
  • 如果文件读取错误,同样返回EOF,但改为设置其错误指示器 (ferror)

示例:

若在.c文件的路径下有一名为data.txt的文件,这个文件有字符串“abcdef”

#include<stdio.h>

int main()
{
	FILE* fp = fopen("data.txt", "r");
	if (NULL == fp)
	{
		perror("fopen");
		return 1;
	}
	
	char ch;
	while ((ch = fgetc(fp)) != EOF)
		printf("%c", ch);
	printf("\n");

	fclose(fp);
	fp = NULL;

	return;
}

output:

abcdef

6.1.2 fputc

int fputc ( int character, FILE * stream );
  • 将一个字符写入文件,然后文件指针向后移动一位
  • 如果写入成功,那么返回这个字符的ASCII值
  • 如果发生错误,则返回EOF

示例:

向同一文件逐个写入26个小写英文字符

#include<stdio.h>

int main()
{
	FILE* fp = fopen("data.txt", "w");
	if (NULL == fp)
	{
		perror("fopen");
		return 1;
	}

	char ch = 'a';
	char ret;
	for (int i = 0; i < 26; i++)
	{
		ret = fputc(ch + i, fp);
		printf("%c", ret);
	}

	fclose(fp);
	fp = NULL;

	return;
}

output:

abcdefghijklmnopqrstuvwxyz

6.1.3 fgets

char * fgets ( char * str, int num, FILE * stream );
  • 从流(stream)中读取字符,并以字符串的形式存储到str中,直到读够(num - 1)个字符,或到达换行符,或读到文件尾

  • 换行符‘\n’会使fgets停止读取,但换行符会被函数认为是有效字符,并存入str中

  • 束符‘\0’会成为第num个字符,添加到str末尾

  • 如果读取成功,则返回str

  • 如果在读取的过程中遇到文件尾,那么就设置 eof 指示器 (feof)

  • 如果没有读到任何字符就遇到文件尾,那么就返回空指针,设置 eof 指示器 (feof),str的内容不会改变

  • 如果读取错误,则设置错误指示器(ferror),同样返回空指针,但str的内容可能会改变

示例1:

从文件中读取26个小写字母

#include<stdio.h>

int main()
{
	FILE* fp = fopen("data.txt", "r");
	if (NULL == fp)
	{
		perror("fopen");
		return 1;
	}

	char ch[30] = {0};

	fgets(ch, 26 + 1, fp);

	puts(ch);

	fclose(fp);
	fp = NULL;

	return;
}

output:

abcdefghijklmnopqrstuvwxyz

示例2:

从文件读取以下内容:

123
456

output:

123
    
6.1.3.1 fgets和gets的区别

fgets

char * fgets ( char * str, int num, FILE * stream );

gets

char * gets ( char * str );
  • fgets接受流参数(标准输入流,文件流都可以),而gets只接受标准输入流
  • fets可指定读取的最大字符数
  • fgets会将换行符读入到str再结束读取,而gets碰到换行符就会停止读取,不会读入换行符

例如:

#include<stdio.h>

int main()
{
	char str1[20] = { 0 };
	char str2[20] = { 0 };

	gets(str1);
	fgets(str2, 5 + 1, stdin);

	return 0;
}

同时在标准输入流读入“abcd\n”,利用调试,可以发现二者区别

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bL2MbhyH-1689748214046)(C:/Users/HUASHUO/AppData/Roaming/Typora/typora-user-images/image-20230718195146834.png)]

6.1.4 fputs

int fputs ( const char * str, FILE * stream );
  • 将str中的字符串输出到流(stream)中,结束符‘\0’不会被写入
  • 如果输出成功,则返回非负值
  • 如果失败,则返回EOF,并设置错误指示器(ferror)

例如:

将字符串“abcdef”写入文件

#include<stdio.h>

int main()
{
	FILE* fp = fopen("data.txt", "w");
	if (NULL == fp)
	{
		perror("fopen");
		return 1;
	}

	char ch[] = "abcdef";

	int ret = fputs(ch, fp);
	printf("%d", ret);
    
    fclose(fp);
	fp = NULL;

	return;
}

output:

0
6.1.4.1 fputs和puts的区别

fputs:

int fputs ( const char * str, FILE * stream );

puts:

int puts ( const char * str );
  • fputs的输出对象可以被指定,而puts只能是标准输出流stdout
  • puts输出会自带一个换行符‘\n’,而fputs不会

例如:

#include<stdio.h>

int main()
{
	char str[] = "abcdef";

	puts(str);
	printf("HELLO");

	printf("\n");

	fputs(str, stdout);
	printf("HELLO");

	printf("\n");

	return 0;
}

output

abcdef
HELLO
abcdefHELLO

6.1.5 fscanf

int fscanf ( FILE * stream, const char * format, ... );
  • 以格式化的形式从流(stream)中读取数据

  • 成功后,该函数返回成功填充的参数列表的项数。此计数可以与预期的项目数匹配,也可以由于匹配失败、读取错误或文件末尾的到达而减少(甚至为零)。

  • 如果发生读取错误或在读取时到达文件末尾,则会设置正确的指示器(feof 或 ferror)。并且,如果在成功读取任何数据之前发生任一情况,则返回 EOF。

例如:

从文件中读取数字123和字符串“abcdef”

#include<stdio.h>

int main()
{
	FILE* fp = fopen("data.txt", "r");
	if (NULL == fp)
	{
		perror("fopen");
		return 1;
	}

	char str[10] = { 0 };
	int num = 0;

	fscanf(fp, "%d %s", &num, str);

	printf("%d\n%s\n", num,str);
    
    fclose(fp);
	fp = NULL;

	return;
}

output:

123
abcdef
6.1.5.1 scanf/sscanf/fscanf

scanf:

int scanf ( const char * format, ... );

sscanf:

int sscanf ( const char * s, const char * format, ...);

fscanf:

int fscanf ( FILE * stream, const char * format, ... );
  • 三者都是以格式化的形式读取数据
  • 三者在**遇到空格时会停止读取,且不会读取空格字符。**这是因为默认情况下,这些函数以空白字符(包括空格、制表符和换行符)作为输入字段的分隔符
  • scanf只能从标注输入流(stdin)读取,sscanf只能从字符串中读取,fscanf可以从标准输入流或文件流读取

例如:

文件内容为: 123 abcdef

#include<stdio.h>

int main()
{
	FILE* fp = fopen("data.txt", "r");
	if (NULL == fp)
	{
		perror("fopen");
		return 1;
	}

	int num1 = 0;
	int num2 = 0;
	int num3 = 0;

	char str1[20] = "123 abcdef";
	char str2[10] = { 0 };
	char str3[10] = { 0 };

	scanf("%d", &num1);

	sscanf(str1, "%d%s", &num2, str2);

	fscanf(fp, "%d%s", &num3, str3);

	printf("num1 = %d, str1 = %s\n", num1, str1);
	printf("num2 = %d, str2 = %s\n", num2, str2);
	printf("num3 = %d, str3 = %s\n", num3, str3);

	fclose(fp);
	fp = NULL;

	return 0;
}

input:

123

output:

num1 = 123, str1 = 123 abcdef
num2 = 123, str2 = abcdef
num3 = 123, str3 = abcdef

6.1.6 fprintf

int fprintf ( FILE * stream, const char * format, ... );
  • 以格式化的形式向流(stream)中输出数据

  • 成功后,将返回写入的字符总数

  • 如果发生写入错误,则设置错误指示器(ferror)并返回负数。

例如:

将数字123和字符串“abcdef”写入文件

#include<stdio.h>

int main()
{
	FILE* fp = fopen("data.txt", "w");
	if (NULL == fp)
	{
		perror("fopen");
		return 1;
	}

	char str[10] = "abcdef";
	int num = 123;

	int ret = fprintf(fp, "%d%s", num, str);

	printf("ret = %d\n", ret);
    
    fclose(fp);
	fp = NULL;

	return;
}

output:

ret = 9

注:如果在%d%f中加入一个空格,那么返回值就会加一

6.1.6.1 printf/sprintf/fprintf

printf:

int printf ( const char * format, ... );

sprintf:

int sprintf ( char * str, const char * format, ... );

fprintf:

int fprintf ( FILE * stream, const char * format, ... );
  • 三者都是以格式化的形式输出
  • print用于将格式化的数据输出到标准输出流(屏幕);sprintf用于将格式化的数据输出到字符串中;fprintf用于将格式化的数据输出到指定流。

例如:

#include<stdio.h>

int main()
{
	FILE* fp = fopen("data.txt", "w");
	if (NULL == fp)
	{
		perror("fopen");
		return 1;
	}

	int num1 = 10;
	int num2 = 10;
	int num3 = 0;

	char str1[10] = "abcdef";
	char str2[10] = { 0 };

	printf("num1 = %d\n", num1);

	sprintf(str2, "%s", str1);
	puts(str2);

	fprintf(fp, "%d %s", num1, str1);

	fclose(fp);
	fp = NULL;

	return 0;
}

outputs:

num1 = 10
abcdef

6.1.7 fread

size_t fread ( void * ptr, size_t size, size_t count, FILE * stream );
  • 以二进制的形式从流中读取count个元素,每个元素的大小为size字节,并将它们存储在 ptr 指定的内存块中。

  • 返回成功读取的元素总数。

  • 如果此数字与 count 参数不同,则表示读取时发生读取错误或到达文件末尾。在这两种情况下,都会设置正确的指标,可以分别用 ferror 和 feof 进行检查。

  • 如果sizecount为零,则该函数返回零,并且流状态和 ptr 指向的内容保持不变。

例如:

读取文件中的字符串“1200”

int main()
{
	FILE* fp = fopen("data.txt", "rb");
	if (NULL == fp)
	{
		perror("fopen");
		return 1;
	}

	int str[10] = {0};

	int ret = fread(str, sizeof(int), 1, fp);
	for (int i = 0; i < 10; i++)
		printf("%d ", str[i]);

	printf("\nret = %d\n", ret);
    
    fclose(fp);
	fp = NULL;

	return;
}

output:

808464945 0 0 0 0 0 0 0 0 0
ret = 1
  • 可能有小伙伴不理解为什么是这个结果,我们一起来分析:
  • 我们知道,fread是以二进制的形式读取文件中的信息,而文件中的1200是文本信息,每个字符对应的ASCII码为49,50,48,48,转换为二进制码:0011 0001 0011 0010 0011 0000 0011 0000
  • 再看看808464945的二进制形式:

  • 可以发现,数据竟然是倒着读取的,这里就又涉及到了小端字节序存储这一概念,文件前面的数据是低地址,后面的数据是高地址,而低位数据存储在低地址,高位数据存储在高地址,因此最终读取到的数据就要将文本信息倒着读

注:

对小端字节序存储该不太了解的同学请看这里👉传送门

在C语言中,文件的数据存储方式取决于计算机的体系结构和操作系统。通常情况下,对于大多数计算机系统,文件的数据是按照字节顺序存储的,这意味着在内存中,文件前面的数据存储在较低的地址,后面的数据存储在较高的地址

6.1.8 fwrite

size_t fwrite ( const void * ptr, size_t size, size_t count, FILE * stream );
  • 以二进制的形式将ptr存储的数据写入流中,一共写入count个元素,每个元素的大小为size字节。

  • 返回成功写入的元素总数

  • 如果此数字与 count 参数不同,则写入错误阻止函数完成。在这种情况下,将为流设置错误指示器(ferror)。

  • 如果sizecount为零,则该函数返回零,错误指示器保持不变。

例如:

向文件中写入字符串“abcdef”

#include<stdio.h>

int main()
{
	FILE* fp = fopen("data.txt", "wb");
	if (NULL == fp)
	{
		perror("fopen");
		return 1;
	}

	char str[] = "abcdef";

	int ret = fwrite(str, sizeof(char), strlen(str), fp);
	printf("%d\n", ret);

	fclose(fp);
	fp = NULL;

	return 0;
}

output:

6

7. 文件的随机读写

注1:当文件被打开时,文件指针默认值向文件的起始位置

注2:当文件以追加的方式打开时,不允许人为改变文件指针位置

7.1 fseek

根据文件位置和偏移量来定位文件指针

int fseek ( FILE * stream, long int offset, int origin );
  • offset为偏移量
  • origin为起始位置,有三种取值:

SEEK_SET:文件头

SEEK_CUR:文件指针的当前位置

SEEK_END:文件尾

  • 如果成功,则返回0,否则返回非零值
  • 如果发生读写错误,那么就设置错误指示器(ferror)。

例如:

先向文件写入26个小写英文字母,再从文件头偏移3个单位,写入字符串“DEF”

#include<stdio.h>

int main()
{
	FILE* fp = fopen("data.txt", "r+");
	if (NULL == fp)
	{
		perror("fopen");
		return 1;
	}
	
	char a = 'a';
	char str[30] = { 0 };
	for (int i = 0; i < 26; i++)
		fputc(a + i, fp);

	fseek(fp, 3, SEEK_SET);

	fprintf(fp, "%s", "DEF");

	fseek(fp, 0, SEEK_SET);
	
	fscanf(fp, "%s", str);
	puts(str);
	
	fclose(fp);
	fp = NULL;

	return 0;
}

output:

abcDEFghijklmnopqrstuvwxyz

7.2 ftell

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

long int ftell ( FILE * stream );

例如:

#include<stdio.h>

int main()
{
	FILE* fp = fopen("data.txt", "w");
	if (NULL == fp)
	{
		perror("fopen");
		return 1;
	}
	
	char a = 'a';
	for (int i = 0; i < 26; i++)
		fputc(a + i, fp);

	printf("%d\n", ftell(fp));
	
	fclose(fp);
	fp = NULL;

	return 0;
}

output:

26

7.3 rewind

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

void rewind ( FILE * stream );

例如:

#include<stdio.h>

int main()
{
	FILE* fp = fopen("data.txt", "w+");
	if (NULL == fp)
	{
		perror("fopen");
		return 1;
	}
	
	char str[30] = { 0 };

	for (int i = 0; i < 26; i++)
		fputc('a' + i, fp);

	rewind(fp);

	for (int i = 0; i < 10; i++)
		fputc('A' + i, fp);

	rewind(fp);

	fscanf(fp, "%s", str);
	puts(str);
	
	fclose(fp);
	fp = NULL;

	return 0;
}

output:

ABCDEFGHIJklmnopqrstuvwxyz

8. 文件读取结束的判定

牢记:在文件读取的过程中,不能使用feof函数的返回值直接来判断文件是否结束

feof的作用是:当文件读取结束的时候,判断是读取结束的原因是否是:遇到文件末尾

  • 文本文件读取是否结束:
    • fgetc判断返回值是否为EOF
    • fgets判断返回值是否为NULL
  • 二进制文件读取是否结束:
    • fread判断返回值是否小于实际要读的个数

本篇完

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

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

相关文章

椒图--分析中心

护网的时候我们要把右边的开关开启。开启就会对系统全量的记录&#xff0c;包含有网络行为日志&#xff0c;就会检测我们服务器里面的链接&#xff0c;端口箭头&#xff0c;内内网暴露的链接&#xff1b;进程操作日志&#xff0c;就可以看我们系统创建了哪些进程&#xff0c;就…

【操作系统】Liunx项目自动化构建工具-make/Makefile

Yan-英杰的主页 悟已往之不谏 知来者之可追 C程序员&#xff0c;2024届电子信息研究生 目录 一、背景 二、Makefile 实现 Makefile依赖 依赖关系 makefile的工作原理 项目清理 补充&#xff1a; .PHONY是什么&#xff1f; Linux如何进行多行注释&#xff1a; 说明&#xf…

app 元素定位失败了,怎么办?一看我的做法,惊呆了!

粉丝们在日常的android app自动化测试工作当中&#xff0c;元素定位时会遇到以下类似的报错&#xff1a; 然后来问博主&#xff0c;这是啥情况&#xff1f; 我一般都会送上亲切的关怀&#xff1a; 1&#xff09;adb能识别到设备吗&#xff1f; 2&#xff09;设备有被其它的程…

VUE+element Input框 实现输入内容可自适应文本高度,换行(空格换行,enter发送)阻止文本域的回车事件

需求 输入框实现输入内容自适应高度 以及可以换行 使用官方文档提供的属性 代码 <el-input clearable autosize type"textarea" :placeholder"$t(navbar.pleaseInput)"v-model"inputText" change"inputChange" keyup.enter.na…

数据分析之Matplotlib

文章目录 1. 认识数据可视化和Matplotlib安装2. 类型目录3. 图标名称title4. 处理图形中的中文问题5. 设置坐标轴名称&#xff0c;字体大小&#xff0c;线条粗细6. 绘制多个线条和zorder叠加顺序7. 设置x轴刻度xticks和y轴刻度yticks8. 显示图表show9. 设置图例legend10. 显示线…

Ceph简介及部署

Ceph Ceph一、存储基础1、单机存储设备2、Ceph 简介3、Ceph 优势5、Ceph 架构6、Ceph 核心组件7、OSD 存储后端8、Ceph 数据的存储过程9、Ceph 版本发行生命周期10、Ceph 集群部署 二、部署ceph-deploy Ceph 集群前环境配置1、关闭 selinux 与防火墙2、根据规划设置主机名3、配…

全网火爆,pytest自动化测试框架从0-1精通实战,你的进阶之路...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、运行方式 命令…

(68Ga)Nota-prgd2,1345968-02-6,通过镓标记的NOTA衍生物

文章编辑来自于&#xff1a;陕西新研博美生物科技有限公司MISS.wu​ (68Ga)Nota-prgd2| CAS&#xff1a;1345968-02-6| 纯度&#xff1a;95% PART1-----(68Ga)Nota-prgd2结构式 PART2-----试剂参数信息 CAS&#xff1a;1345968-02-6 外观&#xff08;Appearance&#xff09;…

网络安全(黑客)学习笔记

0基础学网安或者提升巩固网安技术的小伙伴有福了&#xff01; 本篇整合了网络安全全知识点&#xff0c;零基础也适用&#xff01; 本篇涵盖内容及其全面&#xff0c;强烈推荐收藏&#xff01; 一、学习网络安全会遇到什么问题呢&#xff1f; 1、学习基础内容多时间长 2、难…

周报(1)

文章预览&#xff1a; 本周内容&#xff1a;Python语言的学习和pytorch安装配置1 Python基础知识1.1 交互式解释器1.2 数和表达式1.3 变量1.4 获取用户输入1.5 函数1.6 模块1.7 字符串1.7.1 单引号字符串以及对引号转义1.7.2 拼接字符串1.7.3 字符串表示str 和repr Pytorch 的安…

vue 限制表情输入

在main.js中加入下列代码 import emoji from ./util/emojiVue.directive(emoji,emoji) 在util文件夹中加入emoji.js 下列代码 const findEle (parent, type) > { return parent.tagName.toLowerCase() type ? parent : parent.querySelector(type)}const emoji {bi…

vite vue3进行多环境打包配置

需求&#xff1a; 对此vite创建的vu3项目进行构建&#xff0c;项目分为四个环境&#xff1a;本地、测试、预发、生产 1.在项目根目录创建四个文件夹 .env.development .env.test .env.pre .env.production 2.配置不同环境的 地址和打包文件名 具体例子如下&#xff1a; …

手机验证码登录 -- 手把手教你做ssm+springboot入门后端项目黑马程序员瑞吉外卖(七)

文章目录 前言一、短信发送1. 短信服务介绍2. 阿里云短信服务3. 代码开发 二、手机验证码登录1. 需求分析2. 数据模型3. 代码开发4. 功能测试 总结 前言 为了巩固所学的知识&#xff0c;作者尝试着开始发布一些学习笔记类的博客&#xff0c;方便日后回顾。当然&#xff0c;如果…

项目名称:网络聊天室

目录 一&#xff0c;简述 二&#xff0c;项目要求 三&#xff0c;程序流程图 服务器端&#xff1a; 客户端&#xff1a; 四&#xff0c;相关知识点 通信流程&#xff1a; 函数接口&#xff1a; 五&#xff0c;代码实现 客户端&#xff1a; 服务器&#xff1a; 主程序…

Android性能优化——启动优化

App 的启动速度是用户的第一体验&#xff0c;互联网中有一个八秒定律&#xff0c;如果用户等待八秒App 还没打开&#xff0c;70%的用户都会停止等待 一、启动分类 官方 App startup time 冷启动 耗时最多&#xff0c;衡量标准 热启动 最快。 后台&#xff5e;前台 温启动…

Git 新建本地仓库,推送到远程仓库

1、在项目的根目录右键 Git Bash Here 打开目录下的 git 命令 2、输入 git init 回车&#xff0c;初始化项目&#xff0c;把这个项目变成一个Git可以管理的仓库 项目根目录出现 .git 隐藏文件夹。这个目录是Git来跟踪管理版本库的&#xff0c;没事千万不要手动修改这个目录里面…

MateBook E Go Wi-Fi性能版(GK-W76)工厂模式win11原厂系统,含F10智能恢复功能

HUAWEI华为MateBook E平板笔记本电脑(GK-W76)原装出厂Windows11系统包&#xff0c;带F10一键智能还原 系统自带所有驱动、出厂主题壁纸LOGO、Office办公软件、华为电脑管家等预装程序 所需要工具&#xff1a;16G或以上的U盘 文件格式&#xff1a;zip 文件大小&#xff1a;1…

Linux基础(三)端口、进程及主机状态管理、环境变量、文件管理

目录 端口 nmap netstat 进程管理 查看进程 关闭进程 主机状态监控 系统资源top命令 磁盘信息监控 网络状态监控 环境变量 $符号 自己设置环境变量 自定义环境变量PATH Linux的文件和下载 压缩和解压 tar命令 zip和unzip命令 端口 每个电脑有一个ip地址&#xff…

自动化测试(一):网页结构分析与Google翻译2023.7.18爬虫实例

目录 1. 网页分析1.1 静态网页1.2 静态网页的爬取案例1.3 动态网页1.4 Google翻译2023.7.18爬虫实例1.4.1 基于网页分析的Google翻译2023.7.18爬虫实例1.4.2 基于Selenium的Google翻译2023.7.18爬虫实例 1. 网页分析 网页分析即通过检查元素&#xff0c;确定想提取的内容的区域…

pyright 的配置方法

珍惜发量,拥抱python&#x1f602; 可以很快的构建一个平台管理程序,嵌入式设备,芯片厂商&#xff0c;都是python 的示例代码了 Lua 真的很棒&#xff0c;值得嵌入式领域的推广 实时性要求不高的&#xff0c;嵌入式设备,可以考虑lua python PC 的程序 ,python/Rust/C &#xf…