鱼C论坛

 找回密码
 立即注册
查看: 2324|回复: 5

请老师指点C语言课后题S1E38课后题第一题

[复制链接]
发表于 2018-7-20 21:37:47 | 显示全部楼层 |阅读模式
10鱼币
以下是答案全文(http://bbs.fishc.org/thread-80430-1-5.html
----------------------------------------------------------------------------------
  
  #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;
    }

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2018-7-20 21:54:16 | 显示全部楼层
静态局部变量是放在数据段里的,申请的内存是放在堆里的,我想请问一下malloc后这个ptr指针会不会改变存放地址,还是双属性既有静态局部变量属性又有动态内存属性?

捕获.PNG
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2018-7-20 22:02:03 | 显示全部楼层
二,static局部变量

      普通的局部变量在栈空间上分配,这个局部变量所在的函数被多次调用时,每次调用这个局部变量在栈上的位置都不一定相同。局部变量也可以在堆上动态分配,但是记得使用完这个堆空间后要释放之。

       static局部变量中文名叫静态局部变量。它与普通的局部变量比起来有如下几个区别:

           1)位置:静态局部变量被编译器放在全局存储区.data(注意:不在.bss段内,原因见3)),所以它虽然是局部的,但是在程序的整个生命周期中存在。

           2)访问权限:静态局部变量只能被其作用域内的变量或函数访问。也就是说虽然它会在程序的整个生命周期中存在,由于它是static的,它不能被其他的函数和源文件访问。

           3)值:静态局部变量如果没有被用户初始化,则会被编译器自动赋值为0,以后每次调用静态局部变量的时候都用上次调用后的值。这个比较好理解,每次函数调用静态局部变量的时候都修改它然后离开,下次读的时候从全局存储区读出的静态局部变量就是上次修改后的值。
以下是一些示例程序:


参考:https://www.cnblogs.com/JMatrix/p/8194009.html
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2018-7-20 22:20:04 | 显示全部楼层
ba21 发表于 2018-7-20 22:02
二,static局部变量

      普通的局部变量在栈空间上分配,这个局部变量所在的函数被多次调用时,每次调 ...

天资愚钝,我把static int *p = NULL前的static去掉好像也可以正常运行,没有看出这个static的精妙所在
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2018-7-20 22:35:54 | 显示全部楼层
其实源代码还有小问题
        if (ptr == NULL)
        {
                printf("未检测到矩阵,请先生成矩阵!\n");
                return;
        }

这个要放在函数的开头部分
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2018-7-20 23:19:28 | 显示全部楼层
可能是比较谨慎的写法,不要返回局部变量的指针
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-3-29 16:56

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表