鱼C论坛

 找回密码
 立即注册
查看: 1970|回复: 8

[已解决]关于这段代码的几个问题

[复制链接]
发表于 2023-1-1 20:59:15 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
  1. #include <stdio.h>
  2. #include <stdlib.h>

  3. #define MAX_LIMIT_MATRIX 100

  4. void welcome(void);
  5. int get_ins(void);
  6. int *create_matrix(void);
  7. void init_matrix(int *ptr);
  8. void print_matrix(int *ptr);
  9. void write_matrix(int *ptr);
  10. void read_matrix(int *ptr);

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

  23. int get_ins(void)
  24. {
  25.         int ins;

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

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

  33.         return ins;
  34. }

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

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

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

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

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

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

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

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

  75.         return ptr;
  76. }

  77. void init_matrix(int *ptr)
  78. {
  79.         int m = ptr[0];
  80.         int n = ptr[1];
  81.         int *matrix = ptr + 2;
  82.         int num, i, j;

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

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

  90.         for (i = 0; i < m; i++)
  91.         {
  92.                 for (j = 0; j < n; j++)
  93.                 {
  94.                         matrix[i * n + j] = num;
  95.                 }
  96.         }
  97. }

  98. void print_matrix(int *ptr)
  99. {
  100.         int m = ptr[0];
  101.         int n = ptr[1];
  102.         int *matrix = ptr + 2;
  103.         int i, j;

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

  109.         for (i = 0; i < m; i++)
  110.         {
  111.                 for (j = 0; j < n; j++)
  112.                 {
  113.                         printf("%d  ", matrix[i * n + j]);
  114.                 }
  115.                 putchar('\n');
  116.         }
  117. }

  118. void write_matrix(int *ptr)
  119. {
  120.         int m = ptr[0];
  121.         int n = ptr[1];
  122.         int *matrix = ptr + 2;
  123.         int num, x, y;

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

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

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

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

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

  140. void read_matrix(int *ptr)
  141. {
  142.         int m = ptr[0];
  143.         int n = ptr[1];
  144.         int *matrix = ptr + 2;
  145.         int num, x, y;

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

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

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

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

  160. int main(void)
  161. {
  162.         int ins;
  163.         int *ptr = NULL;

  164.         welcome();

  165.         while((ins = get_ins()) != 6)
  166.         {
  167.                 switch(ins)
  168.                 {
  169.                         case 1: ptr = create_matrix(); break;
  170.                         case 2: init_matrix(ptr); break;
  171.                         case 3: write_matrix(ptr); break;
  172.                         case 4: read_matrix(ptr); break;
  173.                         case 5: print_matrix(ptr); break;
  174.                 }
  175.         }

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

  177.         free(ptr);

  178.         return 0;
  179. }
复制代码

1.我不太清楚为什么init_matrix和print_matrix函数中ptr要+2而不是+8,int不是一个4字节吗
2.这段代码如果第一次输入指令2 3 4 5会发生段错误,这是为什么呢
最佳答案
2023-1-1 22:41:12
第一个问题,你还没看懂这段代码的整体设计。他的思路是让你输入m,n
但是实际操作的时候申请一段空间地址是ptr,这段空间第一个位子存储的是m,第二个位子存储的是n。真正的二维数组是从第三个位子开始存储的
代码写的清清楚楚
  1. // 这里多申请了两个整形空间,用于存放矩阵的长和宽
  2.         ptr = (int *)realloc(ptr, (m * n + 2)* sizeof(int));
  3.         if (ptr == NULL)
  4.         {
  5.                 printf("内存申请失败!\n");
  6.                 exit(1);
  7.         }

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

  10.         // 将长和宽放在前两个元素中
  11.         ptr[0] = m;
  12.         ptr[1] = n;
复制代码

所以才要ptr+2好指向二维数组的第一个元素。这是第一个问题的原因


第二个问题代码写错了。2 3 4 5功能函数里的
  1. if (ptr == NULL)
  2.         {
  3.                 printf("未检测到矩阵,请先生成矩阵!\n");
  4.                 return ;
  5.         }
复制代码

都应该写在对于函数的第一行。至少应该在  int *matrix = ptr + 2;  这句话的上面,按照这个代码,你的 int *matrix = ptr + 2; 写在上面,万一ptr是空指针代码直接崩溃不是很正常的吗?所以那几个函数都应该先判断是否为空指针
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2023-1-1 21:58:43 | 显示全部楼层
202311_215824.png
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-1-1 22:30:43 | 显示全部楼层

请问为什么会发生段错误,不太理解
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-1-1 22:32:37 | 显示全部楼层

还想问一下你这个图里给指针赋值88是什么意思
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-1-1 22:40:21 | 显示全部楼层
pkqbszs 发表于 2023-1-1 22:32
还想问一下你这个图里给指针赋值88是什么意思

.我不太清楚为什么init_matrix和print_matrix函数中ptr要+2而不是+8,int不是一个4字节吗
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-1-1 22:41:12 | 显示全部楼层    本楼为最佳答案   
第一个问题,你还没看懂这段代码的整体设计。他的思路是让你输入m,n
但是实际操作的时候申请一段空间地址是ptr,这段空间第一个位子存储的是m,第二个位子存储的是n。真正的二维数组是从第三个位子开始存储的
代码写的清清楚楚
  1. // 这里多申请了两个整形空间,用于存放矩阵的长和宽
  2.         ptr = (int *)realloc(ptr, (m * n + 2)* sizeof(int));
  3.         if (ptr == NULL)
  4.         {
  5.                 printf("内存申请失败!\n");
  6.                 exit(1);
  7.         }

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

  10.         // 将长和宽放在前两个元素中
  11.         ptr[0] = m;
  12.         ptr[1] = n;
复制代码

所以才要ptr+2好指向二维数组的第一个元素。这是第一个问题的原因


第二个问题代码写错了。2 3 4 5功能函数里的
  1. if (ptr == NULL)
  2.         {
  3.                 printf("未检测到矩阵,请先生成矩阵!\n");
  4.                 return ;
  5.         }
复制代码

都应该写在对于函数的第一行。至少应该在  int *matrix = ptr + 2;  这句话的上面,按照这个代码,你的 int *matrix = ptr + 2; 写在上面,万一ptr是空指针代码直接崩溃不是很正常的吗?所以那几个函数都应该先判断是否为空指针
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-1-1 22:43:52 | 显示全部楼层
整形指针+2 是跳过两个整型,即8个地址位
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-1-1 23:15:57 | 显示全部楼层
洋洋痒 发表于 2023-1-1 22:41
第一个问题,你还没看懂这段代码的整体设计。他的思路是让你输入m,n
但是实际操作的时候申请一段空间地址 ...

谢谢哥,全明白了
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-1-2 08:20:01 | 显示全部楼层
来看看
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-4-22 23:38

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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