高阶C语言|C语言文件管理--输入输出流

news2024/12/28 18:47:49

在这里插入图片描述

文件管理

  • 一、为什么使用文件
  • 二、什么是文件
    • 2.1程序文件
    • 2.2数据文件
    • 2.3文件名
  • 三、文件的打开和关闭
    • 3.1文件指针
    • 3.2文件的打开和关闭
  • 四、文件的顺序读写
    • 4.1顺序读写函数介绍
      • 4.1.1fgetc
      • 4.1.2fputc
      • 4.1.3fgets
      • 4.1.4fputs
      • 4.1.5fscanf
      • 4.1.6fprintf
      • 4.1.7fread
      • 4.1.8fwrite
    • 4.2对比一组函数
      • 4.2.1sscanf
      • 4.2.2sprintf
      • 4.2.3函数对比
  • 五、文件的随机读写
    • 5.1fseek
    • 5.2ftell
    • 5.3rewind
  • 六、文本文件和二进制文件
  • 七、文件读取结束的判定
    • 7.1feof & perror
  • 八、文件缓冲区

一、为什么使用文件

我们前面已经介绍了结构体,也学习了通讯录,存在一个问题就是,每次通讯录程序退出,之前写好的信息都没了,下次进入通讯录,又得重新输入信息,这样的通讯录使用起来就很难受。那么怎样可以使数据保留下来,这里就涉及到了数据持久化的问题,数据持久化的方法有,把数据存放在磁盘文件、存放到数据库等方式。
这里使用文件我们可以将数据直接存放在电脑的硬盘上,文件在我们的硬盘上(C盘,D盘等),将数据存放到文件当中,就是存放到硬盘上,做到了数据的持久化。

二、什么是文件

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

2.1程序文件

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

2.2数据文件

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

在以前各章所处理数据的输入输出都是以终端为对象的,即从终端的键盘输入数据,运行结果显示到显示器上。
其实有时候我们会把信息输出到磁盘上,当需要的时候再从磁盘上把数据读取到内存中使用,这里处理的就是磁盘上文件。

2.3文件名

一个文件要有一个唯一的文件标识,以便用户识别和引用。
文件名包含3部分:文件路径+文件名主干+文件后缀
例如:c:\code\test.txt 为了方便起见,文件标识常被称为文件名。

三、文件的打开和关闭

3.1文件指针

缓冲文件系统中,关键的概念是"文件类型指针",简称"文件指针".
每个被使用的文件都在内存中开辟一个相应的文件信息区,用来存放文件的相关信息(如文件的名字,文件状态及文件当前的位置等)。这些信息是保存在一个结构体变量中的。该结构体类型是由系统声明的,取名FILE。
在这里插入图片描述

每当打开一个文件的时候,系统会根据文件的情况自动创建一个FILE结构的变量,并填充其中的信息,FILE是结构体类型,那用该结构体类型定义的文件指针就是用来维护着文件信息区(即FILE结构体变量),文件信息区会返回起始地址由文件指针来维护,通过访问文件信息区的内容就能访问该文件的内容。也就是说通过文件指针变量能够找到与它关联的文件。
以下是VS2022编译环境提供的stdio.h头文件中的文件类型申明:

typedef struct _ibouf
{
	char* ptr;
	int buffer;
}FILE;
FILE* p;//文件指针变量

3.2文件的打开和关闭

文件在读写之前应该先打开文件,在使用结束之后应该关闭文件。
在编写程序的时候,打开文件的同时就会返回一个FILE*的指针变量指向该文件,建立了指针和文件的关系。
ANSIC规定用fopen函数来打开文件,fclose来关闭文件。

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

文件的打开方式:
在这里插入图片描述
这里的输入数据指的是文件/屏幕中的数据输入到程序上,即从文件/屏幕读取数据。输出数据指的是程序中的数据输出到文件/屏幕中,即向文件/屏幕写入数据。带有r的形式去读取文件,而文件本身不存在时,就会出错,不会建立一个新的文件,会返回NULL,而去写或追加数据到文件中,而文件不存在时,都会自动建立一个新的文件。
在这里插入图片描述
示例:

#include <stdio.h>
int main()
{
	FILE* pFile;
	//打开文件
	pFile = fopen("myfile.txt", "w");
	//文件操作
	if (pFile != NULL)
	{
		fputs("fopen example", pFile);
		//关闭文件
		fclose(pFile);
	}
	return 0;
}

以w的形式向文件myfile.txt写入数据,目前我们原本的路径中没有这个文件,而文件名以这种形式写表明的意思执行程序时,在当前程序所在的目录下创建一个myfile.txt的文件,这种文件形式是绝对路径(当前目录下)
还有一种是指定在哪创建文件就在哪的方式叫做相对路径(任意目录下),例如:c:\code\test.txt。
当然fopen只是打开文件,这只是一种打开文件形式,但还不是真的写,fputs在文件打开的基础上才能真正的写入数据。
程序未执行前,当前目录下是没有该文件,程序执行后,就会生成一个改文件。如何找到当前目录?
在这里插入图片描述
找到打开后
在这里插入图片描述
程序执行后
在这里插入图片描述
以记事本的形式打开改文件,就可以看到刚刚写入的内容。
在这里插入图片描述
接下来,我们进行讨论类似fputs读写函数的介绍。

四、文件的顺序读写

4.1顺序读写函数介绍

在这里插入图片描述

这里涉及到流,什么是流?
流是一种抽象概念,例如:水流,表示水的运动状态,沿着某一路径运动的现象。这里的流用来表示数据流,表示对数据的输入输出进行处理的方式,使得程序可以以连续的方式读取或写入数据。
C语言程序只要运行起来,默认就打开3个流:
1.标准输入流stdin–从键盘输入
2.标准输出流stdout–输出到屏幕上、终端,主要是给用户看
3.标准错误流stderr–用于输出程序运行时的错误和诊断信息的一种特殊流
所有输入流、输出流包含标准输入、输出流,文件输入、输出流等。

4.1.1fgetc

在这里插入图片描述

fgetc函数用于从指定的流(stream)中获取一个字符。它返回当前被内部文件位置指示器指向的字符,并将该指示器前移至下一个字符。即读取完一个字符后,光标会移向后一位,等待下一次读取
参数说明:
stream:要读取的文件流。
返回值:
函数返回值为读取的字符的整数表示。如果发生错误或到达文件末尾,返回值为EOF(End of File)。并设置流的文件结束指示器(feof)。如果发生读取错误,函数将返回EOF并设置流的错误指示器(ferror)。

#include <stdio.h>
int main()
{
	FILE* pFile;
	//打开文件
	pFile = fopen("myfile.txt", "r");//从文件中读取数据
	//文件操作
	if (pFile != NULL)
	{
		int c = fgetc(pFile);
		printf("%c", c);
		//关闭文件
		fclose(pFile);
	}
	return 0;
}

运行结果:
在这里插入图片描述
在这里插入图片描述

#include <stdio.h>
int main()
{
	FILE* pFile;
	//打开文件
	pFile = fopen("myfile.txt", "r");
	//文件操作
	if (pFile != NULL)
	{
		char pc[10]="abcdefg";
		int num = 3;
		while (num--)
		{
			int c = fgetc(pFile);//将数组中的内容写入文件流中
			printf("%c", c);
		}
		

		//关闭文件
		fclose(pFile);
	}
	return 0;
}

运行结果:
在这里插入图片描述

4.1.2fputc

在这里插入图片描述

fputc()是C语言标准库函数之一,用于将一个字符写入文件流中,并在写入后将流的位置指示器自动前进一位。
参数说明:
character:要写入的字符。
stream:文件流指针,指向要写入的文件。
返回值:
如果成功写入字符,则返回写入的字符的无符号值(unsigned char)。
如果发生错误,则返回EOF。

#include <stdio.h>
int main()
{
	FILE* pFile;
	//打开文件
	pFile = fopen("myfile.txt", "w");
	//文件操作
	if (pFile != NULL)
	{
		int c = fputc('y', pFile);//将字符y写入到pFile所指向的文件中去
		printf("%c", c);

		//关闭文件
		fclose(pFile);
	}
	return 0;
}

