堆区 内存的动态分配和手动释放 重复练习5遍

1、在堆区中动态分配内存空间的时候,要注意指针的重指向问题,发生了重指向一定要分析清楚,他的指向还在不在堆区,如果不在,就不需要自己手动释放内存空间了。

2、在给指针赋值的时候,需要注意的是:指针的偏移思想。

3、给指针数组赋值的时候,一定要记住本质,指针数组本质上是数组。

4、数组指针就是把他当指针看待。

5、赋值过程中:结构体之间是可以直接赋值的,数组之间不可以。字符串之间也是不可以的。其实字符串就是一维数组。字符串之间赋值用strcpy(char *,char *);

源代码:

//

//  main.m
//  Tainging_15-08_10
//
//  Created by lanou3g on 15/8/10.
//  Copyright (c) 2015年 lanou.3g.com. All rights reserved.
//

#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
    
    //第一遍=======>全部用的是:指向在堆区中动态分配的内存空间的首地址的指针重指向栈区存放的数组的首地址。--不用free,因为指向的空间已经不是堆区了。
    //====>练习:把数组中的元素赋给堆区;
    int array_Int[10]={0};//原始数组
    for (int i=0; i<10; i++) {
        //数组元素为40-100的随机数
        array_Int[i]=arc4random()%(100-40+1)+40;
    }
    //自己自定义分配内存
    int *point_Int=malloc(10*sizeof(int));
    //把指向自定义分配的内存首地址-->原始数组的首地址
    point_Int=array_Int;
    for (int i=0; i<10; i++) {
        printf("%d\t",*(point_Int+i));
    }
