文章目录
文件
局部变量:
特点:
局部变量也只有局部作用域,他是自动对象,他在程序运行期间不是一直存在,而是只在函数执行期间存在,函数的一次调用结束后,变量就被撤销,其所占用的内存也被收回。
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);
}
静态局部变量和静态全局变量的区别:
- 全局静态变量只能被当前源文件引用,不能被工程里其它源文件引用。除了这点特殊,其它与普通的全局变量一样。
- 局部静态变量,只执行一次初始化,只能被所在函数引用,函数执行完毕,变量仍存在,生存周期贯穿整个程序。
- 静态变量会被放在程序的静态数据存储区里,这样可以在下一次调用的时候还可以保持原来的赋值。这一点是他与堆栈变量和堆变量的区别
- 变量用static告知编译器,自己仅仅在变量的作用域范围内可见。这一点是他与全局变量的区别。
- 局部变量改变为静态变量后是改变了他的存储方式,即改变了他的生存期。把全局变量改变为静态变量后是改变了他的作用域,限制了他的使用范围。因此static这个说明符在不同的地方起的作用是不同的。
文件:
什么是文件?
文件:存储在外部介质上数据的集合
磁盘:永久数据存储->文件存储
内存:断点即消失->读取文件内容、打印、关闭文件
数据流:
数据流:输入输出是数据传送的过程,数据如流水一样从一处流向另一处,因此常将输入输出形象地称为流(stream),即数据流。流表示了信息从源到目的端的流动。
终端键盘是输入文件。
显示屏和打印机是输出文件。
输入输出流:
**输入流:**数据从文件(外存)流向计算机内存
**输出流:**数据从计算机内存流向文件(外存)
文件的分类:
- 根据数据的组织形式,数据文件可分为ASCII文件(文本文件)和二进制文件;
- 数据在内存中是以二进制形式存储的,如果不加转换地输出到外存,就是二进制文件;
- 如果要求在外存上以ASCII代码形式存储,则需要在存储前进行转换,ASCII文件又称文本文件,每一个字节放一个字符的ASCII代码;
- 字符一律以ASCII形式存储;
- 数值型数据既可以用ASCII形式存储,也可以用二进制形式存储。
**eg:**有整数10000,如果用ASCII码形式输出到磁盘,则在磁盘中占5个字节(每一个字符占一个字节),而用二进制形式输出,则在磁盘上只占4个字节(用VC++ C时)
ASCII文件(文本文件):
能够通过记事本打开的,都属于文本文件
二进制文件:
多媒体文件(.mp3、图片)
fopen()
- 对文件读写之前应该“打开”该文件,在使用结束之后应“关闭”该文件。
- 所谓“打开”是指为文件建立相应的信息区(用来存放有关文件的信息)和文件缓冲区(用来暂时存放输入输出的数据)。
绝对路径:一定是从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;
}
运行结果:
#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;
}
结果:
fread()
一般调用形式为: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;
}
运行结果:
(此时存储格式相同,都是以文本格式操作的,不会出现乱码;但一般情况下不建议对中文进行操作)
fwrite()
一般调用形式为: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操作会将原文件中的内容替换掉)
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的尾部 光标向前移动十个位置
统计文件总大小:
- 按二进制只读方式打开文件
- 利用fseek将文件位置标记指向文件的结尾
- 利用ftell获取文件的位置根据返回值就能得到文件的大小
- 关闭文件
ftell()
ftell函数的作用是得到流式文件中文件位置标记的当前位置。
#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;
}