收藏 分销(赏)

C语言研究性学习的路线.docx

上传人:二*** 文档编号:4708660 上传时间:2024-10-10 格式:DOCX 页数:37 大小:181.69KB 下载积分:5 金币
下载 相关 举报
C语言研究性学习的路线.docx_第1页
第1页 / 共37页
本文档共37页,全文阅读请下载到手机保存,查看更方便
资源描述
C语言研究性学习的路线 现行的多数C语言教材有太多的误区,不仅不能给读者提供有效的学习线索,还常常“误 导”读者,于是,“死记硬背”便成了学习C语言的唯一选择。本文以拙作《新编C语言程 序设计教程》(清华大学出版社出版,博客blog. csdn. net/stunt配套视频zeql26. 56. com) 为基础,探讨了 C语言的研究性学习。 C语言的学习可分为四个阶段。 第一阶段 理解C语言与计算机的关系 理解计算机如何计算。 计算机由五大部件组成,C语言如何使用这五大组成部件? 计算机采用二进制,那么正负号,小数点、字符等如何在计算机中存储?采用不同的编 码方式,计算机中的运算与数学上的运算有何异同? 在理解上述问题的基础上,能根据优先级、结合性、数据类型和序列点熟练地对C语言 表达式求值,也就是能模拟计算机进行计算。 第二阶段掌握编程方法 计算机通过连续地对表达式求值(计算)解决实际问题。 掌握逻辑运算之后,理解计算机解决问题的方法,即有条件地重复。编程的关键在于找 到利用“重复”解决问题的方法。算一次加法,再算一次加法,又算一次加法,“重复加”, 如1+2+3+…+100。大僧人数为1时满足条件吗?大僧人数为2时满足条件吗?大僧人数为3 时满足条件吗? “重复试”,如百僧百馍问题。 遇到问题•定要先用自己的超级计算机(大脑)分析问题找出重复,再用循环把重复表 达出现,这就是编程。 第三阶段用函数组织代码当程序由多个函数组成时,可以借助对函数封闭性的研究来理解这一阶段遇到的问题。 递归函数是个奇迹,自然而优雅地模拟了递归算法。递归算法是更高级的重复。 第四阶段掌握指针的用法 指针提供了使用内存中相关存储单元的另一种途径。 由于只需某类型的地址,就可使用相关存储单元,指针变量可以提高函数的执行效率。 由于void型指针变量的特点,程序中的某些函数可以超越类型的限制而具有了某种通用性。 理解了指针的作用,掌握指针也并非什么难事。 C语言的知识点有: 1 . C语言与计算机的关系 2 .表达式的求值 3 .逻辑运算及选择结构 4 .算法及循环结构 5 .数组的作用及准确理解 6 .函数的作用及准确理解 7 .指针的作用及准确理解 8 . 其它 这几局部相辅相成,构成了一个有机的整体。分析如下: 重点: 1 .作用。(用于改写简单的if-else结构) 2 .显然?处有一个序列点,保证了执行过程与if-else结构的完全一致。 3 .总结C语言中操作符的4个序列点的作用。 switch结构 重点: 1 .理解switch结构的语法。(常量表达式,default子句的次序).分析switch结构的执行过程。(体会case标号的作用。为什么常量表达式的值不 能为浮点数?) 2 . break语句对swi tch结构的影响。 3 .有break语句的switch结构的作用。(改写为if结构时如何确定default子句的 条件)(六)典型例题 关键在于学习如何分析解决问题,培养锻炼自己的编程能力。不要在意你能否做出这些 题,如果能,一定要比照分析;如果不能,一张白纸也并非什么坏事。 例4T8升序排列输入的3个整数a, b,c。(注意处理后应让a的值最小,c的值最大) 步骤: 1 .第一步先把b插入到前面有序的了•序列中使a, b有序:第二步再把c插入到前面有 序的子序列中使a, b,c有序,任务完成。 这一步似乎解决了问题,但又好像没有“解决”问题。体会这种分析方法的特点。 (从宏观上研究问题,由于忽略了次要因素从而易于把握关键点。又好像在做可行 性分析。) 2 .再讨论每一步的细节,究竟该如何做。 如何使a, b有序?(这一步没有难度,大局部同学都可以写出伪代码) 如何使a, b, c有序?(局部同学忽视了前提条件此时a, b已经有序。可直接思考也 可举例分析,但要考虑不同的情况) 分b不小于c和b大于c两种情况,当b>c时需要排序,否那么已经有序。显然这是 个if结构。 在这里b>c为真意味着什么? b最大,需要互换b,c的值。换完后a, b,c有序了吗?处于什么状态?(c的值最 大,但a的值是否最小还不一定) 注意: 1. 体会从分析问题到给出解决问题的步骤再到写出程序的编码过程。体会程序中每行代码究竟意味着什么样的处理过程。两者对照,体会“编程”。 2. 此题采用的是“自顶向下,逐步求精”的分析方法,体会其特点。 3. 练习4. 20的算法也解决了这个问题,体会两者的区别。再通过练习4. 21排序5个整数,分析两者的区别。 4. . 练习4. 21不仅让大家通过实践体会了这种排序方法“先进性”,更重要的是引 导大家发现“重复性”,为用“循环”解决这个问题埋下伏笔。 如果学完了例4-18,只学会了对三个数排序而没有体会到什么是编程,什么是“自顶向 下,逐步求精”,不能不说是个遗憾。 例479判断闰年。 算法: 如果不是4的倍数,那么不是闰年。 否那么〈是4的倍数〉如果不是100的倍数,那么是闰年。 否那么〈是100的倍数〉如果不是400的倍数,那么不是闰年。 否那么〈是400的倍数〉 是闰年。 重点: 1 .体会编程时需要的条理性、逻辑性。 2 . else if的用法。(仅仅是简写形式) 例4-20百分制成绩转换成A-E五级成绩。 重点: 1. 先分析出关键处理的流程图。再次体会思路的逻辑性,条理性。(也可直接用五条 if 语句,如 if (grade<=100 && grade>=90) putchar('A');,但要改成 if-else 结构,因为效率问题。改写时注意提醒。Ise也是条件再判断时就没必要用&&了。) 2. 根据流程图写出程序。 3. 比照练习4. 23的流程图,同样的问题不同处理过程,分析两者的区别。 例4-21用switch结构改写例4-20。 结合switch结构的作用,针对问题,找出矛盾。转变思路,解决问题。(问题的解法 有多种,结合要求,具体问题具体分析。) 例4-22判断用户输入的含+-*/的等式如3. 11+3. 12=6. 23是否成立。 算法: 1 .获得用户的输入数据 2 .根据等式中的运算符(+-*/)计算出正确的结果。 3 .比拟运算结果与用户的输入结果判断用户输入的等式是否成立。 重点: 1 .用户的输入分为浮点型和字符型。 2 .用switch结构实现“相等关系”的多分支,而非if-else结构。 3 .浮点型数据通常不直接比拟是否相等,需要比拟时常用的方法是如果两数之差绝对 值小于某数就认为两者相等。 所谓“误差累枳”是指3.11赋值给变量fa时有误差3.12赋值给变量fb时也有误 差,fa与fb之和的误差由于累积跟6. 23赋值给变量fc时产生的误差不同了,因 此fa+fb不等于fc。(如果fa=6. 23; fb=6. 23;,那么fa和fb当然相等。如果 fa=0. 3 ;fb=0. 5; fc=0. 8;那么 fa+fb 与 fc 相等吗?) 再回顾问题:switch结构中为何通常不用浮点型做标号? 四、算法及循环结构 /*前言 这注定又是……的一章。 算法的精髓是“循环”,而构造循环的能力只能在一次次的分析、编码、调试、比照、 思考中培养。除了一道道的演示,我实在想不出其它的方法可以“速成”,毕竟如表达式求 值似的总结个一二三四的速成法仅适用于“知识”。关于编程,有的人似乎“天生”就会, 有的人可能“上手”较慢,所幸正如武侠书中的演绎,并非“上手”越快就一定走得越远。 */ (一)再谈算法 屡次指出,编写程序的过程为:分析问题,得到解决问题的步骤,最后把步骤“翻译” 成相应的语句。解决问题的步骤就是算法。问题的解法可能有多种,行之有效的方法通常与 欲使用的工具相关,也就是说,必须结合工具的特点思考问题的解法。 计算机解决问题主要靠循环!运用循环的熟练程度直接反映了一个程序员的编程水平。 亳不夸张地说,思考问题的解法就是考虑“如何构造循环”。 循环是有条件的重复,是“螺旋式上升”,是“波浪式前进”。 (Zl) while循环结构 重点: 1. while循环结构的形式。 其与if结构有何异同?(从形式、执行过程、流程图) 2 . while循环结构的特点。 while循环结构的循环体执行多少次?(再次强调由循环控制表达式决定) 如何使用while循环结构输出五个*号?(由具体例如展开,总结while循环结构使用 的3个特点:设置循环变量的初值、决定循环控制表达式、调整循环变量的值) 由例5-1熟悉不同while循环结构的执行情况。(循环次数固定的,输出A至循 环次数不定的,(L0/i>L23e-3),体会作用“求出了倒数小于0. 00123的最小整数”,注 意循环执行完毕后循环变量的值;复杂的循环,含有switch结构。可结合循环结构使用特 点) 难点: while循环结构的用法。(关键在于如何得到“重复”的过程) 例 5-2 求 1+2+3+-+100 的和。 1 . 先计算1+2+3+4+5,总结规律:“重复算加法”,加数为“上一次的和”与“一 个新的加数”。如何使用while循环结构来模拟这个过程呢?加到何时为止?新 的加数大于5为止,因此循环控制表达式为i<=5 (i代表新的加数),循环体为 sum=sum+i (sum 为上一次的和)。 2. 尝试写程序。 3. 分析执行过程,并与列式计算过程比照,体会两者的共同之处。 例5-3输出一个正整数各位上的数字和。 1 . 以2325为例,2+3+2+5=12,本质上也是“重复算加法”,但此例与例5-2有何 不同?新的加数为“各位上的数字”,没有规律,需要在加之前求出它。(考虑 是从左向右算呢,还是从右向左算?)加到何时为止? “加完”为止,即新的加 数为。时为止,因此“新的加数为0”可以作为循环控制的条件。当然此时就可 写出程序了。(不过程序可能出现错误,如1002时。)再想‘'什么情况下新的 加数为'标志结束的’0? ”,那么经过深入分析可以得到正确的程序。 2, 尝试写出程序。 3, 分析执行过程,体会程序中每条语句的作用。体会如何让循环“螺旋式上升”, “波浪式前进”。(在下次循环之前先做好准备,“恢复状态”,此例为“去掉” 加过的数字。) 例5-4百僧分百馍 1 .总共有多少种可能?对于每种情况,处理方式相同吗?(本质也是重复) 2 .尝试写出并分析程序的执行情况。 3 .体会用计算机解决问题的特点。(一个一个地试。美其名曰“穷举法”).这个程序在理论上有问题。(应确保小僧的人数为3的倍数,即需同时保证 (100-i)%3=0 为真) (三)for循环结构 为了使循环结构更紧凑,更优雅,C语言提供了 for循环结构。 重点: 1 .for循环结构的一般形式。(典型循环结构的3个特点与for循环结构的对应关系。理解了对应关系自然也就弄懂了 for循环结构。) 2 .for循环结构的特点。(表达式1和表达式2可以为逗号表达式。表达式省略后应如何理解) 难点: 虽然同样为构造循环,同样为“找重复”或“穷举”,但是此处例如的难度有所增加。 例5-6输出100以内奇数之和与偶数之和。 1 .不同的理解可能有不同的算法。1+3+5+-+99 2+4+6+…+100,可以用两个循环结构实现。也可合并为一个从1至100的循环,循环体内用if-else结构。 2 .最终归结为 for (i=l; i<=99; i+=2) {oddsum+=i ;evensum+=i+l;}。 3 .对循环过程分析得越透彻算法的效率越高。 例5-7求正整数m和n的最小公倍数。 1. 公倍数i可能的取值为m, 2*m, 3*m, -n*m,如果i也为n的倍数,那么i就是所要 求的公倍数。显然是穷举法。 2. 写出程序。运行时会发现错误。分析出错的原因。(程序在什么情况下出错,什 么情况下不会出错?) 3. 如何修改?(修改循环控制的条件。应为i不为n的倍数,而非i<=n*m) 4. .循环体竟然是传说中的空语句,呵呵。 例5-8输出斐波那契数列的前30项。 1. 分析从第3项开始的计算过程,手工模拟计算直到熟悉计算过程,找出计算第i 项时的“标准化”步骤。 2. 注意输出结果的安排。 总结: 循环结构的关键在于“第i次循环”有什么作用?循环是如何模拟手工过程的。为了循 环必须把手工过程“标准化”。 (四)break语句和continue语句 重点: 1. . break语句与continue语句的区别和联系。(常用于if结构中,在某些条件下 均可影响循环结构的执行。break语句终止循环结构的执行,而continue语句 终止循环结构的一次执行。)break语句的作用为终止所属结构的执行。(注意其是属于哪个循环结构,有时 可能是哪个switch结构) 2. continue语句如何用选择结构替换? 难点: 例5-9判断正整数n是否为质数。 分析:如果从2至nT均不为n的因数,那么n就是质数。处理过程为:2是因数吗? 3 是吗?循环(穷举)。 循环变量i从2至n-1,对于第i次循环,作用为判断i是否为n的因数。如果i为n 的因数,那么不用再判断其它数,可以立即终止循环了。否那么什么也不用做,显然循环体为一 个if结构。 循环执行完毕,如何判断n是否为质数?或者说,如何判断2至n-1中是否有n的因数? 假设其中有n的因数,那么循环如何执行?没有的话,循环又会如何执行? 循环结束后循环变量i的值反映了循环的执行情况,并最终决定了 n是否为质数。 注意: 1 .体会分析过程。 2 .用特殊数据1测试程序时应输出不为质数。 (五)循环的嵌套 重点:复杂循环结构的构造。仍然为“找重复”或“穷举”,不过要有一点“白顶向下” 的思路。 例5-11输出如下列图形 * ** *** ****.如果是通过重复输出了这个图形,那么每次完成什么工作?(输出一•行!重复5次 输出5行) 1 .第i次循环需要完成什么工作?(输出i个*,再输出一个5') 2 .尝试编程,并详细分析程序的运行情况。体会思路。 3 .成功="自顶向下,逐步求精”的思路+通过“调试执行”认真分析其执行过程的 耐心。 例572输出如下列图形 * *** *****. 第i次循环需要完成什么工作?(空格+*+'\n:多少个空格?第1行2个,第2 行1个,第3行0个,…显然第i行为3-i个。) 1 .空格个数的规律是在列举大量数据的基础上得到的,没什么技巧,只有“汗水”。 例5T3输出100以内的质数。 1 .循环变量i从2至100,第i次循环判断i是否为质数。(穷举。先写出判断i是否 为质数的代码段,再外加一个循环即可) 2 .体会程序的执行过程。 3 .注意输出的安排。 (六)do-while循环结构 重点: 1 .其与while循环结构的区别和联系。 2 . do-while循环结构与continue语句的配合作用有什么效果。 3 . do-while循环结构的常见用法可参考例5-14.(循环执行程序) (七)典型例题 注重分析能力的培养,强调循环的构造能力。 例5-15求1!+2例…+10! 本质上是重复加,在第i次循环中需要先求出新的加数即i的阶乘。 1 .通过循环求出i的阶乘,这是一个循环的嵌套。(嵌套循环的构造及执行过程) 2 .设i的阶乘为mi项,那么有皿二niiT*i,而mi项已在上一次循环中求出。 3 .比照1. 2两种思路,分析它们的执行过程。 例5T6猴子吃桃。 重点:规律常常是在列举大量数据的基础上得到的,没有什么技巧,只有“汗水”。 例577回文数猜测。 通过文字题锻炼编程能力。无限循环,用break退出。 例5-18编程验证哥德巴赫猜测。 如何强制用户输出一个不小于4的偶数。复杂程序的构造能力。 例5-19对阵名单。 能否输出所有可能的对阵名单? A——X B——Y C——Z A——X B——Z C——Y A——Y B——X C——Z 清晰的思路是编程解决问题的前提,注重每条语句的含义。 后记: 1. 计算机解决问题主要靠循环!亳不夸张地说,思考问题的解法就是考虑“如何构造循环”。循环是有条件的重曼,是“螺旋式上升”,是“波浪式前进”。 2. 循环结构的关键在于“第i次循环”有什么作用?循环是如何模拟手工过程的。 为了循环必须把手工过程“标准化”。 3. 复杂循环结构的构造。仍然为“找重复”或“穷举”,不过要有一点“自顶向下”的思路。 4. 成功="自顶向下,逐步求精”的思路+通过“调试执行”认真分析其执行过 程的耐心。 5. 规律常常是在列举大量数据的基础上得到的,没有什么技巧,只有“汗水”。 6. 程序中越来越多“逻辑错误”,建议提高调试能力。关于程序的调试可参考视频:C1O调试。 五、数组的作用及准确理解 重点: 1 .数组的作用。 (数组解决了定义多个变量的麻烦,而且数组中的多个变量依据下标构成了有序的一 组,可以用统一的方式对大批量的数据进行处理。) 2 .数组的准确理解。 (全面理解数组的条件还不成熟,现在只需正确理解何谓“数组的元素仍为数组的数组 称为多维数组”,定义一个多维数组实际上可以使用几个什么样的变量即可。) 3 .字符数组与字符串的关系。 (字符数组首先是一个普通的数组,但其中可能存储了一个字符串,从而变成了一个“字 符串”,于是就“特殊” 了。可以直接用字符串字面量初始化,直接输入输出。) 难点: 使用循环以统一的方式处理数组中的数据,实际上还是构造循环的能力。再次提醒:先 用超级计算机“我们的大脑”分析解决问题,用自然的方式写出算法,再翻译成C语言程序, 最后再调试执行比照分析,体会一个道理“C程序只是模拟了我们解决问题的方法”。除了 提醒,本章没有任何补充,因此就不详细分析相关例题了,欲了解分析过程者请看视频。 (一)一维数组 重点: 1 .定义一个一维数组实际上是定义了几个类型相同的变量。相关变量的标识名中切记下 标从零开始。 2 .定义与使用的不对称性。 (定义时不可以用变量给出数组长度,使用数组元素时可以用变量作为下标。 scanf C%d,,» &a[0]); scanf (,4%d,,» &a[l]); scanf (M%dM, &a[5]);可以改写为for(i=0; i<=5;++i) scanf (M%d,\ &a[i]);) 3 .初始化的特点。 (初值用完后如何理解给剩余的数组元素赋值为0?可省略数组长度。初值均相同时如 何初始化?为0时={0};不为0时一个个地写二{1, 1,..., 1};) 难点: 一维数组的应用。 例6-3再次说明规律是在罗列数据的基础上得到的。 例6-4上一章的思考题,没有数组,即使得到了算法,我们也“无法”写出程序。 例6-5在数组的配合下,我们可以用一种方法对多个数据排序。 例6-6一维数组也可输出成“二维数组”的样子。 (二)二维数组 重点: 1. 一维数组的元素类型仍为一维数组,此时的数组什么样子? 2 .定义了一个二维数组,如int a[3] [4];,分别定义几个什么样的变量?有几种初始 化的方式? (3个有4个元素的整型一维数组a[0],a[l],a[2]。12个整型变量。 相对应 的初始 化方式 int a[3][4] = { {1,2, 3, 4},和 ini a[3] [4] = {1,2,3,4,...};) 3 .三维数组如何理解? 难点: 二维数组的应用。 例6-7列出相关数组元素的名称,即可总结出循环规律。 例6-8找第i行最大值时不找出最大值只找出其下标j的值,即a[i] [j]就是最大值。 根据具体情况灵活地处理问题。 例6-9杨辉三角形与上一章的图形有何不同? (三)字符数组和字符串 重点: 1 .字符数组本身的特点。 2 .字符数组与字符串的关系。 3 .字符数组独有的特点。(用格式字符串为s和专用的输入输出函数输入输出数据时有 何不同?) 难点: 字符串的相关例如。 例6-12体会scanf函数的处理过程。(通过输入设备输入的数据实际上只是一串字符) 例6-13特别注意一个二维数组看成两个一维数组的用法。 (四)综合例如 重占• 1 .大数的表示。 2 .大数的输出。 3 .大数的计算过程。 体会程序是数据结构加算法的思想。 六、函数的作用及准确理解 C语言用函数组织代码。程序和函数通过将用户的输入转换成用户需要的输出实现某种 功能,本质上都是从输入到输出的映射(显然这里的映射仅指“对应关系”。百度百科:在 数学上,映射那么是个术语,指两个元素集之间元素相互“对应”的关系。数学上严格意义的 映射要求“对应的唯一性:定义域中的一个元素只能与映射值域中的一个元素对应”, 最初的函数只能通过函数的返回值输出数据,还勉强算数学上的映射。),因此,同样 的功能既可以用程序实现,又可以用函数实现,也就是说程序可以改为相应的函数,函数也 可扩展成程序(程序似乎就是一个main函数)。 函数这一章内容较多较杂,难以理解。学习函数应从以下几个方面入手。 首先,函数的作用及使用。函数用于封装代码段,函数作用表达在把输入转换成输出。 由此体会如何定义一个函数,即如何把具有一定功能的代码段封装成一个函数。使用函数时 体会实参与形参的关系,理解何谓“传值调用”。 其次,分析函数的特性一一封闭性。由“传值调用”到变量的作用域,分析函数的封闭 性及全局变量对此的影响。体会如何使用全局变量。 最后,体会递归函数。递归函数是个奇迹,那样自然那样优雅地模拟了递归算法。只有 结合递归算法才能真正理解递归函数。算法就是我们解决问题的方法,用计算机解决问题, 只有一种思路一一重兔! “螺旋式上升式”的重药!或“波浪式前进式”的重复!再具体点 就是循环和递归! 本章的重点: 1 .函数的作用。 2 .自定义函数的实现过程。 3 .函数调用的特点。 4 .理解三种函数操作:函数定义、函数声明和函数调用。 5 .变量的作用域对函数封闭性的影响。 6 .关键字static的作用。 7 . 一维数组作为函数参数时的特殊之处。 8 .递归函数的用法。 9 .常用库函数的使用。 10 .用函数组织程序。 本章的难点: 1 .理解函数的传值调用。 2 .自定义函数的实现。 3 .全局变量的正确使用。 4 .随机数函数的使用。 5 .递归函数与递归算法的关系。 6 .正确使用库函数。 7 .函数与程序的关系。 (-)函数定义 重点: 1 .函数定义分两局部,理解各局部的作用。(首部说明函数的功能:函数体完成从输 入到输出的映射。) 2 .怎样实现自定义函数。(第•步根据功能确定函数的首部;第二步完成函数体) 3 .单个函数在VC6.0中可以编译吗?(只能通过编译检查函数中的语法错误。).把例7T至7-4实现为程序,体会相同功能的程序与函数的异同。(算法相同。程 序的服务对象是用户,因此,程序中用scanf函数让用户输入数据,程序中用printf 函数输出结果给用户。函数的服务对象是其它函数,因此,函数的输入用参数,而 函数的输出用返回值。) 讨论: 1 .使用函数时一定要知道函数的函数体吗? 2 .函数有何作用?(把功能包装成函数就可以方便地重复利用这个函数,正如printf 函数和scanf函数所示。) (二)函数的调用与声明 重点: 1 .发生函数调用时,程序如何执行? 2 .函数调用的语法。(注意:“函数调用”在程序中可以看作是其“返|可值";如果 没有返回值,那么其作用仅是执行一次函数体。).通过例7-5切记函数传值调用的特点。(函数调用执行时可能发生两次类型转换。 实参向形参赋值时,如果类型不匹配那么会发生类型转换;通过return语句返回函 数值时,如果其类型与函数定义的返回值类型不一致那么会发生类型转换。) 3 .如何通过文件包含的方式使用已定义好的自定义函数? 4 .通过例7-7体会函数的作用。(重用代码提高编程效率;包装代码提高程序的可读 性。).理解函数声明的作用。通过例7-8再次体会函数的传值调用,并分析其给函数带来 的影响。(当实参为变量时,被调用函数只能使用变量的值,而不能通过形参修改 相关变量的值,也就是说,函数无法影响其它函数。问题:能在被调用函数中直接 使用其它函数中的变量吗?) (三)作用域 重点: 1 .何谓变量的作用域?它给函数带来了什么影响?(变量的作用域给函数带来了封闭 性。函数不能使用其它函数中的变量,同时其变量也不会被其它函数使用。函数的 封闭性是指相同的实参总能得到相同的返回值。).如何看待函数的封闭性?全局变量对此有何影响?(函数应该具有封闭性,只有如 此函数的使用者才能放心地使用;也只有如此,函数才能在多个地方互不影响地执 行。当函数中用到全局变量时,其作用可分为三类:仅用于输入数据、仅用于输出 数据、既用于输入数据又用于输出数据。全局变显用于输入数据时,通常会破坏函 数的封闭性。由例7-14可知实际上没有必要让其用于输入数据,因此尽量防止这 种用法。当全局变量用于输出数据时,既不会破坏函数的封闭性,又可以使函数返 |口|多个函数值,但是这种用法会降低函数的可重:用性和可读性。).通过例7-12体会文件作用域的进一步扩展并比拟其与文件包含方式的区别。 2 .全局变量作用域为何可以扩展?(全局变量与局部变量的区别在于拥有相关存储单 元的时间。用static关键字修饰的变量应该为全局变量而不应该被称为“局部变 软”。如果认为其是局部变显,那么为何其可以保持状态难以解释。如果认为其是全 局变量,那么为何其不能在其它地方使用?因为static关键字的作用就是限制文件 作用域的范围的。) 3 .在函数中如何合理地使用全局变量?如何理解sialic关键字的作用? 4 .分析例7-16中的randomize函数为何可以产生随机序列。 (四)函数嵌套调用与一维数组作为函数参数 重点: 1 .理解嵌套调用函数时程序的执行过程。 2 . 一维数组作为参数时的特别之处。(通过形参可以改变其元素的值。长度被忽略因 此可以省略不写,但通常用一个整型形参专门用于传递数组的长度。) 难点: 分析比照例7-17和例7-20,体会函数的重用。 (五)递归 再次强调:递归函数是个奇迹,优雅地模拟了递归算法。 重点: 1 .理解递归算法。 2 .理解递归函数的执行过程本质上是函数嵌套调用的执行过程。 难点: 1 .用递归算法解决实际问题。 2 .从算法的角度分析递归函数的执行过程。 注意: 程序实际上模拟了我们解决问题的步骤,递归函数也不例外。建议通过看视频来学习递 归这一节。 (六)库函数简介 熟悉常用的库函数,通过使用库函数来提高编程效率。 重点: 1 .理解getch函数、getche函数和getchar函数的区别与联系。 2 .分析在程序运行时如何得到与上次运行程序不同的随机序列。 3 .常见字符串处理函数的功能及考前须知。(相关字符数组必须能容纳新的字符串。) (七)综合实例:确定y年m月d日是星期几。 重点: 1 .体会自顶向下分析方法与函数的结合。 2 .体会使用函数组织程序的优点。(1.便于多人同时开发程序,效率高。2.程序可读 性好。3.可方便重用以函数包装的代码。)七、指针的作用及准确理解 提起指针,大家谈虎色变,之所以如此,我认为最主要的原因是概念不清。学习指针需 弄懂两个关键问题:指针是什么?指针有什么用? 一、C语言与计算机的关系(-)c语言如何驱动计算机 人们利用c语言与计算机沟通,借助编译系统,计算机能够理解并执行c语言程序。c 语言是使用计算机的接口。 使用计算机需了解计算机的三大基本原理,特别是二进制编码和五大组成局部。C语言 与计算机的五大组成局部关系如下图。 语句的执行顺序 图1-6 C语言与计算机的联系(1-6为书中编号) 在此需特别注意“变量”这一概念。C语言中用变量标识计算机中的存储单元,使用变 量就是使用计算机中的存储器。如果存储单元不能存入某类存储数据如5. 5,那么相关变量就 不能赋值为5. 5。这是变量与数学中未知数如x的本质区别。以后在学习指针变量、数组变 量时,主要通过分析它们标识存储单元的特点来探求其本质特征。 C语言用函数控制计算机的输入设备和输出设备,那么C语言中的函数与数学中的函数 有何异同?本质上没有区别!都是从输入到输出的映射。 不仅应注意函数在C语言中的表现形式,更重要的是明白函数与程序的关系。main函 数就是程序,程序的执行过程就是main函数的执行过程。没有main函数,函数再多也不能 称为程序。程序中的其它函数只有通过main函数的调用(直接或间接)才有执行的机会。 借助编译系统的调试功能,不仅可以直观地观察一个“复杂”程序的执行过程,而且应明白 一个道理,程序是一条语句一条语句执行的,并不神秘。 通过学习printf函数的简单使用,既能动手尝试编程,又能体会到编写程序时需要的 严谨,尤其是程序的输出与代码的“绝对一致”。 重点: 1 .计算机的五大组成局部与C语言的关系。 2 .变量的概念。(存储单元的标识;分类型;先定义后使用;赋值) 3 .函数在C语言中的表现形式及重要作用。(写程序就是定义main函数) 4 .程序中#include <stdio. h>的作用。 5 .函数调用及printf函数的使用。 6 .编译系统的作用及VC6.0的使用。(程序的编译及调试执行) (一)指针是什么? 变量是内存中一块存储单元的标识,C语言中通过变量使用计算机中的内存。指针变量 也不例外。定义一个指针变量就会有一块存储单元与之关联(当然指针变量也同样有生命 期)。整型变量存储整数,浮点型变量存储小数,指针变量存储什么? 指针变量存储地址,似乎地球人都知道,不过这种理解并不准确。地址是什么?地址是 计算机中以字节为单位的最小存储单元的编号。把一个整数如23存入整型变量所标识的存 储单元时,它将以二进制补码形式编码并占4个字节,必须将这4个字节作为一个整体才能 正确地访问数据,由此可见与变量相关的存储单元通常有多个字节组成并有固定的编码格 式,也就是说存储单元通常是有类型的。存储单元有多少个字节组成就有多少个相关的地址, 但存储单元以首字节的地址作为其地址。谈到地址时它必定是某类型存储单元的地址,单纯 一个地址是毫无用处的。使用一个存储单元时必须知道它的地址和类型,当然我们在程序中 可以通过变量幸福地使用某存储单元而不必考虑太多。因此,地址是有类型的,地址的类型 就是其相关存储单元的类型。综上所述,指针变量存储某类型的地址。 某种类型的指针变最只能存储相应存储单元的地址。整型指针变最只能存储整型变最的 地址,字符型指针变量只能存储字符型变量的地址。指针变量有多少种类型呢?存储单元有 多少种类指针变量就有多少种类型!存储单元的类型有整型、浮点型、字符型、长度为1 的数组、长度为2的数组、整型指针 无穷无尽,甚至还有函数类型。代码段同样在内 存中存储,也有相应的“存储单元”,也有相应的地址和类型,因此可以用与之匹配的指针 变量保存其存储单元的地址,这样的指针变量称为指向函数的指针变量。指向函数的指针变 量把代码段“存储” 了,呵呵,代码段也成了数据!指针变量确实神通广大! (二)指针有什么用? 通过指针变量可以得知某存储单元的地址和类型,我们也就能使用这个存储单元了。如 有int i,那么*pi与变量i通常可以互换使用,此时在程序中,既可以用变量i使用它所标识的存储单元,也可以用*pi使用这个存储单元。有了指针变量,我们就有了一 种新的访问存储单元的途径。指针变量的意义就在于此! 通过标识符直接访问存储单元既直观又方便,为何要再提供一种新的访问存储单元的途 径呢?新的途径通过指针变量利用间接引用操作符虽然稍嫌复杂,但是它呈现了新的特点。 指针变量的主要作用总结如下: 1 .可以突破变量作用域的限制 程序中通常把相关代码组织成函数,但函数的封闭性致使某些操作不能进行,如使用函 数交换两个实参的值。当指针变量作为参数时,实参传递的是相关存储单元的地址,于是我 们就可以利用形参直接访问相关存储单元,这样就突破了变量作用域的限制,能够在函数中 使用“外部的存储单元”。 2 .可以提高函数的执行效率 形参相关的存储单元比拟大时,如大数组,大结构体等,函数执行用实参给形参赋值时 既浪费时间又浪费空间。如果把形参的类型换成相应的普通的指针类型,因为无论何种类型 的普通指针变最均占4个字节,那么赋值时只需4个字节,且在函数中通过指针变最同样可以 使用相关数据,函数的执行效率无疑会大大提高。注意:为了防止函数中误用实参(如修改 实参的值),可以用关键字const限定。 3 .可以使用“未命名”存储单元 内存中的堆存储空间在程序运行中通过库函数调用“手动”申请,没有变量直接与之相 关,只能通过指针变量间接引用的方式使用。 4 .利用void型指针变量可以提高程序的抽象程度 如下面的一个交换函数,它借助指针可以交换两个整型或浮点型变量的值,甚至是两个数组变量所有元素的值。 void swap(void *pxz void *py, unsigned size) (char temp, *paz *pb; pa = (char *)px;pb = (char *)py; if(pa != pb) while (size--) (temp = *pa; *pa++ = *pb; *pb++ = temp; } ) 又如对“任意类型”的数组进行排序的stdlib.h中的库函数qsorto其用法参见例9-31 和例9-32。 (三)数组变量是指针吗? 数组是变量吗?定义一个数组就是定义了多个变量并以数组名加下标的方式作为变量 名,但数组名本身是变量吗? 举例讨论。int a[3] = {l,2,3};那么数组a的内存状态如图9-7所示。 : 0x0012 ffOO 1 a[0] 0x0012 ffO4 2 a[1] a : 0x0012 ff08 3 a⑵ 图9-7 一维数组a的内存状态 数组a没有专属于自己的存储单元,仅是数组元素的代表。C语言中变量用于标识一个 存储单元,数组名标识存储单元了吗? 从图9-7可知,如果把数组元素标识的存储单元算作数组a的存储单元,那么数组a标识 了存储单元,是一个变量。数组a的存储单元的长度为(4X3) 12个字节(sizeof(a)的值 为12)。数组变量a存储了什么数据?数组变量a的存储单元仅是名义上的,不能通过a 使用它们,也就是说数组变量a中什么数据也没有存储。这样一来数组变量a还能算作变量 吗? C语言规定数组变量的值为数组首元素的地址。虽然数组变量的值仅是规定并非在某存 储单元中存储,但是,按照此规定数组变量a有值(&a[0]),当把这个值看成在数组a的 名义上的存储单元中存储时,数组变量a就可以算作是一个变量了。数组变量a的状态如图 1所示。 0x0012 fKO r 0x00T2-f£00 't共有12个字节[占4个字节I► a|0| 图1数组变量a的状态 数组变量a虽然称为变量,但是它和普通变量还是有区别的。它的存储单元是名义上的, 不能通过a使用它们,如a=&a[2];等语句都是非法的(由此可见数组变量a的内容在程序 中不可能改变)。虽然数组变
展开阅读全文

开通  VIP会员、SVIP会员  优惠大
下载10份以上建议开通VIP会员
下载20份以上建议开通SVIP会员


开通VIP      成为共赢上传

当前位置:首页 > 通信科技 > 开发语言

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        抽奖活动

©2010-2026 宁波自信网络信息技术有限公司  版权所有

客服电话:0574-28810668  投诉电话:18658249818

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :微信公众号    抖音    微博    LOFTER 

客服