第三章 C程序的流程设计
一、算法
?算法的性质与组成要素
?算法是进行操作的方法和步骤。
?算法的性质,
?解题算法是一有穷动作序列。
?序列中只有一个初始动作。
?序列中每一个动作仅有一个后继动作。
?序列终止,表示问题得到解答,或问题没有解答。
?算法的要素,
?操作:各种运算,I/O读写均称为操作。计算机算法是由操作
组成的。
?控制结构,
?顺序结构
?选择结构
?循环结构
?算法的描述
?自然语言
?流程图
?伪代码
?计算机语言
以求两个数的最大数为例说明几种算法。
?自然语言,
s1,输入两个数 a,b
s2:找出最大数赋给 m
s3:输出最大数 m
S2.1:如果 a大于 b,
则将 a赋给 m,否则将
b赋给 m。
输入 a,b
y a>b n
输出 a 输出 b
?N-S流程图,
?伪代码,
input a,b
if a>b then
m=a
else
m=b
end if
print m
?C代码,
main()
{ int a,b,m;
scanf(“%d %d”,&a,&b);
if (a>b)
m=a;
else
m=b;
printf(“a=%d”,a);
}
上机问题,
逻辑运算的注意事项。 E2-15
二、用 C语句描述算法
?表达式语句
?C语言是一种表达式语言,所有操作都通过表达式来实
现。
?由表达式组成的语句叫表达式语句,它由表达式后加
一分号组成。
?表达式语句的三种基本类型,
?赋值语句,x=sin(y);
?函数语句,printf(“a=%d b=%d”,a,b);
?空语句, ;
?复合表达式语句 (逗号表达式 ):几个表达式语句用
“,”分隔组合而成,如 i=1,j=2; 。逗号表达式的值
为最后一个表达式的值,如 a=(a=6,a*3,a+3) 结果 a=9。
? 复合语句 (分程序 )
? C语言允许将一组语句括在一对花括号内,称为复合语句。如,
{c=getchar( );
putchar(c);
}
? 在分程序中可定义变量,但只在分程序中有效,且上级分程序中的
变量对下级分程序有效,反之无效。如,
main( )
{ int a=2;
{int b=3;
printf(“a=%d b=%d,,a,b); /*正确,可使用上级分程序中定义的变量 a*/
}
printf(“a=%d b=%d,,a,b); /*出错,下级分程序定义的变量对上级无效 */
}
三、选择结构程序设计
?if … else 结构
例 L3-3求一个数的绝对值。
main()
{ int x,y;
scanf(“%d”,&x);
if (x>=0) y=x;
else y=-x;
printf(“|%d|=%d”,x,y);
}
例 L3-4 求三个数中的最大值。
main()
{
int a=12,b=2,c=24,max;
clrscr();
max=a;
if(b>max)max=b;
if(c>max)max=c;
printf("max=%d",max);
getch();
}
if …else 的嵌套 符号函数 sign (例 L3-4-2)
int sign(float x)
{int f;
if (x>0)
f =1;
else
{ if (x==0) f =0;
else f =-1;
}
return( f );
}
?else if结构,是 if… else嵌套的一种变形。 (例 L3-4-3)
int sign(float x)
{int f ;
if (x>0) f =1 ;
else if (x= =0) f =0 ;
else f = -1;
return( f ) ;
}
?switch结构
switch( 表达式 )
{ case 常量表达式 1:语句 1; [break ;]
case 常量表达式 2:语句 2; [break ;]
……
case 常量表达式 n:语句 n; [break ;]
default:语句 n+1;
}
例 L3-6 求分数的等级
switch(cj/10)
{case 0,
case 1,
case 2,
case 3,
case 4,
case 5,dj='c';break;
case 6,
case 7,dj='b';break;
default:dj='a';
}
例 L3-7 测试输入的是数字、空白还是其它字符。
test_char(int c)
{
switch(c)
{case '0',case '1',case '2',case '3',
case '4',case '5',case '6',case '7',
case '8',case '9':printf("It is a digit.\n");break;
case ' ',case '\n',
case '\t':printf("It is a white.\n");break;
default:printf("It is a char.\n");
}
例 L3-8 联想猜词游戏。
#include<stdio.h>
main()
{ int c;
c=getchar();getchar();
switch(c)
{ case 'a',case 'A',printf("Ada,Algol?\n"); c=getchar();getchar();
switch(c)
{ case 'c',case 'D',printf("Ada\n");break;
case 'l',case 'L',printf("Algol\n");break;
default:printf("Input error!\n");
}break;
case 'b',case 'B',printf("Basic,BCDL?\n"); c=getchar();getchar();
switch(c)
{ case 'a',case 'A',printf("Basic\n");break;
case 'c',case 'C',printf("BCDL\n");break;
default:printf("Input error!\n");
}break;
case 'c',case 'C',printf("C,Cobol?\n"); c=getchar();getchar();
switch(c)
{ case 'c',case 'C',printf("C\n");break;
case 'o',case 'O',printf("Cobol\n");break;
default:printf("Input error!\n");
}break;
default:printf("Input error!\n"); }}
四、循环程序设计
?程序设计中,人们经常将一些复杂、不易求解的
的过程转换为易于理解的多次重复操作,
?可降低问题的复杂性
?可充分发挥计算机的快速的特点
?常用的循环算法:穷举与迭代
?穷举:对问题的可能状态一一测试,直到找到解
或将所有可能状态都测试一遍。
?计数器法
?标志法
?迭代:是一个不断用新值取代变量的旧值,或由
旧值递推出变量的新值的过程。
穷举法实例
?求所有水仙花数的问题。
?水仙花数是指:一个三位数,其各位数字立方和等于
该数本身。 例如 153=13+33+53,故 153是水仙花数。
?用穷举法解此题的思路,
?从最小的三位数开始,到最大的三位为止,一个个拿出来进
行判断,看是否是水仙花数。
?如何判断一个数 i是否是水仙花数的关键:如何将一个三位数
的各位取出。
?方法一、用数学方法计算出各位的值,
?个位 a,a=i %10
?百位 c,c=i /10
?十位 b,b=(i/10)%10
?方法二、各位依次从最小值到最大值一个个试,
?个位 a,1 到 9
?百位 c,0到 9
?十位 b,0到 9
迭代法实例
?求一元高次方程的近似解问题。
?一元五次以上的方程找不到通用的根的解析表达式,只能
求近似解。
?穷举法解此题的思路:先找一个粗略解,再通过一定的方
法由粗略解得到一个更精确的解,……直到找到的解的精度
达到要求为止。
?方法一、二分迭代法,
?先取两个粗略解 x1,x2,如果 f(x1),f(x2)符号相反,则方程在 (x1,x2)
中至少有一个根。如果在该区间是单调函数,则有一个实根。
?进行二分:取 x3=(x1+x2)/2作为一个新的粗略解,则它至少比
x1,x2中的一个更接近真实的解。
?将 x3和与 x3反号的 x1或 x2作为新的一对粗略解,继续二分,直到
这一对粗略解的差小于给定的误差为止。
x1
x* x2
f(x1)
f(x3)
f(x2)
f(x4)
x4
x3
迭代法实例
?求一元高次方程的近似解问题。
?方法二、牛顿迭代法(切线法),
?设 xk是方程 f(x)=0的一个近似解,过 Pk作 f(x)的切线,有,
f ? (x)=f(xk)/(xk-xk+1) 解得,xk+1=xk-f(xk)/f ? (xk) 该解比 xk更接近于
实际解。
?再过 xk+1作 f(x)的切线,重复一述过程。
x*
xk
f(x)
pk
xk+1 xk+2
1,While 循环结构
?While 循环控制结构
while (条件表达式 )
{
循环体
}
注意:如果循环体只有一个语句,则可不要花括号。
While 循环的执行过程,
1,计算条件表达式的结果。
2,结果为非 0则执行循环体,再返回到 1。
3,结果为 0则不执行循环体,执行 while循环后面的语句。
? While 循环举例
例 L3-14 简单的打印数据程序 1
例 L3-15 简单的打印数据程序 2
例 L3-16 输入字符原样输出 1
例 L3-16-2 输入字符原样输出 2
例 L3-17 等待用户输入指定字符
例 L3-add 累加( 1+2+3+……,1+3+5+……, 2+4+6+……,
3+6+9+……)
例 L3-mul 累乘( n!) 例 L3-flow 求水仙花数
例 L3-18 搬砖问题 例 L3-19 爱因斯坦阶梯问题
例 L3-min( 2) 求最小公倍(穷举法,加倍法 )
例 L3-20 求最大公约数(欧几里德法)
例 L3-21 求平方根(牛顿迭代法)
例 max_min 求若干个数的最大、最小值。
do … while结构
?格式,
Do
{
循环体
} while(条件 );
注意,
分号不能丢!
for 结构
?格式,
for ( 初始化表达式;条件表达式;修正表达式 )
{
循环体
}
1 2
3
4
三种循环举例
例 1、求水仙花数
?L3-flow,while
?L3-flow2,do … while
?L3-flow3,for
例 2、求 1+2+3+…+n
?L3-sum,while
?L3-sum2,do … while
?L3-sum3,for
Continue 与 break在循环中的应用
?continue,直接返回到循环的开始。
?break, 中止循环。
?例,求 [1,1000]能被 7整除的数之和,当和大于 1000时
就中止。
?L3-div
goto循环
?格式,
label,
循环体
goto label;
例:求 1+2+3+……+100
L3-goto
L3-goto2
注:一般情况下尽量不用 goto循环 ——导致程序结
构的破坏。
综合举例
?例 1:打印九九表
L3-22 行列积式 L3-22-2 直角表达式
?例 2:验证素数
L3-23
?例 3:打印出 900-1000间的所有素数
L3-23-2
?例 4:打印 Fibonacci数列的前 n项
1 1 2 3 5 8 13 …… (从第三项起,每个数为前两数之
和。)
L3-24
习题
?E3-2
?E3-4
?E3-5 牛的繁殖问题
年 1代 2代 3代 4代 总数
1 1 1
2 1 1
3 1 1
4 2 2
5 3 3
6 4 4
7 5 1 6
8 6 2 1 9
9 7 3 2 1 13
?E3-6