【C语言】文件

本文详细介绍了C语言中的几种变量类型,包括局部变量、全局变量、静态局部变量和静态全局变量的特点及作用。同时,讲解了文件的概念、数据流和输入输出流,以及文件的ASCII和二进制分类。文中还通过示例展示了fopen、fread、fwrite和fclose等文件操作函数的使用,并提供了文件大小统计的示例代码。
摘要由CSDN通过智能技术生成

文件

局部变量:

特点:

局部变量也只有局部作用域,他是自动对象,他在程序运行期间不是一直存在,而是只在函数执行期间存在,函数的一次调用结束后,变量就被撤销,其所占用的内存也被收回。

eg:

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

void funA(int a)
{
	a++;
}

void funB(int a)
{
	a++;
}

int main()
{
	int a = 0;
	funA(a);
	funB(a);
	printf("%d\n",a);
}//此时a的值不会受到影响,因为局部变量funA(a)、funB(a)不会对实参的值产生影响
//如果形参的改变想要影响实参,就需要(main)传指针、(内部)解引用


void funA(int* pa)
{
	*pa++;
}

void funB(int* pa)
{
	*pa++;
}

int main()
{
	int a = 0;
	funA(&a);
	funB(&a);
	printf("%d\n", a);
}//此时打印结果也为0,因为*pa++是指针在++,不是值在++,所以应该改成(*pa)++


///
//正确结果:
void funA(int* pa)
{
	(* pa)++;
}

void funB(int* pa)
{
	(* pa)++;
}

int main()
{
	int a = 0;
	funA(&a);
	funB(&a);
	printf("%d\n", a);
}

全局变量:

特点:

全局变量具有全局作用域。全局变量只需在一个源文件中定义,就可以作用于所有的源文件。当然,其他不包括全局变量定义的源文件需要用extern关键字再次声明这个全局变量。

**生命周期:**整个项目存活

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

extern void fun();
int a = 0;			//.data区存储  全局变量,整个项目有效
					//链接全局变量:extern int a;
					//extern void fun();	//外部文件定义过fun
void funA()
{
	a++;
}
void funB()
{
	a++;
}
int main()
{
	funA();
	funB();
    fun();
	printf("%d\n", a);
}

静态局部变量:

静态局部变量具有局部作用域。它只被初始化一次,自从第一次初始化直到程序与你新内阁结束都一直存在,他和全局变量的区别在于全局变量对所有的函数都是可见的,而静态局部变量只对定义自己的函数体始终可见。

静态:本文件可见(权限)

静态全局变量:

静态全局变量也具有全局作用域,他与全局变量的区别在于如果程序包含多个文件的话,他作用于定义它的文件里,不能作用到其他文件里,即被static关键字修饰过的变量具有文件作用域。这样即使两个不同的源文件都定义了相同的静态全局变量,他们也是不同的变量。

静态:本文件可见(权限)

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

static int a = 0;	//.data区存储  全局变量,整个项目有效
					//链接全局变量:extern int a;
void funA()
{
	a++;
}
void funB()
{
	a++;
}
int main()
{
	funA();
	funB();
	printf("%d\n", a);
}

静态局部变量和静态全局变量的区别:

  1. 全局静态变量只能被当前源文件引用,不能被工程里其它源文件引用。除了这点特殊,其它与普通的全局变量一样。
  2. 局部静态变量,只执行一次初始化,只能被所在函数引用,函数执行完毕,变量仍存在,生存周期贯穿整个程序。
  3. 静态变量会被放在程序的静态数据存储区里,这样可以在下一次调用的时候还可以保持原来的赋值。这一点是他与堆栈变量和堆变量的区别
  4. 变量用static告知编译器,自己仅仅在变量的作用域范围内可见。这一点是他与全局变量的区别。
  5. 局部变量改变为静态变量后是改变了他的存储方式,即改变了他的生存期。把全局变量改变为静态变量后是改变了他的作用域,限制了他的使用范围。因此static这个说明符在不同的地方起的作用是不同的。

文件:

什么是文件?

文件:存储在外部介质上数据的集合

​ 磁盘:永久数据存储->文件存储

