1 / 41

多维数组与指针

多维数组与指针. 用指针变量可以指向一维数组中的 元素 ,也可以指向多维数组中的 元素 。但在概念上和使用上,多维数组的指针比一维数组的指针要复杂一些。. 1. 多维数组元素的地址. 先回顾多维数组的性质 , 可以认为二维数组是“数组的数组”,例 : 定义 int a[3][4] ={{1 , 3 , 5 , 7} , {9 , 11 , 13 , 15} , {17 , 19 , 21 , 23}} ; 则二维数组 a 是由 3 个一维数组所组成的。设二维数组的首行的首地址为 2000 ,则. 输出二维数组有关的值. #include<stdio.h>

vui
Download Presentation

多维数组与指针

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 多维数组与指针 用指针变量可以指向一维数组中的元素,也可以指向多维数组中的元素。但在概念上和使用上,多维数组的指针比一维数组的指针要复杂一些。 1. 多维数组元素的地址 先回顾多维数组的性质,可以认为二维数组是“数组的数组”,例 : 定义int a[3][4]={{1,3,5,7},{9,11,13,15},{17,19,21,23}}; 则二维数组a是由3个一维数组所组成的。设二维数组的首行的首地址为2000 ,则

  2. 输出二维数组有关的值 #include<stdio.h> #define format″%d,%d\n″ void main() {int a[3][4]={1,3,5,7,9,11,13, 15,17,19,21,23}; printf(format,a,*a); printf(format,a[0] , *(a+0)); printf(format,&a[0],&a[0][0]); printf(format,a[1],a+1); printf(format,&a[1][0],*(a+1)+0); printf(format,a[2],*(a+2)); printf(format,&a[2],a+2); printf(format,a[1][2],*(*(a+1)+2)); }

  3. 某一次运行结果如下: 1244900,1244900 (0行首地址和0行0列元素地址) 1244900,1244900 (0行0列元素地址) 1244900,1244900 (0行0首地址和0行0列元素地址) 1244916,1244916 (1行0列元素地址和1行首地址) 1244916,1244916 (1行0列元素地址) 1244932,1244932 (2行0列元素地址) 1244932,1244932 (2行首地址) 13,13 (1行2列元素的值)

  4. 上机过程中的问题 • 养成良好的程序书写风格 • 变量、函数的命名:体现其意义 • if/else、swith/case、for、while等复合语句中{ }的使用 • { }内代码的缩进 • 适当的空行 • 适当的注释 • 避免太长的语句、适当的换行

  5. 上机过程中的问题 • 应该: • 仔细分析问题 • 考虑各种情况 • 把自己当作计算机,给定输入,再运行一下程序 • 误解: • 在VC环境中写完程序后,就拷贝到编程网格上提交 • 在VC环境中编译正确,程序就是正确的 • 对于给出的样例输入,输出正确,程序就是正确的 程序运行不正确,怎么办?

  6. 程序的调试 • 语法错误:编译(组建)错误 • 不要惊慌,编译结果输出窗口已经为你指明了程序的出错行及错误原因,可以据此来修改程序错误。 • 改错时,应从出错信息中的第一条开始,用鼠标双击该条信息,程序源文件窗口就将定位到出错行。 • 很多时候,程序编译后会出很多错误,但很可能是由第一个错误衍生而来的,改完第一个错误后,再编译时其他错误就不再出现了。所以,应该每修改完一个错误后就编译一次。

  7. 这里的一堆错误,都是由于上面少了一个“{”引起的!这里的一堆错误,都是由于上面少了一个“{”引起的! 二、关于程序的错误修改及调试 这里少了一个“{”。 { 双击第一行,定位错误及了解错误原因!

  8. 程序的调试 • 运行结果错:程序跟踪调试 • 由于程序算法及其他原因,执行结果不正确,这时从源程序表面上就很难发现错误。 • 跟踪调试:可以手动一步一步执行程序语句,在每条语句执行后,可以查看相关变量的值,以判断和预期结果是否相符;也可以了解程序的执行顺序,看它是否和预期的程序流程相符。 • 断点设定:在跟踪调试前,还需要确定一下程序可能从哪里出错,设置一个断点,让程序在此停止自动运行,由我们手动一步一步发出程序执行命令。如果不能确定程序是从哪里出错,则可以将断点设置在程序的第一条语句处。

  9. 设置程序断点

  10. 跟踪方式执行程序 • 程序手动执行 • 进入函数 • 一步一步执行 • 从函数中执行出来 • 执行到光标所在行 查看变量值 当前程序执行停留在此行 手动设置变量,查看变量值

  11. 问题1:骑车与走路

  12. n 没有上限了! 骑车: 找到并启动自行车27秒; 停车锁车23秒; 速度3.0米/秒; 走路: 速度1.2米/秒;

  13. 假设 n 的上限是10

  14. #include <stdio.h> #define N10 void compute(int distance); int main(){ int n; int distance[N]; int i; scanf("%d", &n); for(i = 0; i < n; i++){ scanf("%d", &(distance[i])); } for(i = 0; i < n; i++){ compute(distance[i]); } return 0; } void compute(int distance){ int timeBike = 27 + 23 + distance/3; int timeWalk = (int)(distance/1.2); if(timeBike < timeWalk){ printf("Bike\n"); } else if (timeBike > timeWalk){ printf("Walk\n"); } else { printf("All\n"); } } 提交到编程网格。结果是… …

  15. 把n的上限修改为100

  16. #include <stdio.h> #define N100 void compute(int distance); int main(){ int n; int distance[N]; int i; scanf("%d", &n); for(i = 0; i < n; i++){ scanf("%d", &(distance[i])); } for(i = 0; i < n; i++){ compute(distance[i]); } return 0; } void compute(int distance){ int timeBike = 27 + 23 + distance/3; int timeWalk = (int)(distance/1.2); if(timeBike < timeWalk){ printf("Bike\n"); } else if (timeBike > timeWalk){ printf("Walk\n"); } else { printf("All\n"); } } 提交到编程网格。结果是… …

  17. WHY?

  18. 编程网格判断程序是否正确的机制 对每一个题目, 编程网格预先设定了一组测试数据; 只要你的程序在这组测试数据下正确, 编程网格即认为你的程序是正确的; 在骑车与走路这个题目中, 编程网格使用的测试数据中,所有的n 都小于100

  19. 有没有更稳妥的办法呢?

  20. 动态数组

  21. 静态数组 int sz[10]; 必须是一个常量 静态数组的长度在编译时刻就确定了; 如何能在程序的运行时刻, 动态地确定一个数组的长度呢?

  22. 动态数组 #include <stdio.h> int main(){ int n; scanf(“%d”, &n); int shzu[n]; return 0; } 在VC下编译失败! error C2133: 'shuzu' : unknown size 怎样才能实现 动态数组?

  23. 动态数组 • 如何实现动态数组? • 1、使用指针 • 2、自己申请内存

  24. 动态数组 #include <stdio.h> #include <malloc.h> int main(){ int n; scanf(“%d”, &n); int *shzu = (int *) malloc(sizeof(int)* n); … … free(shuzu); return 0; } #include <stdio.h> int main(){ int n; scanf(“%d”, &n); int shzu[n]; … … return 0; }

  25. 动态数组 #include <stdio.h> #include <malloc.h> int main(){ int n; scanf(“%d”, &n); double *shzu = (double *) malloc(sizeof(double)* n); … … free(shuzu); return 0; } #include <stdio.h> int main(){ int n; scanf(“%d”, &n); doubleshzu[n]; … … return 0; }

  26. 关于malloc()/free()的使用 • 别忘了: #include <malloc.h> • malloc函数的参数为所需申请内存的大小:以字节为单位 • malloc函数返回一个void*类型的地址,必须通过强制类型转换,才能赋值给特定的指针变量: • int * pint = (int *) malloc( ... ); • 用malloc函数生成各种类型的动态数组,最好使用“sizeof(类型名) * 动态数组长度”形式确定分配内存的大小: • int * pint = (int *) malloc( sizeof(int) * 100 ); • 分配的内存不再使用时一定要释放: • free(pint);

  27. 0 1 2 3 4 5 6 7 8 9 10(?) ? 动态数组 • malloc()在内存中分配的一块连续的内存区域,这与静态数组在内存中的布局是一样的。因此,指向这块内存区域的指针变量就可以像数组一样使用了: • int *pint; • pint = (int *)malloc(sizeo(int)*10); • pint[0], pint[1], ……, pint[9] • 在使用动态数组时,一定要注意不要越界引用,即不要引用并没有分配给你使用的内存: • 当引用pint[10] 时,对于C语言来说,这是合法的,但是它所引用的却是所分配的内存区域之外的其他内存区域,其内的值是未知的;如果对其进行修改的话,还可能影响整个程序的正确性。 pint pint+10

  28. #include <stdio.h> #define N10 void compute(int distance); int main(){ int n; int distance[N]; int i; scanf("%d", &n); for(i = 0; i < n; i++){ scanf("%d", &(distance[i])); } for(i = 0; i < n; i++){ compute(distance[i]); } return 0; } #include <stdio.h> #include <malloc.h> void compute(int distance); int main(){ int n; int i; scanf("%d", &n); int *distance = (int *) malloc(sizeof(int)*n); for(i = 0; i < n; i++){ scanf("%d", &(distance[i])); } for(i = 0; i < n; i++){ compute(distance[i]); } free(distance); return 0; }

  29. 问题2:跳绳游戏

  30. 关键信息: • 计算1分钟内跳了多少下绳; • 1秒钟跳1次; • 跳坏后,3秒钟后才能又开始跳;

  31. 输入、输出示例 = 60 – 0 * 3 = 60 – 3 * 3 = 60 – 1 * 3 = 60 – 4 * 3 = 60 – 4 * 3 = 47

  32. 输入:0输出:60 在y秒时,小朋友停止了跳绳 y秒 0秒 60秒 60下

  33. 输入:3 12 23 45输出:51 在y秒时,小朋友停止了跳绳 y秒 0秒 12秒 60秒 15秒 26秒 29秒 51秒 54秒 12下 23下 23下 45下 45下 12下 51 = 60 – 3*3

  34. 输入:1 17输出:57 在y秒时,小朋友停止了跳绳 y秒 0秒 60秒 17秒 20秒 17下 17下 57 = 60 – 1*3

  35. 输入:4 10 20 30 40输出:48 在y秒时,小朋友停止了跳绳 y秒 0秒 60秒 36秒 49秒 10秒 23秒 26秒 13秒 52秒 39秒 40下 30下 10下 20下 40下 20下 10下 30下 48 = 60 – 4*3

  36. 输入:5 10 20 30 40 58输出:48 60秒 0秒 36秒 49秒 70秒 10秒 23秒 73秒 52秒 26秒 39秒 13秒 58下 40下 10下 30下 20下 30下 58下 40下 20下 10下 48 = 60 – 4*3

  37. 输入:6 10 20 30 40 47 60输出:47 0秒 60秒 36秒 49秒 59秒 75秒 10秒 23秒 13秒 39秒 26秒 62秒 78秒 52秒 40下 20下 47下 60下 10下 30下 47下 60下 30下 20下 40下 10下 47

  38. 问题分析 60秒 60秒 0秒 Case 1 Case 2

  39. 请同学们课后思考 如何编写这个程序

  40. 下课!

More Related