执行程序前:
在这里插入图片描述
执行结果后:
在这里插入图片描述

4.1.3fgets

在这里插入图片描述

fgets()是C语言标准库函数之一,用于从文件流中读取字符串并存储到字符数组中。
参数说明:
str:指向目标字符数组的指针,用于存储读取的字符串。
num:要读取的最大字符数(包括末尾的空字符),通常是目标字符数组的长度。
stream:文件流指针,指向要读取的文件。
返回值:
如果成功读取字符串,则返回指向目标字符数组的指针(即str参数)。
如果发生错误或已到达文件末尾,则返回NULL。

#include <stdio.h>
int main()
{
	FILE* pFile;
	//打开文件
	pFile = fopen("myfile.txt", "r");
	//文件操作
	if (pFile != NULL)
	{
		char pc[10];
		char* c = fgets(pc,6, pFile);//从文件流中读取6个字符到数组pc,返回指向pc的指针
		printf("%s", pc);

		//关闭文件
		fclose(pFile);
	}
	return 0;
}

文件中本身内容:
在这里插入图片描述
运行结果:
在这里插入图片描述

4.1.4fputs

在这里插入图片描述

fputs()是C语言标准库函数之一,用于将字符串写入文件流中。
参数说明:
str:指向要写入的字符串的指针。
stream:文件流指针,指向要写入的文件。
返回值:
如果成功写入字符串,则返回非负值。
如果发生错误,则返回EOF。

#include <stdio.h>
int main()
{
	FILE* pFile;
	//打开文件
	pFile = fopen("myfile.txt", "w");
	//文件操作
	if (pFile != NULL)
	{
		char pc[10]="abcdefg";
		fputs(pc, pFile);//将数组中的内容写入文件流中
		printf("%s", pc);

		//关闭文件
		fclose(pFile);
	}
	return 0;
}

运行前:
在这里插入图片描述
运行后:
在这里插入图片描述

4.1.5fscanf

在这里插入图片描述

fscanf()是C语言标准库函数之一,用于从文件流中按格式读取数据并存储到指定的变量中。
参数说明:
stream:文件流指针,指向要读取的文件。
format:格式字符串,指定了要读取的数据的格式。
…:可变参数列表,指定了要读取的数据存储的位置。
返回值:
如果成功读取数据,则返回成功读取的参数个数。
如果发生错误或已到达文件末尾,则返回EOF。
空格会被作为分隔符,跳过输入时的空白字符(包括空格、制表符和换行符),直到找到一个非空白字符或达到文件末尾。

#include <stdio.h>
int main() {
    int num1;
    char str[100];

    FILE* file = fopen("example.txt", "r");
    if (file == NULL) {
        printf("文件打开失败");
            return 1;
    }

    int result = fscanf(file, "%d %s", &num1, str);//从文件中以%d %s的格式读取数据到num1,str中
    if (result != 2) {
        printf("读取文件失败");
            fclose(file);
        return 1;
    }

    printf("成功读取整数:%d", num1);
        printf("成功读取字符串:%s", str);

            fclose(file);
    return 0;
}

执行结果:
在这里插入图片描述
在这里插入图片描述

4.1.6fprintf

在这里插入图片描述

fprintf()是C语言标准库函数之一,用于将格式化的数据写入文件流中。
参数:
stream: FILE类型的指针,表示要写入的目标流。可以是标准输出流(如stdout)或文件流(通过fopen函数打开的文件流),甚至可以是网络连接的套接字。
format: const char类型的指针,表示格式化的字符串,指定了数据的输出格式和位置。它类似于printf函数中的格式化字符串。
…: 可变参数列表,用于填充格式化字符串中的格式控制符。这些参数的类型和顺序必须与格式化字符串中的格式控制符相匹配。
返回值:
int类型的返回值表示成功写入的字符数,如果出现错误则返回负值。常见的返回值有:
正整数:表示成功写入的字符数,其中正数表示已写入的字符数。
0:表示没有成功写入任何字符。
负数:表示发生了错误,具体的负值代表不同的错误类型。