​ 内存:断点即消失->读取文件内容、打印、关闭文件

数据流:

数据流:输入输出是数据传送的过程,数据如流水一样从一处流向另一处,因此常将输入输出形象地称为流(stream),即数据流。流表示了信息从源到目的端的流动。

终端键盘是输入文件。
显示屏和打印机是输出文件。

输入输出流:

**输入流:**数据从文件(外存)流向计算机内存
**输出流:**数据从计算机内存流向文件(外存)

文件的分类:

  1. 根据数据的组织形式,数据文件可分为ASCII文件(文本文件)二进制文件
  2. 数据在内存中是以二进制形式存储的,如果不加转换地输出到外存,就是二进制文件;
  3. 如果要求在外存上以ASCII代码形式存储,则需要在存储前进行转换,ASCII文件又称文本文件,每一个字节放一个字符的ASCII代码;
  4. 字符一律以ASCII形式存储;
  5. 数值型数据既可以用ASCII形式存储,也可以用二进制形式存储。

**eg:**有整数10000,如果用ASCII码形式输出到磁盘,则在磁盘中占5个字节(每一个字符占一个字节),而用二进制形式输出,则在磁盘上只占4个字节(用VC++ C时)

image-20230106204658266

ASCII文件(文本文件):

能够通过记事本打开的,都属于文本文件

二进制文件:

多媒体文件(.mp3、图片)

fopen()

image-20230106211103313

  1. 对文件读写之前应该“打开”该文件,在使用结束之后应“关闭”该文件。
  2. 所谓“打开”是指为文件建立相应的信息区(用来存放有关文件的信息)和文件缓冲区(用来暂时存放输入输出的数据)。

绝对路径:一定是从C:\、D:\、E:\等开头的

相对路径:相对当前文件来说的前一条路径

模式(权限):

文本文件:

模式作用区别
r只读文件必须存在
w只写文件可存在也可不存在;存在则覆盖,不存在则新创建
a追加写若存在该文件,光标移动到文件末尾数据写入;若不存在则新创建
r+读写文件必须存在
w+读写文件可存在也可不存在;存在则覆盖,不存在则新创建
a+读写若存在该文件,光标移动到文件末尾数据写入;若不存在则新创建

二进制文件:(rb、wb不仅能处理二进制文件,也能处理文本文件)

模式作用
rb只读
wb只写
ab追加写
rb+读写
wb+读写
ab+读写
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int main()
{
	//相对路径
	FILE* fp=fopen("text12.19.cpp","r+");	//r+无法打开不存在的文件,返回为空
	if (fp == NULL)
	{
		printf("文件打开失败\n");
	}
	return 0;
}

运行结果:

image-20230106212414478

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int main()
{
	//相对路径
	FILE* fp=fopen("text12.19.cpp","w");	//w可以新创建不存在的文件,可以在当前项目路径下找到新创建的text12.19.cpp
	if (fp == NULL)
	{
		printf("文件打开失败\n");
	}
	return 0;
}

结果:

image-20230106212808184

fread()

image-20230106213341778

一般调用形式为:fread(buffer,size,count,fp);

**buffer:**是一个地址;对fread来说,它是用来存放从文件读入的数据的存储区的地址

**size:**要读写的每个数据项的字节数

**count:**要读写多少个数据项

**fp:**FILE类型指针

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int main()
{
	//相对路径
	//读文件
	FILE* fp;
	if ((fp=fopen("text12.19.cpp","r"))==NULL)
	{
		printf("cannot open this file!\n");
	}
	char buff[256] = { 0 };
	//返回值:成功读取的字符个数
	size_t num = fread(buff, sizeof(char), 256, fp);
	printf("%s\n", buff);

	fclose(fp);			//释放资源,关闭文件
	return 0;
}

image-20230106215317282

运行结果:

image-20230106215355129

(此时存储格式相同,都是以文本格式操作的,不会出现乱码;但一般情况下不建议对中文进行操作)

fwrite()

image-20230106215226187

一般调用形式为:fwrite(buffer,size,count,fp);

**buffer:**是一个地址;对fwrite来说,是要把此地址开始的存储区中的数据向文件输出

