1.动态内存分配
- 可以在程序运行的时候临时决定需要分配的存储区个数,这种分配方式叫动态内存分配。
- 为了管理动态分配内存需要使用一组标准函数。
- 为了使用这些标准函数需要包含stdlib.h头文件
mallloc
void* malloc (size_t size);
----malloc函数可以动态分配一组连续的存储区
----这个函数需要一个整数类型的参数表示希望分配的字节个数
----它的返回值表示分配好的第一个字节的地址
----如果内存分配失败就返回NULL
两种用法:
----int *p = malloc(sizeof(int) * 5);
----int *p = malloc(20);
#include<stdio.h>
#include<stdlib.h>//malloc free
int main(){
int *p = malloc(8);
if(p==NULL){
printf("动态内存分配失败\n");
return -1;
}
printf("p = %p\n",&p);
printf("释放前:p = %p\n",p);
*p = 10;
*(p + 1) = 20;
printf("%d %d\n",p[0],p[1]);
//释放内存
free(p);
printf("释放后:p = %p\n",p);
printf("%d %d\n",p[0],p[1]);
p = NULL;
printf("%d %d\n",p[0],p[1]);
return 0;
}
free
void free (void* ptr);
----计算机不会主动回收动态分配的内存
----当程序不再需要动态分配内存以后就应该主动把它们还给计算机,否则会造成内存泄露----free函数用来把动态分配内存还给计算机,这叫做释放动态分配内存
----这个函数需要第一个字节的地址作为参数
----如果使用指针作为参数调用free函数则函数结束后必须把指针设置成空指针
calloc
void* calloc (size_t num, size_t size);
----calloc函数需要两个参数
----第一个参数是想要分配存储区的个数,第二个参数是分配存储区的大小----int*p = calloc(5, sizeof(int));
和malloc区别:
calloc函数分配的存储区全部初始化为0,malloc函数分配的存储区为随机数
#include<stdio.h>
#include<stdlib.h>
int main(){
//为数组分配动态内存
int *p = calloc(5,sizeof(int));
//int *p = calloc(5,4);
if(p==NULL){
printf("动态内存分配失败\n");
return -1;
}
//赋值
for(int i = 0;i<5;i++){
p[i] = 100 + i;
}
//打印
for(int i = 0;i<5;i++){
printf("%d ",p[i]);
}
printf("\n");
//释放
free(p);
p = NULL;
return 0;
}
realloc
void* realloc (void* ptr, size_t size);
----realloc函数需要两个参数
----第一个参数首地址(malloc函数返回值),第二个参数从首地址上调整后的字节个数
----int*p=malloc(8);
----p=realloc(p,16);----原有的内容不会发生改变
----int*p =malloc(8);
----p = realloc(p,4);
#include<stdio.h>
#include<stdlib.h>
int main(){
//为数组分配内存
int * p = calloc(2,sizeof(int));
if(p == NULL){
printf("内存分配失败\n");
return -1;
}
p[0] = 1;
p[1] = 3;
//修改所分配的存储区
p = realloc(p,16);
p[2] = 5;
p[3] = 7;
for(int i = 0;i<4;i++){
printf("%d ",p[i]);
}
printf("\n");
//释放内存
free(p);
p = NULL;
return 0;
}
文件操作
文件操作基本步骤
1.打开文件 ---fopen
2.操作文件 ---fwrite / fread
3.关闭文件 ---fclose
fopen
fopen函数的功能是打开文件,该函数需要两个参数
第一个参数是文件路径,代表要打开的文件所在的位置
第二个参数是打开方式,代表程序可以对文件做什么操作
fopen函数的返回值是FILE*类型,表示打开的文件
如果文件打开失败,fopen函数的返回值为NULI
打开成功后,后续使用fopen的返回值即文件指针来表示打开的文件
#include <stdio.h>
FILE * fopen(const char *path,const char *mode);
fwrite
fwrite函数的功能是将内存中(程序)中的数据写入到文件所在的硬盘中
fwrite函数需要4个参数
第一个参数是 要向文件中写入的数据的存储区首地址
第二个参数是 要写入的元素占据的字节数
第三个参数是 要写入的元素个数
第四个参数是 要写入的文件的文件指针>
返回的是实际写入的元素个数>
#include <stdio.h>
size_t fwrite(const void *ptr, size_t size, size_t nmemb,FILE * stream);
fread
fread函数的功能是将文件中的数据读取到内存中(程序)以使用
fread函数需要4个参数
第一个参数是 从文件中读取的数据要存储到的存储区的首地址
第二个参数是 要读取的每个元素占据的字节数
第三个参数是 要读取的元素个数
第四个参数是 要读取文件的文件指针
返回的是实际读取的元素个数》
#include <stdio.h>
size_t fread(void *ptr,size_t size,size_t nmemb, FILE * stream);
fclose
int fclose ( FILE * stream );
fclose函数的功能是关闭文件
fclose函数的参数是文件指针,即fopen函数的返回值
如果文件正常关闭,fclose函数返回值为0,如果文件关闭异常,fclose函数返回值为非0
#include <stdio.h>
int fclose(FILE* fp);
当对文件的操作结束后,一定要记得使用fclose函数将对应的关闭如果只打开不关闭那么该文件就会一直占用内存空间,造成资源浪费
文件的打开方式
r 只读,文件必须存在,从头开始读
w 只写,文件不存在就创建,存在就清空,从头开始写
a 追加,文件不存在就创建,存在不清空,从尾开始写
r+ 读写,文件必须存在,从头开始读写
w+ 读写,文件不存在就创建,存在就清空,从头开始读写
a+ 追读,文件不存在就创建,存在不清空,从头开始读,从尾开始写
文件读写位置
- 计算机里为每个打开的文件保留一个整数,这个整数表示下一次文件读写操作的开始位置
- 这个整数就是文件头到这个位置之间包含的字节个数
- 这个整数叫做文件的位置指针
- 每当从文件里获得n个字节或向文件里写入n个字节以后位置指针都会向后移动n个字节
ftell
-
ftell函数可以用来获得位置指针的数值
- long ftell(FILE * stream);
- rewind函数可以把位置指针移动到文件开头
- void rewind(FILE *stream);
fseek
- fseek函数可以把位置指针移动到文件里的任何位置
- fseek函数里需要指定一个基准位置以及目标位置到基准位置之间的距离
- fseek函数需要三个参数
- 第一个参数是文件指针,表示要操作的文件
- 第二个参数是 偏移量
- 第三个参数是 基准位置
SEEK_SET 0 把文件头作为基准位置
SEEK_CUR 1 把当前位置作为基准位置 SEEK_END 2 把文件尾作为基准位置
int fseek(FILE*stream,long offset,int whence);
- FILE* fp = fopen("a.txt",“w+")
- fseek(fp,2,SEEK_SET);读写位置从文件头向后移动2个字节
- fseek(fp,4,SEEK_CUR);读写位置从当前位置向后移动4个字节
- fseek(fp,6,SEEK_END);读写位置从文件尾向前移动6个字节
- printf(“位置在%ld\n",ftell(fp));//显示当前文件读写位置
#include<stdio.h>
int main(){
//打开文件
FILE* fp = fopen("./shared.txt","w+");
if(fp == NULL){
printf("文件打开失败");
}
//读取数据
char a[7] = "abcdefg";
int size = fwrite(a,sizeof(char),7,fp);
printf("实际写入%d个元素\n",size);
//获取当前读写位置
long pos = ftell(fp);
printf("%ld\n",pos);
//读fg
fseek(fp,5,SEEK_SET);
char c[2] = {0};
fread(c,sizeof(char),2,fp);
printf("%c %c\n",c[0],c[1]);
//关闭文件
fclose(fp);
fp = NULL;
return 0;
}
运行结果:
实际写入7个元素
7
f g
fprintf
- fprintf函数可以把数字直接记录到文件中
- fprintf函数的第一个参数是文件指针,后面的参数是 printf函数的参数
- fprintf(fp,“%d\n",a);
#include<stdio.h>
int main(){
//打开文件
FILE* fw = fopen("./out.txt","w");
if(fw == NULL){
printf("文件打开失败\n");
return -1;
}
//fprintf函数可以直接把数据记录到文件中
//均是以字符串形式写到文件中
fprintf(fw,"马上就放假了\n");
int a = 10;
double b = 3.14;
fprintf(fw,"a = %d b = %lg\n",a,b);
fclose(fw);
fw = NULL;
return 0;
}
fscanf
- fscanf函数可以从文本文件里获得数字并记录到存储区里
- fscanf函数的第一个参数是文件指针,后面的参数是scan函数的参数
- fscanf(fp,“%d",&a);
- 这两个函数执行效率比较低,不适合处理大数据量的文件
#include<stdio.h>
int main(){
int i = 0;
double d = 0.0;
char c[12] = {};
FILE* fr = fopen("./in.txt","r");
if(fr == NULL){
printf("文件打开失败\n");
return -1;
}
fscanf(fr,"%d%lg%s",&i,&d,c);//in.txt中的数据为100 3.14 哈哈哈
printf("i = %d d = %lg c = %s\n",i,d,c);
fclose(fr);
fr = NULL;
return 0;
}
三个标准文件指针
标准输入 stdin 键盘
标准输出 stdout 终端窗口
标准错误 stderr 终端窗口
int a= 100;
printf(“%d\n",a);== fprintf(stdout,"%d\n",a);
scanf(“%d",&a);== fscanf(stdin,“%d",&a);
标准输入和标准错误的区别:
stdout在将内容输出到显示器上时,会经历一个标准输出缓冲区,只有在标准输出缓冲区中满足3个条件时,即1.缓冲区数据带有\n 2.输出的数据足够多把缓冲区填满 3.程序正常结束
stderr没有输出缓冲区,直接将内容输出到显示器上。
#include<stdio.h>
int main(){
// printf("Hello");
fprintf(stderr,"Hello");
for(;;);
return 0;
}