//    free(point_Int);//===>point_Int指向了栈区的array_Int的首地址,一定要记住free释放的是point_Int所指向的内存空间,并且只有当 当前所指向的内存空间属于堆区的时候,free()才能够释放,只要指向了不是堆区的内存空间,系统都会自动释放分配过的内存空间
//    point_Int=NULL;
    
    printf("\n");
    
    //======>练习:有一个字符串,其中有数字,提取其中的数字,要求动态分配内存。
    char array_String[20]="yibella520zhouyi1314";//原始数组
    int count_Number=0;//记录数字的个数
    char array_StringTemp[20]={0};//中间数组,存字符串中的数字字符
    for (int i=0,j=0; i<strlen(array_String); i++) {
        if (array_String[i]>='0'&&array_String[i]<='9') {
            count_Number++;
            array_StringTemp[j]=array_String[i];
            j++;
        }
    }
    //根据数字的个数动态分配内存
    char *point_String=malloc(sizeof(char)*count_Number);
    //把指向分配好的内存首地址的指针-->数字字符数组的首地址
    point_String=array_StringTemp;
    for (int i=0; i<count_Number; i++) {
        //其中把数字字符转换成整型输出
        printf("%d\t",*(point_String+i)-48);//0--ASCII--48
    }
    point_String=NULL;
    printf("\n");
    //=====>练习:输入三个学员的姓名,动态分配内存 保存学员的姓名,并最后输出。
    //第一步:输入字符串数组元素
    char _names[3][20]={0};//存数名字的字符串数组
    printf("输入三个名字:\n");
    for (int i=0; i<3; i++) {
        scanf("%s",_names[i]);
        getchar();
    }
    //第二步:计算字符串数组的字符总数
    int count_names=0;//记录字符串数组的字符数量
    for (int i=0; i<3; i++) {
        for (int j=0; j<20; j++) {
            if (_names[i][j]!='\0') {
                count_names++;
            }else{
                break;
            }
        }
    }
    //第三步:指向字符串数组的每一行的首地址
    //返回一个指针类型,并指向内存首地址
    char *point_names=malloc(sizeof(char)*count_names);
    for (int i=0; i<3; i++) {
        point_names=_names[i];//指针指向字符串数组中的字符串的首地址
        printf("%s\t",point_names);
    }
    printf("\n");
    //第二遍
    //====>练习:把数组中的元素赋给堆区;
    int array_Int1[10]={0};
    for (int i=0; i<10; i++) {
        array_Int1[i]=arc4random()%(20-1+1)+1;
    }
    int *point_Int1=malloc(sizeof(int)*10);
    for (int i=0; i<10; i++) {
        *(point_Int1+i)=array_Int1[i];
        //把数组元素中的值给了指针+i的地址,指针+i只是把指针向高位偏移,注意:不是数组是下标的移动

        printf("%d\t",*(point_Int1+i));
    }
    free(point_Int1);
    point_Int1=NULL;
    printf("\n");
    //======>练习:有一个字符串,其中有数字,提取其中的数字,要求动态分配内存。
    char *names_Point[3]={NULL};//定义一个指针数组
    //其中,names_Point[0],names_Point[1],names_Point[2],是这个指针数组中的三个数据元素,同时这三个元素都是一个指针。
    char names_temp[20]={0};//定义一个接收名字的一维数组
    printf("请输入三个名字:\n");
    for (int i=0; i<3; i++) {
        scanf("%s",names_temp);
        getchar();
        //给每一个指针变量根据输入的字符串的长度动态分配内存空间
        names_Point[i]=malloc(sizeof(char)*(strlen(names_temp)+1));
        //只要是字符串,就一定要注意字符串之间不能直接赋值。
        //names_Point[i]是指针数组的数组元素,也是一个指针
        //更白话的堆name_Point[i]的解释:是指向一个连续空间的指针,并代表了这片连续空间的首地址
        //names_temp是一维数组的首地址

        strcpy(names_Point[i], names_temp);
        //strcpy(目的地址,源地址)==>是把从源地址的首地址开始以'\0'为结束符的字符串复制到以目的地址的首地址开始的地址空间。
    }
    for (int i=0; i<3; i++) {
        printf("%s\t",names_Point[i]);
    }
    printf("\n");
    //=====>练习:输入三个学员的姓名,动态分配内存 保存学员的姓名,并最后输出。
    //定义一个字符串数组,用来存储键盘输入的三个字符串
    char _names1[3][20]={0};
    for (int i=0; i<3; i++) {
        scanf("%s",_names1[i]);
        getchar();
    }
    //定义一个指针数组,用数组元素分别指向一个名字
    char *point_names1[3]={NULL};
    long unsigned count[3]={0};
    for (int i=0; i<3; i++) {
        count[i]=strlen(_names1[i]);
        //根据每一个字符串的长度,动态分配内存
        point_names1[i]=malloc(sizeof(char)*count[i]+1);
        //用单个指针指向单个字符串
        //指针指向了栈区,所以不需要自己释放空间了。
        point_names1[i]=_names1[i];
        printf("%s\t",point_names1[i]);
    }
    printf("\n");
     
    //第三遍
    //====>练习:把数组中的元素赋给堆区;
    char _names2[10]="yibella";
    long unsigned count_names2=strlen(_names2);
    char *point_names2=malloc(sizeof(char)*count_names2+1);
    for (int i=0; i<count_names2; i++) {
        //通过赋值,这时的指针还是指向的堆区,所以需要自己释放内存空间
        *(point_names2+i)=_names2[i];
    }
    printf("%s\n",point_names2);
    free(point_names2);
    point_names2=NULL;
    //======>练习:有一个字符串,其中有数字,提取其中的数字,要求动态分配内存。
    //定义一个一维数组指向字符串
    char _names3[20]="613liuyisan007";
    //定义一个一维数组,用来接收上一个字符串中的数字字符
    char _namesTemp2[10]={0};
    for (int i=0,j=0; i<strlen(_names3); i++) {
        if (_names3[i]>='0'&&_names3[i]<='9') {
            _namesTemp2[j]=_names3[i];
            j++;
        }
    }
    //求出数字字符的长度
    long unsigned count_names3=strlen(_namesTemp2);
    //动态分配一个存储数字的指针所指向的内存空间
    int *point_names3=malloc(sizeof(int)*count_names3);
    for (int i=0; i<count_names3; i++) {
        //把数字字符转换成数字 存到堆区中
        *(point_names3+i)=_namesTemp2[i]-48;
        //输出数字数组元素
        printf("%d\t",*(point_names3+i));
    }
    free(point_names3);
    point_names3=NULL;
    printf("\n");
    //=====>练习:输入三个学员的姓名,动态分配内存 保存学员的姓名,并最后输出。
    char _names4[3][20]={0};
    printf("输入三个名字:\n");
    long signed count_names4[3]={0};
    char *point_name4[3]={NULL};
    printf("请输入名字:\n");
    for (int i=0; i<3; i++) {
        scanf("%s",_names4[i]);
        getchar();
        count_names4[i]=strlen(_names4[i]);
        point_name4[i]=malloc(sizeof(char)*count_names4[i]+1);
        //单个赋值,所以指针所指向的还是堆区,需要自己手动释放内存空间
        strcpy(point_name4[i], _names4[i]);
    }
    for (int i=0; i<3; i++) {
        printf("%s\t",point_name4[i]);
        free(point_name4[i]);
        point_name4[i]=NULL;
    }
    printf("\n");
    
    //第四遍
    //====>练习:把数组中的元素赋给堆区;
    //定义一个整型的二维数组
    int array_Int4[3][3]={
        {1,2,3},
        {4,5,6},
        {7,8,9}
    };
    //定义一个整型的指针,根据就近的二维数组的长度开辟的内存空间
    int *point_int4=malloc(sizeof(int)*3*3);
    for (int i=0; i<3; i++) {
        for (int j=0; j<3; j++) {
            //对开辟的的内存空间依次赋值
            *(point_int4+j+i)=array_Int4[i][j];
            //输出开辟空间所存储的内容
            printf("%d\t",*(point_int4+j+i));
        }
        printf("\n");
    }
    //因为是赋值,所以指针指向还是堆区,需要自己手动释放开辟的内存空间
    free(point_int4);
    point_int4=NULL;
    printf("\n");
    //======>练习:有一个字符串,其中有数字,提取其中的数字,要求动态分配内存。
    //定义一个一维数组存储字符串
    char _names5[20]="1111sigle2222";
    //定义一个整型的一维数组,用来接收字符串中的数字
    int array_int5[20]={0};
    //定义一个整型变量来记录数字的个数
    int count_intArray=0;
    for (int i=0; i<strlen(_names5); i++) {
        //循环遍历字符串,找出数字字符
        if (_names5[i]>='0'&&_names5[i]<='9') {
            //把找到的数字字符转换成数字,并保存到整型数组中
            array_int5[count_intArray]=_names5[i]-48;
            count_intArray++;
        }
    }
    //根据整型数组的长度,动态开辟一片内存空间,返回给point_int5指针接收
    int *point_int5=malloc(sizeof(int)*count_intArray);
    for (int i=0; i<count; i++) {
        //把整型数组中的数字
        *(point_int5+i)=array_int5[i];
        printf("%d\t",*(point_int5+i));
    }
    free(point_int5);
    point_int5=NULL;
    printf("\n");
    //=====>练习:输入三个学员的姓名,动态分配内存 保存学员的姓名,并最后输出。
    //定义一个二维数组,用于存储名字
    char _names6[3][20]={0};
    //定义一个含有三个元素的指针数组
    char *point_names6[3]={NULL};
    int count_names6[3]={0};
    printf("请输入三个名字:\n");
    for (int i=0; i<3; i++) {
        scanf("%s",_names6[i]);
        getchar();
        //计算输入的每一个字符串的长度
        count_names6[i]=(int)strlen(_names6[i]);
        //根据计算出的字符串的长度,动态分配内存,别忘了最后的'\0'的空间
        point_names6[i]=malloc(sizeof(char)*count_names6[i]+1);
        //把字符串赋值给指针数组的元素
        strcpy(point_names6[i], _names6[i]);
    }
    for (int i=0; i<3; i++) {
        printf("%s\t",point_names6[i]);
        free(point_names6[i]);
        point_names6[i]=NULL;
    }
    printf("\n");
    //第五遍
    //====>练习:把数组中的元素赋给堆区;
    //定义一个整型数组
    int array_int7[5]={1,4,3,7,2};
    //动态分配内存空间
    int *point_int7=malloc(sizeof(int)*5);
    for (int i=0; i<5; i++) {
        //赋值
        *(point_int7+i)=array_int7[i];
        //输出
        printf("%d\t",*(point_int7+i));
    }
    //释放内存空间
    free(point_int7);
    //防止野指针的出现--野指针就是指向了“垃圾”内容
    point_int7=NULL;
    printf("\n");
    //======>练习:有一个字符串,其中有数字,提取其中的数字,要求动态分配内存。
    //定义一个字符串
    char strings[20]="hello2015";
    //定义一个整型数组,接收字符串中的数字
    int array_stringsInt[20]={0};
    //定义一个指针
    int *point_stringInt=NULL;
    //记录数字的个数
    int count_stringInt=0;
    for (int i=0; i<strlen(strings); i++) {
        //遍历,查找所有的数字字符
        if (strings[i]>='0'&&strings[i]<='9') {
            //把数字字符转换给数字,并存在整型数组中
            array_stringsInt[count_stringInt]=strings[i]-48;
            count_stringInt++;
        }
    }
    for (int i=0; i<count_stringInt; i++) {
        //动态开辟一片空间
        point_stringInt=malloc(sizeof(int)*count_stringInt);
        //把整型数组中的元素赋值给动态开辟的内存地址上
        *(point_stringInt+i)=array_stringsInt[i];
        //输出
        printf("%d\t",*(point_stringInt+i));
    }
    //释放在堆区申请的内存空间
    free(point_stringInt);
    //防止野指针的出现
    point_stringInt=NULL;
    printf("\n");
    
    //=====>练习:输入三个学员的姓名,动态分配内存 保存学员的姓名,并最后输出。
    //定义一个字符串数组,用来存储名字
    char _namesString[3][20]={0};
    //定义一个一维数组,用来记录每个字符串的长度
    long unsigned count_namesString[3]={0};
    //定义一个指针数组
    char *point_namesString[3]={NULL};
    printf("请输入三个名字:\n");
    for (int i=0; i<3; i++) {
        scanf("%s",_namesString[i]);
        count_namesString[i]=strlen(_namesString[i]);
        //根据计算的字符串长度,动态分配堆区内存空间返回给指针数组
        point_namesString[i]=malloc(sizeof(char)*count_namesString[i]);
        //把字符串的首地址复制给指针数组的数组元素--指针,也是动态开辟的内存空间的首地址
        strcpy(point_namesString[i], _namesString[i]);
    }
    for (int i=0; i<3; i++) {
        //输出
        printf("%s\t",point_namesString[i]);
        //释放掉堆区所分配的内存空间
        free(point_namesString[i]);
        point_namesString[i]=NULL;
    }
    printf("\n");
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值