#include <stdio.h>
int main() {
    int num1=2;
    char str[6]= "abcde";

    FILE* file = fopen("myfile.txt", "w");
    if (file != NULL)
    {
        int a = fprintf(file, "%d %s", num1, str);//以%d %s的形式向文件输入数据
        fclose(file);
    }   
    return 0;
}

运行结果:
在这里插入图片描述

4.1.7fread

在这里插入图片描述

fread函数是C语言标准库中的一个输入函数,用于从文件流中读取数据块。
参数说明:
ptr:指向要存储读取数据的内存块的指针。
size:每个元素的大小(以字节为单位)。
count:要读取的元素个数。
stream:要读取的文件流。
返回值:
函数返回值为实际成功读取的元素个数。如果发生错误或到达文件末尾,返回值可能小于count。

#include <stdio.h>
int main()
{
	FILE* file = fopen("myfile.txt", "rb");//以二进制形式读取
	if (file != NULL)
	{
		char buffer[10] = { 0 };
		fread(buffer, sizeof(char), 4, file);//从文件流中读取4个大小为sizeof(char)的元素到buffer中
		int i = 0;
		for (i = 0; i < 10; i++)
		{
			printf("%c ", buffer[i]);
		}

		fclose(file);
	}
	return 0;
}

运行结果:
在这里插入图片描述
在这里插入图片描述

4.1.8fwrite

在这里插入图片描述

fwrite函数用于将数据块写入流中。
参数说明:
ptr:指向要写入数据的内存块的指针。
size:每个元素的大小(以字节为单位)。
count:要写入的元素数量。
stream:表示流的 FILE 对象的指针。
返回值:
返回值是一个 size_t 类型的值,表示成功写入的元素个数。如果返回值等于 count,则表示所有元素都成功写入;如果返回值小于 count,则表示部分或者没有元素被写入。

#include <stdio.h>
int main()
{
	FILE* file = fopen("myfile.txt", "wb");//以二进制形式写入
	if (file != NULL)
	{
		char buffer[10] = "abcdef";
		fwrite(buffer, sizeof(char), 6, file);//从buffer中取出6个大小为sizeof(char)的元素到文件流中
		fclose(file);
	}
	return 0;
}

在这里插入图片描述

4.2对比一组函数

4.2.1sscanf

在这里插入图片描述

参数说明:
s:要从中读取数据的字符串。
format:指定数据格式的格式字符串。
其他额外的参数:用来接收解析出的数据
返回值:
函数返回一个 int 类型的值,表示成功解析并存储的参数个数。如果返回值小于期望的参数个数,则可能存在解析错误。
用法跟fscanf差不多,但不适用于标准输入流

#include <stdio.h>
int main() {
    char name[20];
    int age;
    float height;

    char str[] = "John 25 1.75";

    // 使用 sscanf 解析字符串
    int num = sscanf(str, "%s %d %f", name, &age, &height);//从str读取字符串到name,age,height中

    if (num == 3) 
    {
        printf("Name: %s", name);
        printf("Age: %d", age);
        printf("Height: %.2f ", height);
    }
    else 
    {
        printf("Failed to parse the input string. ");
    }

    return 0;
}

运行结果:
在这里插入图片描述

4.2.2sprintf

在这里插入图片描述

sprintf 函数用于将格式化的数据写入字符串中,而不是打印到标准输出。它与 printf 函数非常相似,但是将结果存储在提供的字符串缓冲区中。
参数说明:
str:指向要写入的字符串缓冲区的指针。
format:格式化字符串,指定输出的格式。
…:额外的参数,用于填充格式化字符串中的占位符。
返回值:
函数的返回值是写入字符串的字符数(不包括终止空字符 \0)。如果发生错误,则返回负数。

#include <stdio.h>
int main() {
    char buffer[50];
    int value = 123;
    float floatValue = 3.14;
    // 使用 sprintf 将格式化数据写入字符串缓冲区
    int numWritten = sprintf(buffer, "Value: %d, Pi: %.2f", value, floatValue);//将格式化的数据写入buffer中
    printf("Formatted string: %s\n", buffer);
    printf("Number of characters written: %d", numWritten);
    return 0;
}

