[C++系列] C语言基础 动态内存分配,文件操作
in C/C++ with 0 comment

[C++系列] C语言基础 动态内存分配,文件操作

in C/C++ with 0 comment

#动态内存分配

可以在程序运行的时候临时决定需要分配多少存储区。
这种分配存储区的方法叫动态内存分配。
为了管理动态分配的内存,需要使用一组标准函数。
为了使用这些标准函数,需要包含stdlib.h头文件。

malloc函数可以动态分配一组连续的字节
这个函数需要一个整数类型的参数来表示希望分配的字节个数。
这个函数的返回值表示分配好的第一个字节的地址。
如果分配失败则返回值是NULL
这个函数把返回值记录在一个无类型指针的存储区里,使用之前最好首先强制转换为有类型指针

free标准函数可以用来把动态分配的内存还给计算机。
这个操作叫做内存释放。
这个函数需要动态分配函数里存储区的地址作为参数。
一起分配的所有内存必须一起释放。
如果使用指针作为参数调用free函数则函数结束后必须把指针恢复成空指针。

两种代码框架

#include<stdio.h>
#include<stdlib.h>
int main(){
int *p_num = (int *)molloc(5*sizeof(int));
if(p_num){
    //使用动态分配内存
    printf("%p \n",p_num);
    free(p_num);
    p_num = NULL;
}
return 0;
}

或者

#include<stdio.h>
#include<stdlib.h>
int main(){
int *p_num = (int *)molloc(5*sizeof(int));
if(!p_num){
    return 0;
}
//使用动态分配内存
free(p_num);
p_num = NULL;
return 0;
}
* 动态内存分配一块存储区,存放一组随机数据(相当于数组),操作方式和数组类似。
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
int main(){
srand(time(0));
int num;
int *p_num = (int *)malloc(5*sizeof(int));
/*
if(p_num){
    //使用动态分配内存
    printf("%p \n",p_num);
    free(p_num);
    p_num = NULL;
}*/
if(!p_num){
    return 0;
}
//使用动态分配内存
for(num=0;num<=4;num++){
    *(p_num+num) = rand()%36+1;
}
for(num =0;num<=4;num++){
        printf("%d ",*(p_num+num));
}
printf("\n");
free(p_num);
p_num = NULL;
return 0;
}

被调用函数可以把自己动态分配内存的地址作为返回值传递给调用函数,通过这种方式可以让调用函数使用被调用函数动态分配的存储区。

慎重使用动态分配内存,否则会造成内存泄露

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
int *create(int size){
int *p_num = (int *)malloc(size * sizeof(int));
if(p_num){
    int num;
    for(num =0;num<=size-1;num++){
        *(p_num+num) = rand()%36+1;
    }
    return p_num;
}
}
int main(){
    int *p_num = NULL,num;
    srand(time(0));
    p_num = create(7);
    if(p_num){
    for(num = 0;num <= 6;num++){
    printf("%d ",*(p_num+num));

    }
    printf("\n");
    free(p_num);
    p_num = NULL;
    }
return 0;
}

#练习

编写函数计算水平长方形中心点的位置,并把结果传递给调用函数。
用动态分配内存记录中心点的位置。

#include<stdio.h>
#include<stdlib.h>
typedef struct{
    int row;
    int col;
}pt;
typedef struct{
    pt pt1;
    pt pt2;
}rect;

pt *mid(const rect *p_r){
    pt *p_mid = (pt *)malloc(sizeof(pt));
    if(p_mid){
    p_mid->row=(p_r->pt1.row+p_r->pt2.row)/2;
    p_mid->col=(p_r->pt1.col+p_r->pt2.col)/2;

    }
    return p_mid;
}

int main(){
    rect rt;
    pt *p_mid;
    printf("输入一个水平长方形位置:");
    scanf("%d%d%d%d",&(rt.pt1.row),&(rt.pt1.col),&(rt.pt2.row),&(rt.pt2.col));
    p_mid = mid(&rt);
    if(p_mid){
        printf("中间点位置为:(%d,%d)\n",p_mid->row,p_mid->col);
        free(p_mid);
        p_mid=NULL;
    }
    return 0;
}

