LINUX-C成长之路(五):控制流

来源:互联网 发布:js怎么让按钮显示 编辑:程序博客网 时间:2024/06/06 22:53

C 语言是一种 “高级” 语言,所谓的高级,就是拥有逻辑控制语句,可以使得我们实现诸如 循环、分支、跳转等操作。我们来逐一分析。


第一,循环语句。 C语言中,总共有3种循环语句,它们分别是 while 循环, do_while 循环 , 和 for 循环。

1,while循环,下面是示例代码:

[cpp] view plaincopy
  1. int a = 0;  
  2.   
  3. while( a < 100 )  // 每循环一次a加1,总共循环100次。  
  4. {  
  5.         printf("%d\n", a);  
  6.         a++;  
  7. }  
上面的例子虽然简单,但已经说明白了while循环的用法了,当程序碰到 while (表达式)  时,系统会计算表达式的值,如果表达式的值为真,那么就执行后面的循环体,即后面用一对花括号包含起来的所有语句。 执行完之后,再来计算一遍这个表达式,如果还是为真,那就把循环体在执行一遍,就这样不断地重复,一直到表达式的值为假为止。如果 while(表达式)  中的表达式永远为真,那就是所谓的 死循环,永不退出。

上面的例子由于 a 的值会不断地递增,当 a 等于 100 时, 表示 a < 100 不成立,值为假,循环退出。


仔细观察 while 循环结构,你会发现,while 循环中的循环体有可能不会被执行,因为循环条件可能一开始就不成立。如果你需要你的循环体代码至少被执行一遍,那么推荐你使用另一种循环结构:

2,do-while 循环,下面是示例代码:

[cpp] view plaincopy
  1. int a = 0;  
  2.   
  3. do{  
  4.         printf("%d\n", a);  
  5.         a++;  
  6. }while( a < 100 ); // 每循环一次a加1,总共循环100次。  

注意,在 do-while 循环结构中,while语句后面有一个分号,不能省略。上面这段代码的意思是:开始的时候不管三七二十一,先来打印一遍a的值,然后 加1,然后再来判断条件是否成立,成立则继续循环,不成立则退出循环。


Note: 

1. do while语句后,有一个 ';' 号, 别忘了。

2. for(a=0, sum =0; a<100;a++) 第一个分号前, 是设置初始值, 除了设置传统的 i=0 以外,还可以设置其他进入这个for循环的初始值,如sum=0, 而第一个,第三个表达式都是可省的,但分号不可省。

 

除此之外,C语言还有第三种循环结构,也是最常用的循环结构:

3,for循环,先来看示例代码:

[cpp] view plaincopy
  1. int a;  
  2. for(a = 0; a < 100; a++)  
  3. {  
  4.         printf("%d\n", a);  
  5. }  

从代码中得知,for循环中,for语句里面有 3 个表达式,第一个表达式是 a = 0, 这个表达式仅在最开始的时候被执行一遍,然后就跟for循环没有任何关系了,这个表达式一般称为循环变量初始化表达式,示例中 a 就是循环变量,被初始化为0。 第二个表达式是 a < 0, 这个表达式相当于 while 循环和 do-while 循环中的循环条件,当这个条件为真时,执行循环体,否则退出循环,这个表达式一般称为条件测试表达式。 第三个表达式是 a++ , 这个表达式在执行完整个循环体之后执行,一般用来更新条件变量。

事实上,以上代码完全等价于:

[cpp] view plaincopy
  1. int a;  
  2. a = 0;  
  3. for(; a < 100; )  
  4. {  
  5.         printf("%d\n", a);  
  6.         a++;  
  7. }  

注意到,for 语句当中的表达式可以被移除,但是两个分号不可省略。

 

C语言中除了循环结构,还有分支跳转结构,它们分别是:

1, if 语句 和 if - else 语句,请看示例代码:

[cpp] view plaincopy
  1. int a = 100;  
  2.   
  3. if( a%2 == 0)  
  4. {  
  5.         printf("a 是偶数");  
  6. }  
  7. else  
  8. {  
  9.         printf("a 是奇数");  
  10. }  

