一门语言应提供以下3种形式的程序流:

  1. 执行语句的序列;
  2. 如果满足某些条件就重复执行语句序列(循环);
  3. 通过测试选择执行哪一个语句序列(分支)。

while语句

while语句的通用形式如下:

while( expression ) //测试表达式(都为关系表达式)
    statement //可以是以分号结尾的简单语句,也可以是花括号括起来的复合语句

如果expression为真(或者非0),执行statement部分一次,然后再次判断expression。在expression为假(0)之前,循环的执行一直重复进行。每次循环称为一次迭代

  1. 终止while循环
    注意:在构建while循环时,必须让测试表达式的值有变化,表达式最终要为假。否则,循环就不会终止(当然可以使用breakif语句来终止循环)。
  2. 何时终止循环
    要明确一点:只有在对测试条件求值时,才决定是终止还是继续循环。
  3. while:入口条件循环
    while循环是使用入口条件的有条件循环。所谓“有条件”指的是语句部分的执行取决于测试表达式描述的条件。
  4. 语法要点
    牢记:

    • 只有在测试条件后面的单独语句(简单语句或复合语句)才是循环部分。
    • 即使while语句本身使用复合语句,在语句构成上,它也是一条单独的语句。该语句从while开始执行,到第一个分号结束。在使用了复合语句的情况下,到右花括号结束。
    • 空语句(即循环体什么都不做,就一个分号)多用于所有任务都在测试条件中完成了的情况。

用关系运算符和表达式比较大小

测试表达式被称为关系表达式,出现在关系表达式中间的运算符叫做关系运算符。关系运算符用于构成关系表达式。

运算符含义
<小于
<=小于或等于
==等于
>=大于或等于
>大于
!=不等于
  • 关系表达式可用于比较字符(但不能比较字符串)。比较时使用的是机器字符码(如ASCII)。
  • 注意比较浮点数时,应尽量只使用<>。因为浮点数的舍入误差会导致在逻辑上应该相等的两数却不相等。
  1. 什么是真
    对C而言,表达式为真的值是1;表达式为假的值是0。
  2. 其他真值
    一般而言,所有的非零值都视为真,只有0被视为假。

    • while( gosts )while( gosts != 0 )等价,应尽量使用前者简洁的写法。
  3. 真值的问题

    • while( status == 1 )while( status = 1 ),因为一个关系运算符的差别,行为天差地别,后者会导致死循环,且循环体内对status的值更改都是无意义的,因为执行测试条件时总是会被赋值为1。
    • 而编译器不会检查你使用了错误的形式(现在大多编译器都会给出警告),得出也不是预期的结果。如果待比较的一个值是常量,可以把常量放在左侧有助于编译器捕获错误(因为C不允许给常量赋值)。
  4. 新的_Bool类型

    • 在编程中,表示真或假的变量被称为布尔变量,所以_Bool是C语言中布尔变量的类型名。_Bool类型的变量只能存储1(真)或0(假)。如果把其他非零值赋给_Bool类型的变量,该变量会被设置为1.这反映了C把所有的非零值都视为真。
    • 给布尔变量取一个能表示真或假的变量名是一种常见的做法。注意如下,如何为变量命名才能让while循环的测试简单易懂:
      定义:_Bool input_is_good;,使用则:while( input_is_good )
    • C99提供了stdbool.h头文件,该头文件让bool称为_Bool的别名,而且还把truefalse分别定义为1和0的符号常量。
  5. 优先级和关系运算符
    关系运算符的优先级比算术运算符低,比赋值运算符高。结合律也是从左往右。

运算符优先级:

运算符(优先级从高至低)结合律
()从左往右
- + ++ -- sizeof从右往左
* / %从左往右
+ -从左往右
< > <= >=从左往右
== !=从左往右
=从右往左

不确定循环和记数循环

  • 不确定循环:指在测试表达式为假之前,预先不知道要执行多少次循环。
  • 计数循环:在执行循环之前就知道要重复执行多少次。
    在创建一个重复执行固定次数的循环中涉及了3个行为:

    1. 必须初始化计数器;
    2. 计数器与有限值作比较;
    3. 每次循环时递增计数器。
  • while循环不适合作计数循环(上述三个步骤),所以我们应该用下面学习的for循环。

for循环