#`calloc`函数的动态内存分配

calloc函数也可以动态分配内存
它可以把动态分配得到的内存内容都设置为0
这个函数也需要包含stdlib.h的头文件。

malloc(7 * sizeof(int)); //一个参数,分配的内存其值是不确定的

calloc(7,ziseof(int)); //两个参数,分配的内存其值为0

它的返回值也是分配好的第一个存储区的地址,如果分配失败则返回值为NULL.

realloc函数可以调整一段动态分配内存里存储区的个数。
尽量少使用这个函数。

#文件操作

所有文件都采用二进制的方式记录数据
如果文件里的所有二进制数据都来自与字符这种文件叫做文本文件
除了文本文件以外的文件都叫做二进制文件。

C语言种提供两种操作文件的方法,一种方法只能操作文本文件,另外一种方法可以操作所有文件

第一种操作方式叫文本方式,第二种操作方式叫做二进制方式。

文件操作基本步骤
1,打开文件
2,操作文件(fread/fwrite
3,关闭文件(fclose)

#include<stdio.h>

int main(){
FILE *p_file = fopen("abc.txt","w");
/*
if(p_file){
    //操作文件

    fclose(p_file);
    p_file = NULL;
}*/
if(!p_file){

    return 0;
}
//操作文件
fclose(p_file);
p_file = NULL;
return 0;
}

fopen函数需要两个参数
1,第一个参数代表要打开的文件路径
2,打开文件的方式(决定可以在程序里对文件做什么操作)

打开方式:

1, “r”只能查看文件内容,不能修改,只能从文件头开始查看。如果文件不存在则打开失败。

2, “r+” "r" 的方式多了修改功能。

3,“ w ” 只能修改文件内容,不能查看,只能从文件头开始修改。如果文件不存在就创建文件,如果文件已经存在就删除文件原有内容。

4,“w+”“w”多了查看功能。

5, “a” 只能修改,不能查看,在文件末尾追加新内容。如果文件不存在就创建文件。如果文件存在,不会修改源文件原有内容。

6, “a+”“a”多了查看功能。

7 “b” 也是一种打开方式,这个打开方式和前面任何一个打开方式混合使用。如果程序中以二进制方式操作文件,就应该在打开方式里加上这个方式。

fopen 函数的返回值应该记录在文件指针里,程序里只能用文件指针代表文件。
fopen 函数有可能失败,如果失败则返回值是 NULL

一旦完成对文件的操作之后必须用 fclose 函数关闭文件。

fclose 函数需要文件指针作为参数。

fclose 函数结束后文件指针为野指针,必须恢复成空指针。

文件操作分为两组:

1,把内存里一组连续存储区的内容拷贝到文件里(写文件)
2,把文件里一组连续存储区的内容拷贝到内存里(读文件)

fread 函数以二进制方式对文件进行读操作。
fwrite 函数以二进制方式对文件进行写操作

这两个函数都需要四个参数
1,内存里第一个存储区的地址
2,单个存储区的大小
3,希望操作的存储区个数
4,文件指针

它们的返回值表示实际操作的存储区个数。

//将数组中的数据通过二进制方式写入文件
#include<stdio.h>
int main(){
    int arr[]={1,2,3,4,5};
    FILE *p_file =fopen("a.bin","wb");  //打开创建文件
    if(p_file){
    fwrite(arr,sizeof(int),5,p_file);   //写文件
    fclose(p_file);
    p_file=NULL;
    }

    return 0;
}
#include<stdio.h>
//把文件里的内容读到数组中。
int main(){
    int arr[5],num;
    FILE *p_file = fopen("a.bin","rb");  //读文件
    if(p_file){
        fread(arr,sizeof(int),5,p_file);  //读取的数据保存到数组     这个函数返回值是5,`返回实际操作的存储区格式。`
        fclose(p_file);
        p_file=NULL;
        for(num=0;num <=4;num++){
            printf("%d ",arr[num]);
        }
        printf("\n");
    }
return 0;
}
#include<stdio.h>
#include<string.h>
int main(){
    char tmp[10];
    int arr[]={34,4,542,5,87};
    FILE *p_file = fopen("abc.txt","wb");
    if(p_file){
          int num;
        for(num = 0;num <= 4;num++){
            sprintf(tmp,"%d",arr[num]);
            fwrite(tmp,sizeof(char),strlen(tmp),p_file);
        }
        fclose(p_file);
        p_file = NULL;
    }
    return 0;
} 

以下两个函数可以以文本方式操作文件

1, fprintf 用来把数据按照指定格式记录到文本文件中。这个函数的第一个参数是文件指针,第二个参数就是printf函数的参数。

#include<stdio.h>
int main(){
int arr[] = {23,43,546,45,42};
FILE *p_file = fopen("abb.txt","w");
if(p_file){
    int num;
    for(num=0;num<=4;num++){
        fprintf(p_file,"%d ",arr[num]);
    }
    fclose(p_file);
    p_file=NULL;
}
return 0;
}

2, fscanf 函数用来按照格式从文本文件里获得数据并记录在存储区里。这个函数第一个参数是文件指针,第二个参数是 scanf 函数的参数。

#include<stdio.h>
int main(){
int val;
FILE *p_file = fopen("abb.txt","r");
if(p_file){
    int num;
    for(num =0;num <=4;num++){
        fscanf(p_file,"%d",&val);
        printf("%d ",val);
    }
    printf("\n");
    fclose(p_file);
    p_file=NULL;
}
return 0;
}

#练习

编写一个模拟人员信息管理系统,程序从键盘得到多个人员信息并记录到二进制文件里
每个人员信息包括整数类型的id,float类型的工资和姓名。
文件可以扩展。

#include<stdio.h>
#include<string.h>
typedef struct{
    int id;
    char name[10];
    float sala;
} person;

int main(){
    int choise;
    person *p_pr;
    FILE *p_file = fopen("info.bin","ab");
    if(p_file){
        while(1){
            printf("输入员工id:");
            scanf("%d",&(p_pr->id));
            printf("输入工资:");
            scanf("%g",&(p_pr->sala));
            scanf("%*[^\n]");
            scanf("%*c");
            printf("请输入姓名:");
            fgets(p_pr->name,10,stdin);
            if(strlen(p_pr->name)==9 && p_pr->name[8]!='\n'){
                    scanf("%*[^\n]");
                    scanf("%*c");
            }
            fwrite(p_pr,sizeof(person),1,p_file);
            printf("是否需要输入下一个人员信息?0   不需要    1  需要");
                    scanf("%d",&choise);
                if(!choise){
                    break;
                }
        }
    fclose(p_file);
    p_file=NULL;
    }

return 0;
}

练习

11111
22222
33333
44444
55555

声明一个二维数组,记录以上25个个位数,编写程序把这些数字记录到二进制文件中。
编写程序从文件里得到这25个数字,并按照以下格式记录到二维数组里。

55555
44444
33333
22222
11111
#include<stdio.h>
int main(){
int arr[][5] = {1,1,1,1,1,
                2,2,2,2,2,
                3,3,3,3,3,
                4,4,4,4,4,
                5,5,5,5,5,};
FILE *p_file= fopen("arr.bin","wb");
if(p_file){
        fwrite(arr,sizeof(int),25,p_file);
        fclose(p_file);
        p_file = NULL;
}
}
#include<stdio.h>
int main(){
int arr[5][5];
FILE *p_file = fopen("arr.bin","rb");
if(p_file){
    int num,row,col;
    for(num=4;num>=0;num--){
        fread(arr[num],sizeof(int),5,p_file);
    }

    for(row = 0;row <=4;row++){
        for(col =0;col<=4;col++){
            printf("%d ",arr[row][col]);
        }
        printf("\n");
    }
    fclose(p_file);
    p_file=NULL;
}
}

重点

*   函数

* 指针

* 结构体

* 动态内存分配

预习

*  算法与数据结构
Responses