第四章 顺序程序设计.docx
《第四章 顺序程序设计.docx》由会员分享,可在线阅读,更多相关《第四章 顺序程序设计.docx(30页珍藏版)》请在冰豆网上搜索。
第四章顺序程序设计
第四章顺序程序设计
程序设计时,通常采用三种不同的程序结构,即顺序结构、选择结构和循环结构。
其中顺序结构是最基本、最简单的程序结构。
通过本章顺序程序设计的学习,使大家可以开始最简单的C程序设计。
4、1C语句概述
C语言的语句用来向计算机系统发出操作指令。
一个语句经过编译后产生若干条机器指令。
实际程序包含若干条语句。
语句都是用来完成一定操作任务的。
声明部分的内容不应当称为语句。
函数包含声明部分和执行部分,执行部分由语句组成。
C程序结构:
一个C程序可以由若干个源程序文件组成,一个源文件可以由若干个函数和预处理命令以及全局变量声明部分组成,一个函数由数据定义部分和执行语句组成。
程序包括数据描述(由声明部分来实现)和数据操作(由语句来实现)。
数据描述主要定义数据结构(用数据类型表示)和数据初值。
数据操作的任务是对已提供的数据进行加工。
C语句可以分为以下3大类:
4、1、1控制语句-完成一定控制功能的语句(主要用于控制程序流程)。
C有9种控制语句,它们是:
4、1、2表达式语句-用表达式构成语句,表示一个运算或操作。
表达式;
表达式语句是在表达式最后加上一个“;”组成。
一个表达式语句必须在最后出现分号,分号是表达式语句不可缺少的一部分。
C程序中大多数语句是表达式语句(包括函数调用语句)。
表达式语句的一般形式:
例如:
表达式
表达式语句
说明
a=3(赋值表达式)
a=3;(赋值语句)
getch()(函数调用-表达式)
函数调用也属于表达式
getch();(函数调用语句)
getch();合法且有意义,只关心是否有击键,不关心具体的值
i++(自增表达式)
i++;(一般表达式语句)
ch=getch()(函数调用表达式,赋值表达式)
ch=getch();
(一般表达式语句)
x+y(算术表达式)
x+y;(一般表达式语句)
x+y;是一个语句,其作用是完成x+y操作,是合法的,但是并不将结果赋给另外的变量,所以并无实际意义
表达式语句常见的形式可以有:
赋值语句、函数调用语句、空语句。
1、赋值语句:
由赋值表达式加上一个分号构成赋值语句。
C语言的赋值语句先计算赋值运算符右边的子表达式的值,然后将此值赋值给赋值运算符左边的变量。
C语言的赋值语句具有其它高级语言的赋值语句的一切特点和功能。
2、函数调用语句:
由函数调用表达式加一个分号构成函数调用语句。
例如:
printf(“ThisisaCstatement.”);
3、空语句:
只有一个分号的语句,它什么也不做(表示这里可以有一个语句,但是目前不需要做任何工作)。
例如:
(1)空循环100次,可能表示一个延时,也可能表示目前还不必在循环体中做什么事情。
for(i=0;i<100;i++);/*循环结构要求循环体,但目前什么工作都不要做。
;表示循环体*/
(2)如果条件满足什么都不做,否则完成某些工作。
(;表示if块,什么都不做)
if()
;
else
{
......
}
4、1、3复合语句
用{}把一些语句(语句序列,表示一系列工作)括起来成为复合语句,又称语句块、分程序。
一般情况凡是允许出现语句的地方都允许使用复合语句。
在程序结构上复合语句被看作一个整体的语句,但是内部可能完成了一系列工作。
注意:
C语言允许一行写几个语句,也允许一个语句拆开写在几行上,书写格式无固定要求。
一般将彼此关联的、或表示一个整体的一组较短的语句写在一行上。
比如第1A章各个算法的赋初值语句可以写在一行上(避免罗嗦,看上去也清晰)。
4、2输入/输出及其C语言的实现(补充)
1、计算机由主机(CPU、内存),外围设备(输入/输出设备),接口组成。
2、输入/输出:
从计算机向外部设备(如显示器、打印机、磁盘等)输出数据称为“输出”,从外部设备(如键盘、鼠标、扫描仪、光盘、磁盘)向计算机输入数据称为“输入”。
输入/输出是以计算机主机为主体而言的。
3、C语言本身不提供输入/输出语句,输入/输出操作由函数实现。
在C标准函数库中提供了一些输入/输出函数,如printf函数,scanf函数。
不要将两者看作是输入/输出语句。
实际上完全可以不用这两个函数,而另外编制输入/输出函数。
C编译系统与C函数库是分别设计的,因此不同的计算机系统所提供函数的数量、名字、功能不完全相同。
但是,有些通用的函数各种计算机系统都提供,成为各种计算机系统的标准函数。
C函数库中有一批“标准输入/输出函数”,它是以标准的输入/输出设备(一般为终端)为输入/输出对象的。
其中有:
putchar(输出字符),getchar(输入字符),printf(格式化输出),scanf(格式化输入),puts(输出字符串),gets(输入字符串)。
4、在使用C库函数时,要用预编译命令“#include”将有关的“头文件”包含到用户源文件中。
头文件包含库中函数说明,定义的常量等。
每个库一般都有相应的头文件。
比如printf等函数属于标准输入/输出库,对应的头文件是stdio.h。
也就是说如果要使用printf等函数,应当在程序的开头#include。
又如fabs函数属于数学库,对应的头文件是math.h,如果要使用fabs函数计算绝对值,那么应当在程序的开头#include。
注意:
1、函数说明检查函数调用,进行数据类型转换,并产生正确的调用格式。
许多编译系统强制要求函数说明(函数原型声明),否则编译不成功。
2、TurboC中可以用^F1查看一个函数的说明(包含属于哪个头文件)。
4、3格式输入/输出
4、3、1printf函数(格式输出函数)
功能:
按照用户指定的格式,向系统隐含的输出设备(终端)输出若干个任意类型的数据。
printf(格式控制字符串,输出表列)
1、printf函数的一般格式:
例如:
函数参数包括两部分:
(1)“格式控制”字符串是用双引号括起来的字符串,也称“转换控制字符串”,它指定输出数据项的类型和格式。
它包括两种信息:
●格式说明项:
由“%”和格式字符组成,如%d,%f等。
格式说明总是由“%”字符开始,到格式字符终止。
它的作用是将输出的数据项转换为指定的格式输出。
输出表列中的每个数据项对应一个格式说明项。
●普通字符:
即需要原样输出的字符。
例子中的逗号和换行符。
(2)“输出列表”是需要输出的一些数据项,可以是表达式。
例如:
假如a=3,b=4,那么printf(“a=%db=%d”,a,b);输出a=3b=4。
其中两个“%d”是格式说明,表示输出两个整数,分别对应变量a,b,“a=”,“b=”是普通字符,原样输出。
由于printf是函数,因此“格式控制”字符串和“输出表列”实际上都是函数的参数。
printf函数的一般形式可以表示为:
printf(参数1、参数2、参数3、…参数n)
printf函数的功能是将参数2-参数n按照参数1给定的格式输出。
2、格式字符(构成格式说明项)
对于不同类型的数据项应当使用不同的格式字符构成的格式说明项。
常用的有以下几种格式字符:
(按不同类型数据,列出各种格式字符的常用用法)
(1)d格式符。
用来输出十进制整数。
有以下几种用法:
●%d,按照数据的实际长度输出
●%md,m指定输出字段的宽度(整数)。
如果数据的位数小于m,则左端补以空格(右对齐),若大于m,则按照实际位数输出。
●%-md,m指定输出字段的宽度(整数)。
如果数据的位数小于m,则右端补以空格(左对齐),若大于m,则按照实际位数输出。
●%ld,输出长整型数据,也可以指定宽度%mld。
(2)O格式符。
以八进制形式输出整数。
注意是将内存单元中的各位的值按八进制形式输出,输出的数据不带符号,即将符号位也一起作为八进制的一部分输出。
inta=-1;
printf(“%d,%o,%x”,a,a,a);
-1的原码:
1000,0000,0000,0001。
-1在内存中的补码表示为:
1111,1111,1111,1111=1,111,111,111,111,111=1,7,7,7,7,7=ffff
输出:
-1,177777,ffff
-1是十进制,177777是八进制,ffff是十六进制。
(3)x格式符。
以十六进制形式输出整数。
与o格式一样,不出现负号。
(4)u格式符。
用来输出unsigned无符号型数据,即无符号数,以十进制形式输出。
一个有符号整数可以用%u形式输出,反之,一个unsigned型数据也可以用%d格式输出。
(5)c格式符。
用来输出一个字符。
一个整数只要它的值在0-255范围内,也可以用字符形式输出。
反之,一个字符数据也可以用整数形式输出。
main()
{
charc=’a’;
inti=97;
printf(“%c,%d\n”,c,c);
printf(“%c,%d\n”,i,i);
}
运行结果:
a,97
a,97
也可以指定字段宽度。
%mc,m-整数
(6)s格式符。
用来输出一个字符串。
有几种用法:
●%s,输出字符串
●%ms,输出的字符串占m列,如果字符串长度大于m,则字符串全部输出;若字符串长度小于m,则左补空格(右对齐)。
●%-ms,输出的字符串占m列,如果字符串长度大于m,则字符串全部输出;若字符串长度小于m,则右补空格(左对齐)。
●%m.ns,输出占m列,但只取字符串左端n个字符,左补空白(右对齐)。
●%-m.ns,输出占m列,但只取字符串左端n个字符,右补空白(左对齐)。
(7)f格式符。
用来输出实数(包括单、双精度,单双精度格式符相同),以小数形式输出。
有以下几种用法:
●%f,不指定宽度,使整数部分全部输出,并输出6位小数。
注意,并非全部数字都是有效数字,单精度实数的有效位数一般为7位(双精度16位)。
●%m.nf,指定数据占m列,其中有n位小数。
如果数值长度小于m,左端补空格(右对齐)。
●%-m.nf,指定数据占m列,其中有n位小数。
如果数值长度小于m,右端补空格(左对齐)。
(8)e格式符,以指数形式输出实数。
可用以下形式:
●%e,不指定输出数据所占的宽度和小数位数,由系统自动指定,如6位小数,指数占5位-e占1位,指数符号占1位,指数占3位。
数值按照规格化指数形式输出(小数点前必须有而且只有1位非0数字)。
例如:
1.234567e+002。
(双精度)
●%m.ne和%-m.ne,m总的宽度,n小数位数。
(9)g格式符,用来输出实数,它根据数值的大小,自动选f格式或e格式(选择输出时占宽度较小的一种),且不输出无意义的0(小数末尾0)。
#include
main()
{
floatf=123.0;
printf("%f,%e,%g\n",f,f,f);
}
123.000000,1.23000e+02,123
以上介绍的9种格式符,归纳如下表:
教材p32-p34的4、2、4节是将格式说明项分为几个部分依次说明各个部分的作用,并对每个部分进行说明,课后请对照笔记仔细阅读,总结一般规律,切忌死记硬背。
TurboC中printf函数格式字符串的一般形式:
%±m.nh/l格式字符
[开始符][标志字符][宽度指示符][精度指示符][长度修正符][格式转换符]
3、使用printf函数的几点说明:
(1)除了X,E,G外,其它格式字符必须用小写字母。
如%d不能写成%D。
(2)可以在“格式控制”字符串中包含转义字符。
如“…\n…”
(3)格式符以%开头,以上述9个格式字符结束。
中间可以插入附加格式字符。
(4)如果想输出字符%,则应当在“格式控制”字符串中用两个%表示。
scanf(格式控制字符串,地址列表)
4、3、2scanf函数(格式输入函数)
1、scanf函数的一般格式:
其中:
(1)格式控制字符串的含义与printf类似,它指定输入数据项的类型和格式。
(2)地址列表是由若干个地址组成的列表,可以是变量的地址(&变量名)或字符串的首地址。
例如,用scanf函数输入数据。
main()
{
inta,b,c;
scanf(“%d%d%d”,&a,&b,&c);
printf(“%d,%d,%d\n”,a,b,c);
}
●&是地址运算符,&a指变量a的地址。
scanf的作用是将键盘输入的数据保存到&a,&b,&c为地址的存储单元中,即变量a,b,c中。
●%d%d%d表示要求输入3个十进制整数。
输入数据时,在两个数据之间以一个或多个空格分隔,也可以用回车键,跳格键(tab)分隔。
这种格式不能用逗号分隔数据。
例如,合法的输入:
●345
●3
45
●3(按tab键)4
5
非法的输入:
3,4,5
2、格式说明
与printf函数中的格式说明相似,以%开始,以一个格式字符结束,中间可以插入附加字符。
说明:
(1)对unsigned型变量所需的数据,可以用%u,%d或%o,%x格式输入。
(2)可以指定输入数据所占列数,系统自动按它截取所需数据。
如:
inti1,i2;
charc;
scanf(“%3d%3c%3d”,&i1,&c,&i2);
输入:
123---456后,i1=123,i2=456,c=’-’
(3)如果%后有“*”附加格式说明符,表示跳过它指定的列数,这些列不赋值给任何变量。
如:
scanf(“%3d%*3c%2d”,&i1,&i2);
输入:
123456789后,i1=123,i2=78,(456被跳过)
在利用现有的一批数据,有时不需要其中某些数据,可以用此方法“跳过”它们。
(4)输入数据时可以指定数据字段的宽度,不能规定数据的精度。
例如,scanf(“%7.2f”,&a);是不合法的。
不能指望使用这种形式通过输入1234567获得a=12345.67。
3、使用scanf函数应当注意的问题
(1)scanf函数中“格式控制”后面应当是变量地址,而不应是变量名。
例如:
scanf(“%d,%d”,a,b);不合法。
(原因:
C是传值调用,不能由形参返回值)
(2)如果在“格式控制”字符串中除了格式说明以外还有其它字符,则在输入数据时在对应位置应当输入与这些字符相同的字符。
建议不要使用其它的字符。
例1:
scanf(“%d,%d,%d”,&a,&b,&c);应当输入3,4,5;不能输入345。
例2:
scanf(“%d:
%d:
%d”,&h,&m,&s);应当输入12:
23:
36
例3:
scanf(“a=%d,b=%d,c=%d”,&a,&b,&c);应当输入a=12,b=24,c=36(太罗嗦)
(3)在用“%c”格式输入字符时,空格字符和转义字符都作为有效字符输入。
%c只要求读入一个字符,后面不需要用空格作为两个字符的间隔。
对于scanf(“%c%c%c”,&c1,&c2,&c3);
输入:
abc后,c1=’a’,c2=’’,c3=’b’
(4)在输入数据时,遇到下面情况认为该数据结束:
●遇到空格,或按“回车”或“跳格”(tab)键。
inta,b,c;
scanf(“%d%d%d”,&a,&b,&c);
输入:
1234(tab)567后,a=12,b=34,c=567
●按指定的宽度结束
●遇到非法的输入
floata,c;charb;
scanf(“%d%c%f”,&a,&b,&c);
输入:
1234a123o.26后,a=1234.0,b=’a’,c=123.0(而不是希望的1230.26)
C语言的格式输入输出的规定比较繁琐,重点掌握最常用的一些规则和规律即可,其它部分可在需要时随时查阅。
4、4其它输入/输出函数(#include)
4、4、1putchar函数(字符输出函数)
一般形式:
putchar(字符表达式);
功能:
向终端(显示器)输出一个字符(可以是可显示的字符,也可以是控制字符或其它转义字符)。
例如:
putchar(‘y’);putchar(‘\n’);putchar(‘\101’);putchar(‘\’’);
4、4、2getchar函数(字符输入函数)
一般形式:
c=getchar();
功能:
从终端(键盘)输入一个字符,以回车键确认。
函数的返回值就是输入的字符。
#include
main()
{
charc;
c=getchar();
putchar(c);
}
#include
main()
{
putchar(getchar());
}
4、4、3puts函数(字符串、字符数组中字符串输出函数)
一般形式:
puts(char*str);
功能:
将字符串或字符数组中存放的字符串输出到显示器上。
例如:
putstr(“China\nBeijing\n”);
4、4、4gets函数(字符串输入函数)
一般形式:
gets(char*str);
功能:
接收从键盘输入的一个字符串,存放在字符数组中。
例如:
chars[81];
gets(s);
4、5算法与程序设计
(本节请参考潭浩强《C程序设计》二版,第2章算法,受时间限制本节只能做简单介绍)
4、5、1算法及其表示方法
1、算法:
为解决一个问题而采取的方法和步骤称为“算法”。
对于同一个问题可以有不同的解题方法和步骤,也就是有不同的算法。
算法有优劣,一般而言,应当选择简单的、运算步骤少的,既运算快、内存开销小的算法(算法的时空效率)。
2、算法的5大特性
(1)有穷性:
一个算法应当包含有限的步骤,而不能是无限的步骤;同时一个算法应当在执行一定数量的步骤后,算法结束,不能死循环。
事实上“有穷性”往往指“在合理的范围之内”的有限步骤。
如果让计算机执行一个历时1000年才结束的算法,算法尽管有穷,但超过了合理的限度,人们也不认为此算法是有用的。
(2)确定性
算法中的每一个步骤都应当是确定的,而不是含糊的、摸棱两可的。
也就是说不应当产生歧义。
特别是算法用自然语言描述时应当注意这点。
例如:
“将成绩优秀的同学名单打印输出”就是有歧义的。
“成绩优秀”是要求每门课程都90分以上,还是平均成绩在90分以上?
不明确,有歧义,不适合描述算法步骤。
(3)有0个或多个输入(即:
可以没有输入,也可以有输入)
所谓输入是指算法执行时从外界获取必要信息。
(外界是相对算法本身的,输入可以是人工键盘输入的数据,也可以是程序其它部分传递给算法的数据)
例如:
例如:
不需要输入任何信息,就可以计算出5!
;(0个输入)
例如:
输入一个正整数n,然后判断n是否为素数;(1个输入)
例如:
如果要计算两个整数的最大公约数,则需要输入2个整数m,n。
(2个输入)
(4)有1个或多个输出(即算法必须得到结果)
算法的输出:
算法得到的结果。
算法必须有结果,没有结果的算法没有意义。
(结果可以是显示在屏幕上的,也可以是将结果数据传递给程序的其它部分)
(5)有效性
算法的每个步骤都应当能有效执行,并能得到确定的结果。
例如:
b=0,则执行a/b是不能有效执行的。
3、算法的表示方法
为了表示一个算法,可以用不同的方法。
常用的算法表示方法:
自然语言,传统流程图,结构化流程图(N-S流程图),伪代码、计算机语言等。
(重点:
传统流程图,N-S流程图)
(1)用自然语言表示算法
算法可以用自然语言描述的。
自然语言就是人们日常使用的语言,可以是汉语、英语或其它语言。
用自然语言表示通俗易懂,但文字冗长,容易出现歧义。
自然语言表示的含义往往不太严格,要根据上下文才能准确判断其含义。
此外,用自然语言描述分支和循环的算法,不是很直观。
因此,除了简单问题,一般不采用自然语言描述算法。
(2)用流程图表示算法
流程图表示算法:
用一些图框表示各种操作,用箭头表示算法流程。
用图形表示算法直观形象,易于理解。
美国标准化协会ANSI规定了一些常用的流程图符号,已为世界各国程序工作者普遍采用。
●起止框:
表示算法的开始和结束。
一般内部只写“开始”或“结束”。
●处理框:
表示算法的某个处理步骤,一般内部常常填写赋值操作。
●输入输出框:
表示算法请求输入输入需要的数据或算法将某些结果输出。
一般内部常常填写“输入…”,“打印/显示…”
●菱形框(判断框):
作用主要是对一个给定条件进行判断,根据给定的条件是否成立来决定如何执行其后的操作。
它有一个入口,两个出口。
●连接点:
用于将画在不同地方的流程线连接起来。
同一个编号的点是相互连接在一起的,实际上同一编号的点是同一个点,只是画不下才分开画。
使用连接点,还可以避免流程线的交叉或过长,使流程图更加清晰。
●注释框:
注释框不是流程图中必须的部分,不反映流程和操作,它只是对流程图中某些框的操作做必要的补充说明,以帮助阅读流程图的人更好地理解流程图的作用。
流程图是表示算法的较好的工具。
流程图包括以下几个部分:
表示相应操作的框,带箭头的流程线,框内、框外必要的文字说明。
注意:
流程线一定不要忘记箭头,因为它反应流程执行的先后次序。
传统流程图采用流程线指出各框的执行顺序,对流程线的使用没有严格限制。
因此,使用者可以不受限制地使流程转来转去,使流程图变得毫无规律。
人们对这种流程图进行改进,规定几种基本的结构,然后由这些基本结构按一定规律组成算法结构,整个算法结构是由上而下地将各个基本结构顺序排列起来。
这样可以在一定程度上,提高算法的质量。
三种基本结构,有以下共同点:
●只有一个入口:
不得从结构外随意转入结构中某点。
●只有一个出口:
不得从结构内某个位置随意转出(跳出)。
●结构中的每一部分都有机会被执行到。
(没有“死语句”)
●结构内不存在“死循环”(无终止的循环)
已经证明:
由三种基本结构顺序组成的算法结构,可以解决任何复杂问题。
由基本结构组成的算法属于“结构化”算法。
用流程图表示的算法直观形象,比较清楚地显示出各个框之间的逻辑关系,因此得到广泛使用。
每一个程序编制人员都应当熟练掌握流程图,会看会画。
(软件专业水平、资格考试也用这种流程图表示)。
绘制流程图可以使用Visio3,4…等流程图设计工具。
(3)用N-S流程图表示算法(盒图)
既然基本结构的顺序组合可以表示任何复杂的算法结构,那么,基本结构之间的流程线就属于多余的了。
美国学者I.Nassi,B.Shneiderman提出了一种新的流程图N-S流程图。
这种流程图中,完全去掉了带箭头的流程线。
每种结构用一个矩形框表示。
N-S流程图的流程图符号:
●顺序结构:
先执行A操作,再执行B操作。
●选择结构:
当p条件成立,执行A操作,当p条件不成立,执行B操作。
A,B操作允许空操作,即什么都不做。
注意选择结构是一个整体,代表一个基本结构。
●循环结构:
a)当型循环:
当条件p成立时,反复执行A操作,直到p条件不成立为止。
当型循环先判断,再决定是否执行循环体,所以在条件p一次都不满足时,循环体A可能一次都不执行。
b)直到型循环:
当条件p不成立时,反复执行A操作,直到p条件成立为止。
直到型循环先执行循环体A,然后再判断