**size:**要读写的每个数据项的字节数

**count:**要读写多少个数据项

**fp:**FILE类型指针

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int main()
{
	//相对路径
	FILE* fp;
	if ((fp=fopen("text12.19.cpp","w"))==NULL)
	{
		printf("cannot open this file!\n");
	}
	fwrite("//hello", sizeof(char), 7, fp);

	fclose(fp);			//释放资源,关闭文件
	return 0;
}

运行结果:(w操作会将原文件中的内容替换掉)

image-20230106220407079

fclose()

关闭文件fclose函数。fclose函数调用的一般形式为:fclose(文件指针);
eg:fclose (fp);
如果不关闭文件将会丢失数据。

练习:

将text12.19.cpp文件覆盖到new.cpp中

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int main()
{
	FILE* fp1 = fopen("text12.19.cpp", "r");		//以读的方式读取文件
	if (fp1 == NULL)
		return -1;
	FILE* fp2 = fopen("new.cpp", "w");		//以写的方式读取文件
	if (fp2 == NULL)
		return -1;
	char buffer[256] = { 0 };		//创建一个数组用来存储从fp1中读取到的数据
	int num = 0;			//初始化一个num,用来判断fread的值是否为0,为0则退出
	while (num = fread(buffer, sizeof(char), 256, fp1))		//while循环是为了将字节数大于256的文件,也能全部拷贝到new.cpp中
	{
		fwrite(buffer, sizeof(char), num, fp2);		//将buffer数组中保存的num数量个值写入到fp2所指向的文件中
		memset(buffer, 0, 256);		//清空buffer,防止buffer数组中遗留上次循环存储的数据
	}
	fclose(fp1);
	fclose(fp2);
	return 0;
}

写一个拷贝文本文件的函数copefile:

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

void copyfile(const char* pathnewfile, const char* patholefile)
{
	if (pathnewfile==NULL || patholefile == NULL)
		return;
	FILE* fp1 = fopen(patholefile, "r");		//以读的方式读取文件
	if (fp1 == NULL)
		return;
	FILE* fp2 = fopen(pathnewfile, "w");		//以写的方式读取文件
	if (fp2 == NULL)
		return;
	char buffer[256] = { 0 };		//创建一个数组用来存储从fp1中读取到的数据
	int num = 0;			//初始化一个num,用来判断fread的值是否为0,为0则退出
	while (num = fread(buffer, sizeof(char), 256, fp1))		//while循环是为了将字节数大于256的文件,也能全部拷贝到new.cpp中
	{
		fwrite(buffer, sizeof(char), num, fp2);		//将buffer数组中保存的num数量个值写入到fp2所指向的文件中
		memset(buffer, 0, 256);		//清空buffer,防止buffer数组中遗留上次循环存储的数据
	}
	fclose(fp1);
	fclose(fp2);
}

int main()
{
	copyfile("D:/new.txt", "D:/1.txt");	
    copyfile("D:\\new.txt", "D:\\1.txt");	//在C语言中用\\表示路径,也可以用/表示
    return 0;
}

fseek()

作用:移动光标

函数作用
SEEK_SET定位光标到文件头
SEEK_CUR文件当前位置
SEEK_END文件尾部

fseek(fp,10,SEEK_SET); //从文件fp的头部 光标向后移动十个位置

fseek(fp,-3,SEEK_CUR); //从文件fp光标的当前位置 光标向前移动3个位置

fseek(fp,-10,SEEK_END); //从文件fp的尾部 光标向前移动十个位置

统计文件总大小:

  1. 按二进制只读方式打开文件
  2. 利用fseek将文件位置标记指向文件的结尾
  3. 利用ftell获取文件的位置根据返回值就能得到文件的大小
  4. 关闭文件
ftell()

ftell函数的作用是得到流式文件中文件位置标记的当前位置。

image-20230106234807113

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int main()
{
	FILE* fp = fopen("text12.19.cpp", "rb");
	fseek(fp, 0, SEEK_END);
	long size = ftell(fp);
	printf("该文件一共%ld个字节\n", size);
	fclose(fp);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值