S1E38:动态内存管理2 课后作业

测试题:
0. 请问调用一次 malloc 函数可以申请多块内存空间吗?

答:不可以

答案:不行,调用一次 malloc 函数只能申请一块连续的内存空间,只是其尺寸可以自定义。


1. 以 mem 开头的函数比如 memcpy,memcmp 被编入字符串标准库(函数的声明包含在 string.h),那么请问它们与同在该标注库的 strncpy,strcnmp 函数有什么区别呢?

答:mem开头的是对地址进行操作,str开头的是对字符串的值进行操作

答案:从形式上看,str 开头的函数使用的是 char 类型的指针(char *)作为参数和返回值;而 mem 开头的函数使用的是 void 类型的指针(void *)作为参数和返回值。从本质上看,str 开头的函数主要目的是提供字符串的拷贝,比较等操作;而 mem 开头的函数主要目的是提供一个高效的函数接口来处理内存空间的数据。


2. 请用 malloc 函数实现 calloc(1024, sizeof(int)) 函数得到的结果?

答:malloc(1024*sizeof(int))

答案:calloc 函数在申请完内存后,自动初始化该内存空间为零,而 malloc 函数不进行初始化操作,所以调用完 malloc 函数之后,需要再调用 memset 函数将内存初始化为零。

int *ptr = (int *)malloc(1024 * sizeof(int));
memset(ptr, 0, 1024 * sizeof(int));


3. realloc(NULL, 1024) 的含义是?

答:重新分配地址,地址为NULL空指针(错误

答:申请 1024 个字节的内存空间,并返回地址,相当于 malloc(1024)。

4. 请问下面代码存在什么问题?

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
        static int *pi = (int *)malloc(sizeof(int));

        *pi = 520;
        printf("*pi = %d\n", *pi);

        return 0;
}