在这里插入图片描述

4.2.3函数对比

scanf/fscanf/sscanf
输入源:
scanf函数从标准输入流(stdin)中读取数据。
fscanf函数从指定的文件流(FILE *stream)中读取数据。
sscanf函数从一个字符串(const char *str)中读取数据。
函数原型:
scanf的函数原型是int scanf(const char *format, …)
fscanf的函数原型是int fscanf(FILE *stream, const char *format, …)
sscanf的函数原型是int sscanf(const char *str, const char *format, …)
功能:
scanf、fscanf和sscanf都用于按照指定格式解析输入数据,并将解析结果存储到对应的变量中。
它们都返回成功匹配和赋值的参数个数。
输入错误处理:
scanf、fscanf和sscanf在解析输入数据时,如果遇到与指定格式不匹配的情况,会停止解析,并返回已成功匹配和赋值的参数个数。
可以通过检查返回值来判断是否成功解析了预期的参数个数。

printf/fprintf/sprintf
输出位置:
printf:输出到标准输出设备(通常是控制台)。
fprintf:输出到指定的文件。
sprintf:输出到字符数组作为结果保存。
函数原型:
printf:int printf(const char *format, …)
fprintf:int fprintf(FILE *stream, const char *format, …)
sprintf:int sprintf(char *str, const char *format, …)
功能和用途:
printf:主要用于将格式化的数据输出到控制台供用户查看。
fprintf:主要用于将格式化的数据输出到文件,可以用于日志记录等。
sprintf:主要用于将格式化的数据转换为字符串并保存在字符数组中,可以用于字符串构建、打印到日志等。
参数和返回值:
printf 和 fprintf:接受格式化字符串作为第一个参数,后续参数为要填充到格式化字符串中的值。返回成功输出的字符数,若发生错误则返回负值。
sprintf:接受一个字符数组作为第一个参数,后续参数与 printf 相同。返回成功输出的字符数,不包括结尾的空字符’\0’。若发生错误则返回负值。
输出结果处理:
printf:直接将结果输出到标准输出设备,不保存输出结果。
fprintf:直接将结果输出到指定文件,不保存输出结果。
sprintf:将结果输出到字符数组中并保存,可以通过访问该字符数组获取输出结果。

五、文件的随机读写

5.1fseek

在这里插入图片描述

fseek 函数用于设置流的位置指示器到一个新的位置。
参数说明:
stream:指向要定位的流的指针。
offset:偏移量,用于指定新位置相对于起始位置的偏移量。
origin:指定起始位置的参考点。可选值有:
SEEK_SET:从文件开头开始计算偏移量。
SEEK_CUR:从当前位置开始计算偏移量。
SEEK_END:从文件末尾开始计算偏移量。
返回值:
fseek 函数的返回值是一个整数,表示操作的成功与否。

#include <stdio.h>
int main()
{
	FILE* pFile;
	pFile = fopen("myfile.txt", "wb");
	fputs("this is an apple.", pFile);
	fseek(pFile, 9, SEEK_SET);//起始位置文件开头,偏移量为9
	fputs(" sam", pFile);
	fclose(pFile);
	return 0;
}

运行结果:
在这里插入图片描述

5.2ftell

在这里插入图片描述

ftell 函数的作用是获取流的当前位置指示器的值。
参数:
stream:指向 FILE 结构的指针,代表要获取当前位置指示器值的流对象。
返回值:
long int:表示当前位置指示器的值。对于二进制流,该值是从文件开头算起的字节数;对于文本流,该值可能没有实际意义。

#include <stdio.h>
int main()
{
	FILE* pFile;
	long size;
	pFile = fopen("myfile.txt", "rb");
	if (pFile == NULL)
	{
		perror("pFile");
	}
	else
	{
		fseek(pFile, 0, SEEK_END);//起始位置为文件末尾,偏移量为0
		size = ftell(pFile);
		fclose(pFile);
		printf("%ld", size);
	}
	return 0;
}