for循环把上述3个行为(初始化、测试和更新)组合在一处。

    //第一个表达式是初始化,只会在for循环开始时执行一次;
    //第二个表达式是测试条件,在执行循环之前对表达式求值,如果为假,循环结束;
    //第三个表达式执行更新,在每次循环结束时求值
    for(initialize; test; update)
        statement    //可以是以分号结尾的简单语句,也可以是花括号括起来的复合语句
  1. 利用for的灵活性

    • 可以使用递减运算符来递减计数器
    • 可以让计数器递增2、10等(步进值)
    • 可以用字符代替数字计数(利用ASCII码)
    • 除了测试迭代次数外,还可以测试其他条件
    • 可以让递增的量几何增长,而不是算术增长(不递增相加,而是乘以某个数)
    • 第3个表达式可以使用任何合法的表达式
    • 可以省略一个或多个表达式(但是不能省略分号),只要在循环中包含能结束循环的语句即可
    • 第1个表达式不一定是给变量赋初值,也可以使用printf()(注意,该表达式只在执行循环其他部分前执行一次)
    • 循环体中的行为可以改变循环头中的表达式

其他赋值运算符:+=-=*=/=%=

  • 赋值运算符和其他赋值运算符都用于更新变量,其用法都是左侧是一个变量名,右侧是一个表达式。赋给变量的新值是根据右侧表达式的值调整后的值。

逗号运算符

  • 逗号运算符扩展了for循环的灵活性,以便在循环头中包含更多的表达式。
  • 逗号运算符并不局限于在for循环中使用,但这是它最常用的地方。
  • 逗号运算符有两个其他特质。首先,它保证了被它分割的表达式从左往右求值(即逗号是一个序列点,所以逗号左侧项的所有副作用都在程序执行逗号右侧项之前发生);其次,整个逗号表达式的值是右侧项的值。
  • 任何表达式后面加上一个分号就成了表达式语句。
  • 逗号也可做分隔符,如常见的是在一个类型后申明多个变量,此外还有函数参数的分割。

出口条件循环:do while

while循环和for循环都是入口条件循环,即在循环的每次迭代之前检查测试条件,所以有可能根本不执行循环体中的内容。C语言还有出口条件循环,即在循环的每次迭代之后检查测试条件,这保证了至少执行循环体中的内容一次。这种循环被称为 do while 循环。
下面是 do while 循环的通用形式:

do
    statement    //可以是以分号结尾的简单语句,也可以是花括号括起来的复合语句
while ( expression );    //测试表达式(都为关系表达式)

如何选择循环

  1. 首先,确定是需要入口条件循环还是出口条件循环。通常入口条件循环用得比较多。
  2. 那么,假设需要一个入口条件循环,用for循环还是while循环?这取决于个人爱好,因为二者皆可。for循环可以像while一样使用,while也可以模仿for循环方式使用。
  3. 一般而言,当循环涉及初始化和更新变量时,用for循环比较合适,而在其他情况下用while循环更好。

嵌套循环

嵌套循环指在一个循环内包含另一个循环。嵌套循环常用于按行和列显示数据,也就是说,一个循环处理一行中的所有列,另一个循环处理所有的行。

  1. 程序分析(按行和列显示数据)

    • 这种循环包含外层循环和内层循环,外层循环控制行,内层循环控制列。
    • 注意,嵌套循环中的内层循环在每次外层循环迭代时都执行完所有的循环。
  2. 嵌套变式

    • 可以通过外层循环控制内层循环,在每次外层循环迭代时内层循环完成不同的任务(如九九乘法表)。

数组简介

  • 数组是按顺序存储的一系列类型相同的值,整个数组有一个数组名,通过整数下标访问数组中单独的项或元素。注意,数组元素的编号是从0开始,不是从1开始
  • 考虑到影响执行的速度,C编译器不会检查数组的下标是否正确。
  • 可以把字符串存储在char类型的数组中,如果char类型的数组末尾包含一个表示字符串末尾的空字符\0,则该数组中的内容就构成了一个字符串。
  • 用于识别数组元素的数字被称为下标索引偏移量,下标必须是整数而且从0开始计数。数组的元素被依次存储在内存中相邻的位置。
  1. 在for循环中使用数组

    1. #define指令创建明示常量(SIZE),来指定数组大小
    2. 下面的代码可以很方便的处理一个大小为SIZE的数组,设置正确的数组边界很重要:
    for (index = 0; index < SIZE; index++)
3. 程序能重复显示刚读入的数据。

使用函数返回值的循环示例

  1. 程序分析

    1. main()是一个驱动程序,即被设计用来测试函数的小程序。
    2. 函数的使用至少出现3次在程序中:

      1. 函数声明
      2. 函数调用
      3. 函数定义
  2. 使用带返回值的函数

    • 声明函数、调用函数、定义函数、使用关键字return,都是定义和使用带返回值函数的基本要素。
    • 编译器在程序中首次遇到带返回值的函数时,需要知道该函数的返回类型。此时编译器尚未执行到该函数的定义,并不知道返回类型,所以必须通过前置声明预先说明函数的返回类型。
    • 当然可以把函数定义放在main()的文件顶部就可以省略前置声明,但这不是C的标准风格。因为main()通常只提供整个程序的框架,最好把main()放在所有函数定义的前面。

标签: C/C++, C-Primer-Plus

添加新评论