答:static修饰的变量为只读,*pi = 520错误(错误

答案:上面程序如果编译会报错,这是因为初始化静态变量时不能调用函数。static 声明的变量在程序运行过程中是始终存在的,通常在 main 函数运行之前就完成了初始化过程。
但 malloc 函数的调用是在 main 函数之后进行的,所以从概念上来说,static 声明的变量不可能通过调用库函数来进行初始化。同样的道理,这个规则对于全局变量来讲也是一样的!
对于静态变量来说,可以通过在后面用一个单独的语句给变量分配内存来避免这个问题:

……
        static int *pi;
        pi = (int *)malloc(sizeof(int));
……

动动手:
0. 编写一个猜拳小游戏,电脑随机出拳,与人类比拼,最后打印结果。
程序实现如下:

答:以后再做c语言小游戏

答案:

#include <stdio.h>
#include <time.h>
#include <stdlib.h>

#define HUMANWIN 0
#define COMPUTERWIN 1

int get_computer(void)
{
        int computer;

        srand((unsigned)time(NULL));
        computer = rand() % 3 + 1;

        return computer;
}

int get_human(void)
{
        int human;

        printf("请出拳(1剪刀/2石头/3布/0退出)-> ");
        scanf("%d", &human);

        while (human < 0 || human > 3)
        {
                printf("出拳错误,请重新出拳(只需要输入数字即可)-> ");
                scanf("%d", &human);
        }

        return human * 3;
}

void welcome(void)
{
        printf("\n########################\n");
        printf("# 欢迎来到猜拳小游戏! #\n");
        printf("########################\n\n");
}

void gameover(int winner)
{
        if (winner)
        {
                printf("\n#########################################################################\n");
                printf("#                                                                       #\n");
                printf("# ##    ##    ####    ##     ##    ##         ####     ######  ######## #\n");
                printf("#  ##  ##    ##  ##   ##     ##    ##        ##  ##   ##       ##       #\n");
                printf("#   ####    ##    ##  ##     ##    ##       ##    ##  ##       ##       #\n");
                printf("#    ##     ##    ##  ##     ##    ##       ##    ##  ######   #######  #\n");
                printf("#    ##     ##    ##  ##     ##    ##       ##    ##       ##  ##       #\n");
                printf("#    ##      ##  ##    ##   ##     ##        ##  ##        ##  ##       #\n");
                printf("#    ##       ####      #####      #######    ####    ######   ######## #\n");
                printf("#                                                                       #\n");
                printf("#########################################################################\n");
        }
        else
        {
                printf("\n##########################################################################\n");
                printf("#                                                                        #\n");
                printf("# ##    ##    ####    ##     ##    ##              ##  ######  ##     ## #\n");
                printf("#  ##  ##    ##  ##   ##     ##    ##      ##      ##    ##    ###    ## #\n");
                printf("#   ####    ##    ##  ##     ##    ##     ####     ##    ##    ## #   ## #\n");
                printf("#    ##     ##    ##  ##     ##     ##   ##  ##   ##     ##    ##  #  ## #\n");
                printf("#    ##     ##    ##  ##     ##      ## ##    ## ##      ##    ##   # ## #\n");
                printf("#    ##      ##  ##    ##   ##        ###      ###       ##    ##    ### #\n");
                printf("#    ##       ####      #####          #        #      ######  ##     ## #\n");
                printf("#                                                                        #\n");
                printf("##########################################################################\n");

        }
}

int main(void)
{
        int human, computer; // 1、2、3分别代表剪刀石头和布
        int result;
        int human_win = 0;
        int computer_win = 0;

        welcome();

        while (1)
        {
                human = get_human();
                computer = get_computer();

                // 用户输入0表示退出游戏
                if (human == 0)
                {
                        break;
                }

                printf("你出");
                switch (human)
                {
                        case 3: printf("剪刀,"); break;
                        case 6: printf("石头,"); break;
                        case 9: printf("布,"); break;
                }

                printf("我出");
                switch (computer)
                {
                        case 1: printf("剪刀,"); break;
                        case 2: printf("石头,"); break;
                        case 3: printf("布,"); break;
                }

                result = human + computer;

                // 你出剪刀,电脑出布:3 + 3 == 6
                // 你出石头,电脑出剪刀:6 + 1 == 7
                // 你出布,电脑出石头:9 + 2 == 11
                // 以上三种情况算你赢~
                if (result == 6 || result == 7 || result == 11)
                {
                        printf("你赢了!\n\n");
                        human_win++;
                }
                else if (result == 5 || result == 9 || result == 10)
                {
                        printf("我赢了!\n\n");
                        computer_win++;
                }
                else
                {
                        printf("咱打平!\n\n");
                }
        }

        // 打平也算人类赢
        if (human_win >= computer_win)
        {
                gameover(HUMANWIN);
        }
        else
        {
                gameover(COMPUTERWIN);
        }
}

1. 编写一个小程序,要求使用本节课学到的函数在堆中申请一个矩阵(二维数组),矩阵的尺寸由用户指定,并且允许修改。该小程序的更多功能及要求如下图所示。

答:无~

答案:

#include <stdio.h>
#include <stdlib.h>

#define MAX_LIMIT_MATRIX 100

void welcome(void);
int get_ins(void);
int *create_matrix(void);
void init_matrix(int *ptr);
void print_matrix(int *ptr);
void write_matrix(int *ptr);
void read_matrix(int *ptr);

void welcome(void)
{
        printf("\n============================\n");
        printf("* 欢迎使用该程序,指令如下 *\n");
        printf("* 1.生成一个 M*N 的矩阵    *\n");
        printf("* 2.初始化矩阵             *\n");
        printf("* 3.给矩阵中某个元素赋值   *\n");
        printf("* 4.读取矩阵中某个元素     *\n");
        printf("* 5.打印整个矩阵           *\n");
        printf("* 6.结束程序               *\n");
        printf("============================\n");
}

int get_ins(void)
{
        int ins;

        printf("\n请输入指令:");
        scanf("%d", &ins);

        while (ins < 1 || ins > 6)
        {
                printf("\n指令错误,请重新输入:");
                scanf("%d", &ins);
        }

        return ins;
}

int *create_matrix(void)
{
        int m, n;
        static int created = 0; // 用于判断是否已经创建过矩阵
        static int *ptr = NULL;

        if (created)
        {
                printf("矩阵已存在,是否需要重新创建?(Y/N)-> ");
                getchar(); // 清除缓冲区残留的换行符
                while (getchar() == 'N')
                {
                        return ptr;
                }
        }

        printf("请输入新矩阵的规模(M*N)-> ");
        scanf("%d*%d", &m, &n);

        while (m < 1 || n < 1)
        {
                printf("规模太小,请重新输入:");
                scanf("%d*%d", &m, &n);
        }

        while (m > MAX_LIMIT_MATRIX || n > MAX_LIMIT_MATRIX)
        {
                printf("规模太大,请重新输入:");
                scanf("%d*%d", &m, &n);
        }

        // 虽然说是矩阵是二维数组,但在C语言中它的存放形式是“平铺”的
        // 这里用realloc,支持重新创建二维数组
        // 这里多申请了两个整形空间,用于存放矩阵的长和宽
        ptr = (int *)realloc(ptr, (m * n + 2)* sizeof(int));
        if (ptr == NULL)
        {
                printf("内存申请失败!\n");
                exit(1);
        }

        printf("%d*%d 的矩阵创建成功!\n", m, n);
        created = 1;

        // 将长和宽放在前两个元素中
        ptr[0] = m;
        ptr[1] = n;

        return ptr;
}

void init_matrix(int *ptr)
{
        int m = ptr[0];
        int n = ptr[1];
        int *matrix = ptr + 2;
        int num, i, j;

        if (ptr == NULL)
        {
                printf("未检测到矩阵,请先生成矩阵!\n");
                return ;
        }

        printf("请输入一个数字:");
        scanf("%d", &num);

        for (i = 0; i < m; i++)
        {
                for (j = 0; j < n; j++)
                {
                        matrix[i * n + j] = num;
                }
        }
}

void print_matrix(int *ptr)
{
        int m = ptr[0];
        int n = ptr[1];
        int *matrix = ptr + 2;
        int i, j;

        if (ptr == NULL)
        {
                printf("未检测到矩阵,请先生成矩阵!\n");
                return ;
        }

        for (i = 0; i < m; i++)
        {
                for (j = 0; j < n; j++)
                {
                        printf("%d  ", matrix[i * n + j]);
                }
                putchar('\n');
        }
}

void write_matrix(int *ptr)
{
        int m = ptr[0];
        int n = ptr[1];
        int *matrix = ptr + 2;
        int num, x, y;

        if (ptr == NULL)
        {
                printf("未检测到矩阵,请先生成矩阵!\n");
                return ;
        }

        printf("请输入要修改的位置(行,列)-> ");
        scanf("%d,%d", &x, &y);

        if (x > m || y > n || x < 1 || y < 1)
        {
                printf("坐标输入有误!\n");
                return ;
        }

        printf("请输入一个数字:");
        scanf("%d", &num);

        matrix[(x - 1) * n + (y - 1)] = num;
}

void read_matrix(int *ptr)
{
        int m = ptr[0];
        int n = ptr[1];
        int *matrix = ptr + 2;
        int num, x, y;

        if (ptr == NULL)
        {
                printf("未检测到矩阵,请先生成矩阵!\n");
                return ;
        }

        printf("请输入要读取的位置(行,列)-> ");
        scanf("%d,%d", &x, &y);

        if (x > m || y > n || x < 1 || y < 1)
        {
                printf("坐标输入有误!\n");
                return ;
        }

        printf("第%d行,第%d列的数字是:%d\n", x, y, matrix[(x - 1) * n + (y - 1)]);
}

int main(void)
{
        int ins;
        int *ptr = NULL;

        welcome();

        while((ins = get_ins()) != 6)
        {
                switch(ins)
                {
                        case 1: ptr = create_matrix(); break;
                        case 2: init_matrix(ptr); break;
                        case 3: write_matrix(ptr); break;
                        case 4: read_matrix(ptr); break;
                        case 5: print_matrix(ptr); break;
                }
        }

        printf("\n感谢使用本程序^_^\n\n");

        free(ptr);

        return 0;
}

  • 14
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值