运行结果:
在这里插入图片描述
在这里插入图片描述

5.3rewind

在这里插入图片描述

rewind 函数的作用是将流的位置指示器设置到文件开头。
stream:要操作的流的指针,通常是使用 fopen 函数返回的文件指针。
没有特定的返回值

int main()
{
	char n;
	FILE* pFile;
	char buffer[27];
	pFile = fopen("myfile.txt", "w+");//建立一个可读可写的文件
	for (n = 'A'; n <= 'z'; n++)
		fputc(n, pFile);//将26个字母输入到文件中去
	rewind(pFile);//光标移到了最后一位,调用rewind使光标回到起始位置
	fread(buffer, 1, 26, pFile);//读取文件中的字符到buffer数组中
	fclose(pFile);
	buffer[26] = '\0';//在数组末尾放入'\0'以便打印
	puts(buffer);//输出数组中的内容	
	return 0;
}

运行结果:
在这里插入图片描述

六、文本文件和二进制文件

数据文件被称为文本文件和二进制文件。
数据在内存中以二进制形式存储,如果不加以转换输出到外存,就是二进制文件。
如果在外存上是以ASCLL码字符的形式存储那就是文本文件

#include <stdio.h>
int main()
{
	int a = 10000;;
	FILE* pFile;
	pFile = fopen("myfile.txt", "wb");//打开一个文件,用于存储二进制的数据
	if (pFile != NULL)
	{
		fwrite(&a, 4, 1, pFile);
		fclose(pFile);
	}
	
	return 0;
}

当我们写入的数据是以二进制的形式存储,这个时候打开文件发现它是乱码的,明明写入的a是10000,但却是看不懂的符号,因为我们目前打开的文件是文本文件,不能够解读二进制数据。那么我们可以通过编译器去解读二进制文件。
在这里插入图片描述
在源文件中将我们的现有项文件导过来
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
右击该文件,选择打开方式,选择二进制编辑器
在这里插入图片描述

在这里插入图片描述
这个时候就会解读二进制数据,会以十六进制显示该数据
在这里插入图片描述

七、文件读取结束的判定

7.1feof & perror

在这里插入图片描述

feof() 函数用于检查给定文件流的文件结束标志是否已设置。它接受一个指向 FILE 对象的指针作为参数,并在文件结束标志被设置时返回一个非零值,表示文件已完全读取。

在这里插入图片描述

perror()函数用于将errno的值解释为错误消息,并将其打印到stderr(标准错误输出流,通常是控制台)

因此不能直接使用feof来判断文件的是否结束,因为文件可能因为遇到错误而导致读取结束,这时就要用perror来判断。

#include <stdio.h>
int main()
{
	int c;
	FILE* fp = fopen("myfile.txt", "r");
	if (!fp)
	{
		perror("fp");
		return -1;
	}
	//fgetc当读取失败的时候或者遇到文件结束的时候,就会返回EOF
	while ((c = fgetc(fp)) != EOF)
	{
		putchar(c);
	}
	//判断是什么原因结束的
	if (ferror(fp))
		puts("\n遇到错误读取结束\n");
	else if (feof(fp))
		puts("\n遇到文件末尾读取结束\n");
}

运行结果:
在这里插入图片描述
在这里插入图片描述

八、文件缓冲区

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

