C语言研究性学习的路线
现行的多数C语言教材有太多的误区,不仅不能给读者提供有效的学习线索,还常常“误导”读者,于是,“死记硬背”便成了学习C语言的唯一选择。本文以拙作《新编C语言程序设计教程》(清华大学出版社出版,配套视频zeq126.56.com)为基础,探讨了C语言的研究性学习。
C语言的知识点有:
1. C语言与计算机的关系
2. 表达式的求值
3. 逻辑运算及选择结构
4. 算法及循环结构
5. 数组的作用及准确理解
6. 函数的作用及准确理解
7. 指针的作用及准确理解
8. 自定义数据类型及文件
这几部分相辅相成,构成了一个有机的整体。分析如下:
四、算法及循环结构
/*前言
这注定又是……的一章。
算法的精髓是“循环”,而构造循环的能力只能在一次次的分析、编码、调试、对比、思考中培养。除了一道道的演示,我实在想不出其它的办法可以“速成”,毕竟如表达式求值似的总结个一二三四的速成法仅适用于“知识”。关于编程,有的人似乎“天生”就会,有的人可能“上手”较慢,所幸正如武侠书中的演绎,并非“上手”越快就一定走得越远。
*/
(一)再谈算法
多次指出,编写程序的过程为:分析问题,得到解决问题的步骤,最后把步骤“翻译”成相应的语句。解决问题的步骤就是算法。问题的解法可能有多种,行之有效的方法通常与欲使用的工具相关,也就是说,必须结合工具的特点思考问题的解法。
计算机解决问题主要靠循环!运用循环的熟练程度直接反映了一个程序员的编程水平。毫不夸张地说,思考问题的解法就是考虑“如何构造循环”。
循环是有条件的重复,是“螺旋式上升”,是“波浪式前进”。
(二)while循环结构
重点:
1. while循环结构的形式。
其与if结构有何异同?(从形式、执行过程、流程图)
2. while循环结构的特点。
while循环结构的循环体执行多少次?(再次强调由循环控制表达式决定)
如何使用while循环结构输出五个*号?(由具体示例展开,总结while循环结构使用的3个特点:设置循环变量的初值、决定循环控制表达式、调整循环变量的值)
由例5-1熟悉不同while循环结构的执行情况。(循环次数固定的,输出’A’至‘Z’;循环次数不定的,(1.0/i>1.23e-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时为止,因此“新的加数为0”可以作为循环控制的条件。当然此时就可写出程序了。如果再想“什么情况下新的加数为0?”,则经过深入分析可以得到“简洁”的程序。
2. 尝试写出程序。
3. 分析执行过程,体会程序中每条语句的作用。体会如何让循环“螺旋式上升”,“波浪式前进”。(在下次循环之前先做好准备,“恢复状态”,此例为“去掉”加过的数字。)
例5-4 百僧分百馍
1. 总共有多少种可能?对于每种情况,处理方式相同吗?(本质也是重复)
2. 尝试写出并分析程序的执行情况。
3. 体会用计算机解决问题的特点。(一个一个地试。美其名曰“穷举法”)
4. 这个程序在理论上有问题。(应确保小僧的人数为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=1;i<=99;i+=2){oddsum+=i;evensum+=i+1;}。
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语句终止循环结构的一次执行。)
2.break语句的作用为终止所属结构的执行。(注意其是属于哪个循环结构,有时可能是哪个switch结构)
3.continue语句如何用选择结构替换?
难点:
例5-9判断正整数n是否为质数。
分析:如果从2至n-1均不为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输出如下图形
*
**
***
****
*****
1. 如果是通过重复输出了这个图形,那么每次完成什么工作?(输出一行!重复5次输出5行)
2. 第i次循环需要完成什么工作?(输出i个*,再输出一个’\n’)
3. 尝试编程,并详细分析程序的运行情况。体会思路。
4. 成功=“自顶向下,逐步求精”的思路+通过“调试执行”认真分析其执行过程的耐心。
例5-12输出如下图形
*
***
*****
1.第i次循环需要完成什么工作?(空格+*+’\n’。多少个空格?第1行2个,第2行1个,第3行0个,…显然第i行为3-i个。)
2.空格个数的规律是在列举大量数据的基础上得到的,没什么技巧,只有“汗水”。
例5-13输出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项,则有mi=mi-1*i,而mi-1项已在上一次循环中求出。
3. 对比1.2两种思路,分析它们的执行过程。
例5-16猴子吃桃。
重点:规律常常是在列举大量数据的基础上得到的,没有什么技巧,只有“汗水”。
例5-17回文数猜想。
通过文字题锻炼编程能力。无限循环,用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.程序中越来越多“逻辑错误”,建议提高调试能力。关于程序的调试可参考视频:C10调试。