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

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


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

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

int a = 0;

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

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


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

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

int a = 0;

do{
        printf("%d\n", a);
        a++;
}while( a < 100 ); // 每循环一次a加1,总共循环100次。

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

 

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

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

int a;
for(a = 0; a < 100; a++)
{
        printf("%d\n", a);
}

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

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

int a;
a = 0;
for(; a < 100; )
{
        printf("%d\n", a);
        a++;
}

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

 

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

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

int a = 100;

if( a%2 == 0)
{
        printf("a 是偶数");
}
else
{
        printf("a 是奇数");
}

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

 

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

int color = red;

if(color == yellow)
{
        printf("黄色");
}
else if(color == blue)
{
        printf("蓝色");
}
else if(color == red)
{
        printf("红色");
}
else if(color == pink)
{
        printf("粉色");
}
else
{
        printf("不认识的颜色");
}

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

 

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

int color = red;

switch(color)
{
case yellow:
        printf("黄色");
        break;
case blue:
        printf("蓝色");
        break;
case red:
        printf("红色");
        break;
case pink:
        printf("粉色");
        break;
default:
        printf("不认识的颜色");
}

这段代码实现跟上面 阶梯形 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的语句。

 

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

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

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
源程序说明: 1.有些程序是“面试题选”部分的程序,这些程序是习题,有些是不完整(没有main函数,只是一个函数)、有些是故意留有错误的,但书的例题解答里已经详细说明错误的原因。所以,并不是每个程序都可以编译运行的,所有程序请对照书的相应部分。如果是一个用于说明某个知识点的示范程序,那么是一定可以运行的。此外,要注意:有些程序编译时要带上命令行参数,比如编译多线程程序时,需带上-lpthread选项。对于此程序编译时,书都有对应的编译命令。对于一般的程序,只需使用如下命令:gcc -o test test.c。 2.由于格式原因,源程序在Windows下使用Visual C++编辑器打开,那么程序是对齐的。如果使用其他文本编辑器打开,不能一定保证源代码象书一样是对齐的。 3.1~5章的程序是按照例子编号命名的,比如:第2章例1的源程序命名为2-1.c。有些例子没有程序,因此编号不是连续的,比如:4-18.c之后是4-20.c,因为第4章的例19没有程序代码。6~12章的程序是以书的程序名命名的,比如:第6章的第一个程序,书命名为my_chmod.c,那么在这里源程序也命名为my_chmod.c。 4.每一章的源代码可以使用命令“make”进行编译,使用该命令可以生成该章所有可执行程序。如果没有生成对应的可执行程序,请对照书相应的内容。在编译生成可执行程序时,可能会生成警告:“warning:no newline at end of file”,产生这个警告是因为本书所有源代码是在Windows进行编写的,Windows和Linux两种操作系统对于文件末尾的标识符处理不一致。该警告不会影响程序的功能和性能,所以不必理会。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

干燥剂007860

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值