上述代码中,使用了if - else 语句,在if 语句中,有一个表达式 a%2 == 0, 这个表达式的值决定了程序是否执行 if 语句所包含的代码块,即第 5 行。 如果该语句为真,则执行第 5 行,否则执行 else所包含的语句,即第 9 行。

 

注意,else语句不可单独使用, 它必须要跟if 语句配套使用。 if 语句所带的代码块和else 语句所带的代码块是互斥的,换句话说,它们是程序执行的两路分支,非此即彼,不可同时执行。 那如果不是两路分支,而是多路分支呢? 此时可以写成 阶梯形 的if - else 语句,例如:

[cpp] view plaincopy
  1. int color = red;  
  2.   
  3. if(color == yellow)  
  4. {  
  5.         printf("黄色");  
  6. }  
  7. else if(color == blue)  
  8. {  
  9.         printf("蓝色");  
  10. }  
  11. else if(color == red)  
  12. {  
  13.         printf("红色");  
  14. }  
  15. else if(color == pink)  
  16. {  
  17.         printf("粉色");  
  18. }  
  19. else  
  20. {  
  21.         printf("不认识的颜色");  
  22. }  

这段代码展示了所谓的阶梯形的 if - else 语句,用来实现多路分支,代码中的各种颜色是互斥的,运行时只会打印其中的一种。

 

事实上,要实现上述的多路分支,有一个更好的选择:switch。请看打印颜色的另一个版本代码:

[cpp] view plaincopy
  1. int color = red;  
  2.   
  3. switch(color)  
  4. {  
  5. case yellow:  
  6.         printf("黄色");  
  7.         break;  
  8. case blue:  
  9.         printf("蓝色");  
  10.         break;  
  11. case red:  
  12.         printf("红色");  
  13.         break;  
  14. case pink:  
  15.         printf("粉色");  
  16.         break;  
  17. default:  
  18.         printf("不认识的颜色");  
  19. }  

这段代码实现跟上面 阶梯形 if - else 代码完全一样的功能,但是明显更加简洁易读,其主要的语法要点有:

1, switch(表达式) 语句中的那个表达式的类型必须是一个整型(包括字符型)

2, case语句后面的表达式必须是一个整型常量。比如100, 200, 或者yellow,blue等宏常量或者枚举常量,或者'A', 'X', 等字符常量。

3, case语句是一个入口标签,程序会先计算switch语句的值,然后跟下面的所有case语句相比较,如果相等则执行下面的代码,否则跳过。 另外, case 标签是只管进去不管出来的,换句话讲,如果要让 color 的值为 yellow 时只打印“黄色”,那在第 6 行下面必须有一句break 语句,否则,程序将会将“蓝色”也打印出来,直到遇到右花括号或者break语句为止。

4, default语句是可选的。 如果有这条语句,它的意思是:假如所有的情况都不匹配,那么就执行default的语句。

 

Note: 

1. switch 的大括号内, case 之前,写下的语句是不会执行的,也不会报错。

2. switch 表达式的类型必须是整型(包括字符型),不能是string.

3. switch的case ,是需要写break;的, 不然,switch中的case后的所有case 都会执行完。

4. goto语句,现在最好只用在出错处理。


最后,C语言中还有一位“臭名昭著”的家伙: goto,在任何书籍中都被警告为会破坏程序逻辑的语句,编程者少用为妙。情况到底是怎样的呢?

goto 语句在语法结构上,确实跟刚刚提到的那些“正常”的控制流不同,它几乎不受约束,它可以跳转到任意你所指定的位置,这样做的后果是程序代码太自由,滥用将会使得整个程序面临无法阅读的境地,但是goto语句并不可怕,翻开LINUX源代码,你不仅可以看到goto语句的身影,而且它出现的频率还相当地高,但是用的多不代表用的广,goto语句往往只被用在一个地方:出错处理。

C语言跟C++比较,缺少所谓的异常捕获机制,在工程中,为了更好地管理代码,往往会将出错处理代码统一放在一个地方,程序中当发现有错误的时候,就可以使用goto 语句直接跳转到该代码处进行处理。这么做的好处是,程序中出错的地方可能被深层嵌套在函数或者循环语句当中,要一层一层地返回无疑极其繁琐, goto语句的直接跳转特性使得这一切都不再是问题。

原创粉丝点击