#include <stdio.h>
int main()
{
	FILE* pf = fopen("myfile.txt", "w");
	fputs("abcdef", pf);//此时才将数据写到输出缓冲区上
	printf("睡眠10秒-已经写数据了,打开myfile.txt文件,发现文件没有内容\n");
	Sleep(10000);//等待10秒钟,发现在文件上并没有数据,说明数据还在输出缓冲区上
	printf("刷新缓冲区\n");
	fflush(pf);//10过后,刷新缓冲区时,才将输出缓冲区的数据写到文件(磁盘)
	printf("再睡眠10秒-此时,再次打开myfile.txt文件,文件有内容了\n");
	Sleep(10000);//再过10过后关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

运行结果:
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

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

在这里插入图片描述

end~

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

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

相关文章

pg三种插件验证

sr_plan 创建extension, 他会创建保留执行计划的表 创建表并插入数据 开启sr_plan.write_mode, 允许sr_plan收集SQL和执行计划 查看QUERY 1的执行计划 PostgreSQL支持merge join、GroupAggregate(通过INDEX SCAN),所以这个CASE,非常快,并不需要b对所有数据进行聚合。查看…

linux 动态库so相关操作

1. 查看库版本号 一般在文件名上有版本号&#xff0c;若文件名上没有版本号&#xff0c;使用如下命令查看&#xff1a; readelf -d libstdc.so 2. 查看库内函数 a) nm -d libstdc.so | grep 内容 b) objdump -tT libstdc.so | grep 内容 c) readelf -s libstdc.so | grep…

第十章:重新审视扩张卷积:一种用于弱监督和半监督语义分割的简单方法

0.摘要 尽管取得了显著的进展&#xff0c;弱监督分割方法仍然不如完全监督方法。我们观察到性能差距主要来自于它们在从图像级别监督中学习生成高质量的密集目标定位图的能力有限。为了缓解这样的差距&#xff0c;我们重新审视了扩张卷积[1]并揭示了它如何以一种新颖的方式被用…

HTML编码-Form-ifram

字符编码&#xff1a; 主要有两类&#xff1a; 一类为非Unicode编码&#xff1b;一类是Unicode编码&#xff1b; 常见编码种类&#xff1a; 1、ASCII码&#xff1a; ASCII&#xff08;American Standard Code for Information Interchange&#xff0c;美国信息交换标准代码&a…

25.6 matlab里面的10中优化方法介绍——模拟退火算法(matlab程序)

1.简述 相信没有相关物理知识背景的小伙伴看到“退火”二字是一脸懵逼的...固体的退火过程指的是将固体加热至足够高的温度&#xff0c;再使其慢慢冷却的过程。在加热过程中&#xff0c;原本有序排列的内部粒子开始无序运动&#xff0c;此时固体的内能不断增大&#xff1b;而在…

【GEC6818开发板简介】

(꒪ꇴ꒪ ),hello我是祐言博客主页&#xff1a;C语言基础,Linux基础,软件配置领域博主&#x1f30d;快上&#x1f698;&#xff0c;一起学习&#xff01;送给读者的一句鸡汤&#x1f914;&#xff1a;集中起来的意志可以击穿顽石!作者水平很有限&#xff0c;如果发现错误&#x…

计算机网络 day13 TCP拥塞控制 - tcpdump - DHCP协议 - DHCP服务器搭建 - DNS域名解析系统 - DNS域名解析过程

目录 TCP的流控机制 -- 拥塞控制 参考文章&#xff1a;什么是TCP拥塞控制算法&#xff1f; - 知乎 (zhihu.com) 拥塞控制主要是四个算法&#xff1a; 主机如何知道数据在传输的过程中&#xff0c;知道中间的网络堵塞了&#xff1f; TCP/IP协议栈 tcpdump抓包工具的学习使用…

AtcoderABC231场

A - Water PressureA - Water Pressure 题目大意 假设水压仅取决于深度&#xff0c;在深度为x米时&#xff0c;水压为x/100兆帕斯卡。 现在给定一个深度D米&#xff0c;需要计算在该深度下的水压是多少兆帕斯卡。 思路分析 直接将输入的深度除以100得到水压结果。 时间复杂…

【无标题】自定义类型:位段,枚举,联合

自定义类型&#xff1a;位段&#xff0c;枚举&#xff0c;联合 1. 位段1.1 什么是位段1.2 位段的内存分配1.3 位段的跨平台问题 2. 枚举2.1 枚举类型的定义2.2 枚举类型的优点2.3 枚举的使用 3. 联合&#xff08;共用体&#xff09;3.1 联合类型的定义3.2联合的特点3.2.1 相关面…

使用 ChatGPT 进行研究的先进技术

在这篇文章中&#xff0c;您将探索改进您研究的先进技术。尤其&#xff0c; 分析和解释研究数据进行文献综述并找出研究差距废话不多说直接开始吧&#xff01;&#xff01;&#xff01; 分析和解释研究数据 一家小企业主希望分析客户满意度数据以改善客户服务。他们使用包含 10…

【vue】Vue中解读关于this.$emit()的用法:

文章目录 一、Vue.sync修饰符与this.$emit(‘update:xxx‘, newXXX)二、this.$emit()传多个参数 一、Vue.sync修饰符与this.$emit(‘update:xxx‘, newXXX) 二、this.$emit()传多个参数

python与深度学习(八):CNN和fashion_mnist二

目录 1. 说明2. fashion_mnist的CNN模型测试2.1 导入相关库2.2 加载数据和模型2.3 设置保存图片的路径2.4 加载图片2.5 图片预处理2.6 对图片进行预测2.7 显示图片 3. 完整代码和显示结果4. 多张图片进行测试的完整代码以及结果 1. 说明 本篇文章是对上篇文章训练的模型进行测…

基于新浪微博海量用户行为数据、博文数据数据分析:包括综合指数、移动指数、PC指数三个指数

基于新浪微博海量用户行为数据、博文数据数据分析&#xff1a;包括综合指数、移动指数、PC指数三个指数 项目介绍 微指数是基于海量用户行为数据、博文数据&#xff0c;采用科学计算方法统计得出的反映不同事件领域发展状况的指数产品。微指数对于收录的关键词&#xff0c;在指…

javaweb如何格式化日期时间

解决方式&#xff1a; 方式一&#xff1a;在属性上加入注解&#xff0c;对日期进行格式化 方式二&#xff1a;在 WebMvcConfiguration 中扩展Spring MVC的消息转换器&#xff0c;统一对日期类型进行格式化处理 package com.sky.json;import com.fasterxml.jackson.databind.Des…

[OnWork.Tools]系列 01-简介

说明 OnWork.Tools 是基于 Net6 的桌面程序。支持Windows7SP1及以上系统&#xff0c;主要是日常办公或者是开发工作过程中常用的工具集合。界面使用WPF Mvvm模式开发&#xff0c;目的是将开源项目中&#xff0c;好用的项目集成到一起&#xff0c;方便大家使用和学习。 功能 …

牛客周赛 Round 4

A 游游的字符串构造 思路分析 构造字符串&#xff0c;注意k>1 时间复杂度 O(n) AC代码 #include<bits/stdc.h> using namespace std; int main() {int n,k;cin>>n>>k;if(n>3*k){for(int i0;i<k;i)cout<<"you";for(int i0;i<…

工作纪实34-emoji表情包存储异常,修改db的字段类型

线上问题&#xff0c;发现emojo表情写入数据库出现异常 修改mysql字段的字符集 ALTER TABLE customer_cycle_info MODIFY COLUMN customer_sales_remark varchar(500) CHARACTER SET

已实现商业化却仍陷亏损泥潭,瑕瑜错陈的觅瑞集团求上市

撰稿|行星 来源|贝多财经 7月25日&#xff0c;Mirxes Holding Company Limited-B&#xff08;以下简称“觅瑞集团”&#xff09;向港交所递交上市申请材料&#xff0c;计划在港交所主板上市&#xff0c;中金公司和建银国际为其联席保荐人。 据招股书介绍&#xff0c;成立于2…

0基础系列C++教程 从0开始 第二课

0基础系列C教程 从0开始 第二课来了&#xff01; 复习第一课内容 1 怎么输出数字“1919810”&#xff1f; 答案&#xff08;关键语句&#xff09;: cout<<"1919810"; 2 怎么输出字符串“Hello World”&#xff1f; 答案&#xff08;关键语句&#xff09;&a…

MySQL案例——多表查询以及嵌套查询

系列文章目录 MySQL笔记——表的修改查询相关的命令操作 MySQL笔记——MySQL数据库介绍以及在Linux里面安装MySQL数据库&#xff0c;对MySQL数据库的简单操作&#xff0c;MySQL的外接应用程序使用说明 文章目录 系列文章目录 前言 一 创建数据库 1.1 创建一个部门表 1.…