版本比较
标识
- 该行被添加。
- 该行被删除。
- 格式已经改变。
结构化程序设计里有三种程序结构,分别是顺序结构,分支结构,循环结构。goto语句不属于结构化程序设计范畴,但在某些情况也会使用。
顺序结构
指代码从前往后,从上往下顺序执行,之前遇到的所有程序都是顺序结构。
分支语句
指代码会根据不同的条件来选择不同的分支执行,C语言支持if语句和switch...case语句的分支结构。
if语句
也称为判断语句,一共有下面三种形式:
版块 | |||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
if语句可以嵌套,也就是在一个if语句的语句块中再嵌套一个if语句。
使用if语句的注意事项:
如果if语句的某个语句块只有一条语句,那么可以省略这个语句块的大括号,如下:
代码块 if(a > b) printf("a > b"); else printf("a <= b");
if语句的判断条件,只要计算出来的结果是非0,那么条件就成立。计算的方式可以是函数调用或是任何运算符所构成的表达式,像下方式都是合理的:
代码块 if(0) { ... } if(1) { ... } if(a = 3} { ... } if(a == 3) { ... } if(scanf("%d %d %d", &a, &b, &c)) { ... }
- 注意判断条件中赋值与相等的区别,赋值是 "=",判断相等是 "=="。 谨慎的做法是,在相等判断的时候,把常量写在前面,比如 "3 == a",这样,即使错写成 "3 = a",编译器也能检查出错误,避免程序出现逻辑错误。
- if与else的配对原则:从最内层开始,else总是与它上面最接近的、未曾配对的if匹配。
- 避免if与else配对错位的最佳方法是使用括号和缩进,良好的编程习惯是即使if或者else的语句只有一条,也要另起一行加上括号和缩进。
switch语句
代码块 | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
switch(表达式1) { case 常量表达式1: 语句1; break; case 常量表达式2: 语句2; break; ... case 常量表达式n: 语句n; break; default: 默认语句; break; } |
使用switch语句的注意事项:
- switch后面的表达式计算结果必须为int型或char型,浮点型与地址类型及其他构造类型都是不合法的。
- case后面必须为可以精确进行比较的int型或char型常量或常量表达式,使用变量表达式是不合法的。
- case后面的常量表达式必须的互不相同,否则编译无法通过。
- 每个case的结尾绝对不要忘了加break,否则将导致多个分支重叠(除非有意使多个分支重叠)。
- case与default的出现顺序不影响执行结果。
- 必须使用default分支,即便程序不需要default,也应该保留default语句并加上break。保留的目标是让程序来解释,编程者已经考虑到了default情况并认为可以不加处理,从而避免让人误以为你忘了default处理。
if语句与switch语句的比较
理论上,使用switch的语句都可以用if语句来改写,但是,在纯粹进行数字或字符比较且比较的分支较多时,使用switch语句的代码逻辑性和可读性都要优于if语句,自行体会。
循环结构
循环结构可以让代码得到重复的执行,循环是一种非常重要的编程手段,很多重要的计算过程都要用到循环结构。使用循环结构的步骤一般分三步:
- 初始化循环条件,常见的手段是通过一个变量来控制循环,那么第一步就应该给这个变量赋初值。
- 编写循环结构要执行的操作,其中必须要有一步是改变循环条件,最终让循环条件不成立,比如增加变量使其超越临界值。
- 检查循环条件是否符合成立,以便在某个时该跳出循环。不能跳出的循环称为死循环,死循环会严重占用CPU的时间片资源,在编程中应该尽量避免。如果不得不使用死循环,那么也要在每个循环中加入一小段睡眠,以便于让出时间片使得CPU可以处理其他的任务。
while与do-while循环
代码块 | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
while(循环条件)
{
语句块;
}
do
{
语句块;
}while(循环条件);
|
while循环执行的步骤:
- 如果循环条件为假,则跳过整个while语句;
- 如果循环条件为真,则执行语句,然后再次检查循环条件。
- 重复第1步和第2步。
do-while循环执行的步骤:
- 执行语句块;
- 检查循环条件,如果为假,则结束整个do-while循环;
- 如果为真,重复第1步和第2步。
while与do-while都是通过检查循环条件来确定是否结束循环的,循环正常结束的条件是,括号里面的计算结果为0(包括数值0,空间指针NULL,函数返回值为0)。
do-while循环与while循环的区别是,do-while的循环体语句至少会被执行一次,而while循环的语句则有可能一次都不执行。
for循环
代码块 | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
for(表达式1;表达式2;表达式3)
{
语句块;
}
|
for语句的执行顺序是:
- 求解表达式1;
- 求解表达式2,如果表达式2的值不为0,则执行循环语句块,否则结束循环;
- 执行表达式3;
- 重复第2步到第3步,再判断表达式2是否为0,不为零则继续循环,否则循环结束。
for循环语句自带三个表达式,意味着它可以把循环的三步曲,既初始化循环变量,控制循环变量,结束循环这三步合在一起进行操作,使得for循环的执行语句可以不用去管循环变量的状态,以下是for循环的典型用法:
int i;
for(i = 0; i < 100; i++)
{
//语句块;
}
注意,在C99标准中,可以在for语句的三个表达式中定义并初始化变量,比如,以上语句可以写成:
for(int i = 0; i < 100; i++)
{
//语句块;
}
但是,这只是在较新的编译器中才支持这样的写法,为了程序的可移植性,请大家不要采用这种写法。
break与continue
正常情况下,循环是否结束要依赖于循环条件,但在某些情况下,我们也可以通过break与continue来人为地控制循环走向。
break
break是最简单的结束循环的办法,程序在遇到break语句后,将自动跳出本循环。注意,break只能结束一层循环,多层的循环需要通过多个break才可以完全跳出,以下是break语句的应用示意:Image Added
continue
continue只用于结束本轮循环,如果循环条件符合,则循环还会继续下去,以下是continue的示意图:
Image Added
goto语句
使用goto语句可以在程序中进行无条件地跳转。goto语句的格式如下:
代码块 | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
…
语句标号:
…
goto 语句标号;
…
|
标号命名同变量命名,标号后面紧跟一个冒号,标号的作用域是整个函数。
任何一本关于C语言的书上都会提到,使用goto语句会破坏C程序的结构,下面通过一个例子让大家感受一下。一般认为,if-else语句中,if的语句块和else的语句块是不可能同时执行到的,但是,使用goto语句后,则可以使if和else中的语句都得到执行,如下:
代码块 | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
if(xxx)
{
…
goto test;
}
else
{
test:
…
}
|
同样很多书上会提到,不主张使用goto语句。我的建议是,不要使用goto,但要了解goto语句的语法和常见的应用场景,因为在某些典型应用场景下,goto语句还是可以发挥作用的,具体的情形在《代码大全》17章第3小节中有比较详细的论述,有兴趣的同学可以去翻看。
goto
目录 |
---|