目录
开始学习程序控制结构和语句之前,先来简单的讲述一下程序流程概述。无论我们干什么事,无论在生活、休闲还是工作中,都有一个“先做什么、接着做什么、最后做什么”的先后顺序,这就是生活中的流程。如厨师烧制美味的菜肴,先要购买所需的材料然后便会按照烧制的顺序,什么时候放油,什么时候放肉类,什么时候放蔬菜,什么时候放调料火调至多大,都是有讲究的,按菜谱的顺序和要求来做,便会制作出美味可口的菜肴。
那么在编程世界中,程序就相当于“ 菜谱 ”,是计算机动作执行的过程,而程序的流程便是“ 菜谱 ”中规定的执行顺序,即先做什么,后做什么。
程序的流程有顺序结构、选择结构和循环结构等3 种。
比如生产线上的零件的流动过程,应该顺序地从一个工序流向下一个工序,这就是顺序结构。但当检测不合格时,就需要从这道工序中退出,或继续在这道工序中再加工,直到检测通过为止,这就是选择结构和循环结构。
1、语句
和其他的高级语言一样,C 语言的语句用来对数据进行加工处理,完成一定的任务。一个程序或函数包含有若干条语句。利用语句不仅可以表达编程人员所要达到的目标,也规定了达到此目标所要经历的步骤一这就是程序的执行流向。
C语言属于第三代语言,是过程性语言,具有结构化程序设计的方法。从程序执行流向的角度上讲,程序可以分为顺序、选择和循环等 3 种基本结构,而且任何复杂的问题都可以由这3种基本结构任意结合而完成。但是这每个结构当中又包含有若干条语句,C 语句可以分为以下4类:表达式语句、控制语句、空语句和复合语句。注意:C语句都是用来完成一定操作任务的。声明部分的内容不应称为语句。如int a;不是一个C语句,它不产生机器操作,而只是对变量的定义。一个函数包含声明部分和执行部分,执行部分即由语句组成。
1.1基本赋值语句
在前面的博客里,已经学习了赋值运算符和表达式,这对赋值语句的理解将会更容易一些。赋值语句就是在赋值表达式的后面加上分号,是C语言中最典型的一种语句,也是程序设计中使用频率最高、最基本的语句,一般的形式:
变量=表达式;
功能:首先计算“ = ”右边表达式的值,将值类型转换成“ = ”左边变量的数据类型后,赋给该变量(即把表达式的值存入该变量存储单元)。
说明:赋值语句中,“ = ”左边是以变量名标识符的内存中存储单元 。在程序中定义变量,编译程序将为该变量分配存储单元,以变量名代表该存储单元。所以出现在“ = ”左边的通常是变量。
1.2表达式语句
由一个表达式加一个分号构成一个表达式语句,这是 C 语言中最简单的语句,其一般形式
为:
表达式;
注 意:从语法上讲,任何表达式的后面加上分号都可以构成一条语句,例如:a*b;这也是一条语句,实现a、b相乘,但相乘的结果没有赋给任何变量,也没有影响到a、b本身的值,所以,这条语句并没有实际意义。
1.3基本输入/输出语句
1.3.1基本输出语句
printf()本身是C语言的输出函数,功能是按指定的输出格式把相应的参数值在标准输出设备(通常是终端)上显示出来。其一般使用格式是:
printf(格式控制串,参数1,参数2......);
//例如:
printf("a,b的值分别是:%d,%d",a,b);//这里假设a和b都是整型变量
格式控制串是由双引号引起来的字符串,如“ ab的值分别为:%d,%d ”。如上例的 “ %d ” 称为转换说明,是由“ % ”和类型描述字符构成,它的作用就是将指定的数据按该格式输出。在格式控制串与参数之间用逗号作为分隔符。参数就是所要输出的数据。每一个转换说明就对应一个参数,如第1个“ %d ”对应参数a,第2个“ %d ”对应参数 b。下表列出常用的转换说明及作用:
转换说明 | 输出形式 | 举例 | 输出 |
%d | 十进制的int型 | printf("count is %d",12); | 12 |
%f | 十进制的float型 | printf("the pi is %f",3.14); | the pi is 3.14 |
%c | 单个字符 | printf("**%c**",a='A'); | **A** |
%s | 字符串 | printf("%s","hello world!"); | hello world! |
%o | 无符号八进制数 | printf("Oce=%d",a=034); | Oce=34 |
%x | 无符号十六进制数 | printf("Hex=%x",a=0xFF4e); | Hex=FF4e |
%% | %本身 | printf("a%%b==3"); | a%b==3 |
1.3.2 基本输入语句
基本输入语句的功能是接收用户从键盘上输入的数据,并按照格式控制符的要求进行类型转换,然后送到由对应参数所指定的变量单元中去。其一般格式为:
scanf(格式控制串,参数1,参数2......);
//例如:
scanf("%d%f",&a,&b);
与printf()类似,格式控制串是用双引号引起来的字符串,如“ %d ”和“ %f ”,转换说明同上,其作用是将用户输入的数据转换成指定的输入格式。参数地址是指明输入数据所要放置的地址,因此参数地址部分必须为变量,且变量名之前要加上“ & ”运算符,表示取变量的地址,如“ &a,&b ”。而且,一个转换说明对应一个参数,如“ %d ”对应参数“ &a ”,“ %f ”对应参数“ &b ”。
转换说明 | 输出形式 | 举例 | 输入 |
%d | 匹配带符号的十进制的int型 | scanf("%d",&a); | 输入20,则a为20 |
%f | 匹配带符号的十进制的浮点数 | scanf("%f",&a); | 输入2.0,则a为2.000000 |
%c | 匹配单个字符 | scanf("%c",&a); | 输入a,则a为'a' |
%s | 匹配非空白的字符序列 | scanf("%s",&s); | 输入hello,则数组s中放置hello,末尾自动加上空字符 |
%o | 匹配带符号的八进制数 | scanf("%o",&a); | 输入754,则a为八进制754 |
%x | 匹配带符号的十六进制数 | scanf("%x",&a); | 输入123,则a为十六进制123 |
1.4控制语句
控制语句用于完成一定的控制功能,由特定的语句定义符组成。C语言中有9种控制语句,分别是:if-else语句、for语句、while语句、do-while语句、break语句、switch语句、goto语句、continue语句和return语句。
1.5空语句和复合语句
空语句只由一个分号构成。即:
;
它表示什么都不做,有时用来做被转向点,或者循坏体提供空体(循坏什么也不做)。例如:
while(getchar()!='\n');
或者写成:
while(getchar()!='\n')
;
复合语句就是用{ }把多个单一的语句括起来。
复合语句的一般形式为:
{
a=x+y;
v=a/100;
printf("%f",v);
}
注 意:①复合语句中最后一条语句的分号不能忽略不写。而且复合语句的 “ { } ” 之后不能有 “ ;” 。“ { } ”必须成对使用。②复合语句当中可以是表达式语句、复合语句、空语句等。
2、顺序结构与语句
顺序结构是程序设计中最常用、最简单的基本结构。在顺序结构中,程序是按照语句的书写顺序依次执行,语句在前的先执行,语句在后的后执行。顺序结构虽然只能满足设计简单程序的要求,但它是任何一个程序的主体结构,即从整体上看,都是从上向下依次执行的。但在顺序结构中又包含了选择结构或循环结构,而在选择和循环结构中往往也以顺序结构作为其子结构。
顺序流程图如下:
其含义为:先执行语句1,再执行语句2。执行顺序与书写的顺序一致。
3、选择结构和语句
选择结构通过给定的条件进行判断,来确定执行哪些语句。
3.1选择结构
C语言中的选择结构也称为分支结构,选择结构可以用分支语句来实现。分支语句包括 if 语句和 switch 语句。if 语句提供一种二路选择,它是根据表达式的值来决定执行给出的两个程序段之一;switch 是一种专门进行多路选择问题的语句。
3.2单分支选择结构-----if 语句
if 语句的最简单的形式,即单分支结构,其一般语法为:
if(表达式)
{
语句;
}
其执行过程为:先计算表达式的值,如果表达式为非 0(即为真),则执行语句;否则不执行语句。
其中,表达式必须是关系表达式或逻辑表达式,语句可以为简单语句或复合语句,后面的内容凡提到 “ 语句 ” 的部分都是指简单语句或复合语句。
用流程图表示如下。
例如:
if(x>y)
{
printf("%d",x);
}
//其含义为:如果 x 大于 y ,打印出 x 的值,否则什么都不做。
注意:初学者容易在语句 ( if ) 后面误加分号,例如:if (x>y); x+=y;这样相当于满足条件执行空语句,后面的x+=y语句将被无条件执行。一般情况下 if 条件后面不需要加分号。
下面我们来看一个例题吧:输入3个不同的数,按从大到小的顺序输出。代码如下:
#include<stdio.h>
int main()
{
int a = 0;
int b = 0;
int c = 0;
int temp = 0; /*定义四个变量,temp作为中间变量,方便两个数进行交换*/
printf("请输入a,b,c三个数:> ");
scanf("%d %d %d", &a, &b, &c);
if (a < b) /*如果a小于b,a和b进行交换*/
{
temp = b;
b = a;
a = temp;
}
if (a < c) /*如果a小于c,a和c进行交换*/
{
temp = c;
c = a;
a = temp;
}
/*通过两个if的判断,那么这个时候a的值是最大的,接下来就是比较b和c的值*/
if (b < c) /*如果b小于c,b和c进行交换*/
{
temp = c;
c = b;
b = temp;
}
/*打印出已经排序好的三个数*/
printf("三个数从大到小为: %d > %d > %d", a, b, c);
return 0;
}
实现两个变量的交换,通常都要引用第三个变量,进行三次赋值操作。
注意:在 if 语句中,可以包含多个操作语句(如上面例子),此时必须用 “ { } ” 将几条语句括起来作为一个复合语句。
3.3双分支选择结构-----if-else 语句
if 语句的标准形式为:if-else,当给定的条件满足时,执行一个语句;当条件不满足时执行另一个语句。其一般语法格式为:
if(表达式)
{
语句1;
}
else
{
语句2;
}
其执行过程为:先计算表达式的值,如果表达式的值为非0(即为真),则执行语句 1,否则执行语句 2。总之,该格式中的 “ 语句 1 ” 和 “ 语句 2” 总会有一个得到执行。
if-else语句流程图。
例如:
if(value>0)
{
printf("value is positive.\n");
}
else
{
printf("value is not positive.\n");
}
/*其含义为:如果value大于0,打印出“ value is positive.”,否则打印“ value is not positive.”*/
注意:else部分不能独立存在,即else 的前面一定有一个“ ;”,它一定是 if 语句的一部分。
3.4多分支选择结构-----if-else的嵌套形式
前两种形式的 if 语句一般都用于两个分支的情况。在 if 语句中,又可以包含一个或多个 if 语句,这种形式称做 if 语句的嵌套。if 语句嵌套的目的是解决多路选择问题。
嵌套有以下两种形式:
(1)嵌套在 else 分支中,形成 if......else......if 语句
其形式表示为:
if(表达式1)
{
语句1;
}
else if(表达式2)
{
语句2;
}
else if(表达式3)
{
语句3;
}
......
else
{
语句n;
}
该结构的流程图如下:
接下来,我们看一下相关的例题:评价学生的成绩。按分数score输出对应的等级:score≥90为优,80≤score<90为良,70≤score<80为中等,60≤score<70为良,score<60为不及格。程序如下:
#include<stdio.h>
int main()
{
int score = 0;
printf("请输入该学生的成绩:> ");
scanf("%d", &score); /*由用户输入成绩*/
/*对用户输入的成绩进行判断,之后打印出对应的等级*/
if (score >= 90)
{
printf("优\n");
}
else if (score >= 80)
{
printf("良\n");
}
else if (score >= 70)
{
printf("中\n");
}
else
{
printf("不及格\n");
}
return 0;
}
注 意:一般使用嵌套结构的 if 语句时,须注意要合理地安排给定的条件,即符合给定问题在逻辑功能上的要求,又要增加可读性。
(2)嵌套在 if 分支中
其形式为:
if(表达式1)
{
if(表达式2)
{
语句1;
}
else
{
语句2;
}
}
else
{
语句3;
}
结构流程图如下。
例题:判断某个学生的成绩score是否合格,如果合格是否达到优秀(score≥90)。
#include<stdio.h>
int main()
{
int score = 0;
printf("请输入该学生的成绩:> ");
scanf("%d", &score); /*由用户输入成绩*/
/*对输入的成绩进行判断*/
if (score >= 60)
{
if (score >= 90)
{
printf("优\n");
}
else
{
printf("合格\n");
}
}
else
{
printf("不及格\n");
}
return 0;
}
这里我们要注意的一点是,C语言规定了 if 和 else 的“ 就近配对 ”原则,即 else 总是与前面最近的(未曾配对的)if配对。
比如:
if(score>60)
if(score>90)
printf("优\n");
else
printf("不及格\n");
此时,从书写形式上看,“ else printf("n 不及格");” 似乎与 if (score>60) 是匹配的,它们在上下是对齐的,但是 C 语言是一种无格式语言,可以不分行、不分结构,只要语法关系对就能通过编译。所以说,C 不会按所写的格式来分析语法。那么上面的代码实际等价于:
if(score>60)
{
if(score>90)
printf("优\n");
else
printf("不及格\n");
}
也就是 else 与第2个 if 构成了 if-else 语句,但从逻辑上来看,与我们的目的是矛盾的。为了保证 else 与第1个if配对,必须用圆括号将第2个 if 语句括起来作为第1个if语句的分支。即:
if(score>60)
{
if(score>=90)
printf("优\n");
}
else
printf("不及格\n");
注意:If 语句的嵌套结构可以是 if......else 形式和 if 形式的任意组合,被套的 if 语句仍然可以是 if 语句的嵌套结构,但在实际使用中,是根据实际问题来决定的如果需要改变配对关系,可以加个“ { } ”。为了便于书写和阅读,可采用左对齐形式,即:相匹配的 “ if ” 和 “ else ” 左对齐上下都在同一列上,这样显得层次清晰。
3.5多分支选择结构-----switch语句
上面讲的 if 语句的嵌套结构可以实现多分支,但实现起来,if 的嵌套层数过多,程序冗长且较难懂,并使得程序的逻辑关系变得不清晰。那么采用 switch 语句实现分支结构则比较清晰而且更容易阅读及编写。
switch语句的一般语法格式为:
switch(表达式)
{
case 常量表达式1: 语句1; [break;]
case 常量表达式2: 语句2; [break;]
......
case 常量表达式n: 语句n; [break;]
[default: 语句 n+1;break;]
}
其中:[ ]括起来的部分是可选的,可根据程序本身的需求选择。
执行过程为:先计算表达式的值,并逐个与 case 后面的常量表达式的值相比较,当表达式的值与某个常量表达式 n 的值一致时,则从语句 n 开始执行,直到遇到 break 语句或 switch 语句的 “ } ”;若表达式与任何常量表达式的值均不一致,则执行 defaut 后面的语句或执行后续语句。
关于 switch 结构的说明:
(1)switch 后面的表达式类型一般为整形、字符型和枚举型,但不能为浮点型。
(2) 常量表达式 n 仅起语句标号作用,不作求值判断。
(3)每个常量表达式的值必须各不相同,没有先后次序。
(4)多个 case 语句可以共用一组执行语句,如:
#include<stdio.h>
int main()
{
int n=0;
printf("请输入你的选择:> ");
scanf("%d", &n);
switch (n)
{
case 1:
case 2: printf("hello C.\n");
default: printf("haha\n");
}
return 0;
}
n 的值为 1 或者 2 时都会执行完所有的语句。
例:根据一个代表星期几的0到6之间的整数,在屏幕上输入它就代表的是星期几。
#include<stdio.h>
int main()
{
int n = 0;
printf("请输入你的选择(0~6):> ");
scanf("%d", &n); /*从键盘中获取数据给变量 n */
switch (n) /*根据变量 n 的值选择执行对应的语句*/
{
case 1:
printf("星期一\n");
break;
case 2:
printf("星期二\n");
break;
case 3:
printf("星期三\n");
break;
case 4:
printf("星期四\n");
break;
case 5:
printf("星期五\n");
break;
case 6:
printf("星期六\n");
break;
default: /*当 n 取别的值时*/
printf("星期天\n");
break;
}
return 0;
}
从本范例可以看到:switch 语句中的每一个 case 的结尾通常有一个 break 语句,它停止 switch 语句的继续执行,而转向该 switch 语句的下一个语句。但是,使用 switch 语句比用 if-else 语句简洁得多,可读性也好得多。因此遇到多分支选择的情形,则应当尽量选用 switch 语句,而避免采用嵌套较深的 if - else 语句。
注意:case 后面的常量表达式可以是一条语句,也可以是多条语句,甚至可以在 case 后面的语中再嵌套一个 switch 语句。