对标题和序号有稍加修改。
6.1 while循环
本章仍从一个程序开始。
/*根据用户键入的整数求和*/
#include<stdio.h>
int main(void)
{
long num;
long sum=0L;
int status;
printf("Please enter an integer to be summed (q to quit):");
status=scanf("%ld",&num);
while (status==1)
{
sum=sum+num;
printf("Please enter next integer (q to quit):");
status=scanf("%ld",&num);
}
printf("Those integers sum to %ld.\n",sum);
return 0;
}
运行后输出结果:
Please enter an integer to be summed (q to quit):44
Please enter next integer (q to quit):33
Please enter next integer (q to quit):88
Please enter next integer (q to quit):121
Please enter next integer (q to quit):q
Those integers sum to 286.
该程序用以下特性完成的交互输入以及循环求和:
- 用关系运算符(relational operator)判断真假。
-
scanf()
返回读取的项数,读取失败返回0。 - 程序在进入循环体之前检查条件。
6.1 while语句
while循环是使用入口条件(entry condition)的有条件循环,循环体的执行取决于入口条件是否满足。while循环通用形式:
while (expression)
statement
update
语法格式说明:
- statement部分可以是分号结尾的简单语句或复合语句。
-
expression部分是关系表达式(relational expression),
(expression)
就是入口条件。 - expression为假(0)之前,重复执行判断和循环体,每次循环称为一次迭代(iteration)。
- update部分更新控制循环次数的变量,用于终止循环。
6.2.1 语法要点
- 直接跟在入口条件后面的单独语句是循环体。
- 必须更新关系表达式的值,表达式最终为假,否则会陷入无限循环(infinity loop)。
6.2 关系运算符
关系运算符(结合性由高到低) | 含义 |
---|---|
< | 小于 |
<= | 小于或等于 |
> | 大于 |
>= | 大于或等于 |
== | 等于 |
!= | 不等于 |
前四个优先级相同,后两个优先级相同。结合性都是从左往右。
注意事项:
- 不能用于比较字符串。
- 建议使用
<
和>
比较浮点数。 - 求值为真或假,真1假0。
- 区分
=
和==
。
第11章详解字符串的比较。比较浮点数可用
fbs()
(定义在math.h),返回浮点数的绝对值。C中,非0为真,0为假。
6.3 _Bool类型
C99新增表示真或假的布尔变量(Boolean variable)。布尔变量只能储存1或0,赋非0值也会被设置为1。使用stdbool.h
使bool
成为_Bool
的别名,可以赋值为true或false。
6.4 不确定循环和计数循环
不确定循环(indefinite loop)指在关系表达式为假之前不知道要执行多少次循环。计数循环(counting loop)指在执行循环前直到要循环的次数。计数循环示例:
#inlude<stdio.h>
{
const int NUMBER=5;
int count=1; /*初始化计数器*/
while (count<=NUMBER) /*比较*/
{
printf("UnicornBeetle\n");
count++; /*更新计数器*/
}
return 0;
}
计数循环的3个行为:
- 初始化计数器。
- 计数器与有限值比较。
- 每次迭代时更新计数器。
6.5 for循环
for循环把初始化、判断和更新组合在一起。形式为:
for (initialize;r expression;update)
statement
- initialize部分在循环开始前执行一次。
- 对test求值,为真就执行循环体。
- 每次循环结束时执行update再对test求值。
- 三个表达式都是完整表达式。
章首的示例程序可以改为:
#include<stdio.h>
int main(void)
{
long num,sum=0L;
int status;
printf("Please enter an integer to be summed (q to quit):");
for (status=scanf("%ld",&num);status==1;status=scanf("%ld",&num))
{
sum=sum+num;
printf("Please enter next integer (q to quit):");
}
printf("Those integers sum to %ld.\n",sum);
return 0;
}
6.5.1 for的灵活性
- 初始化部分不一定是为变量赋初值。
- 更新表达式可以使任意合法的表达式。
- 可以省略一个或多个表达式(不能省略
;
),循环体中包含能结束循环的语句即可。 - 循环体中的行为可以改变循环头中的表达式。
省略表达式
#include<stdio.h>
int main(void)
{
int n,ans=2;/*初始化部分*/
for (n=3;ans<=25;)/*仅有关系表达式*/
ans=ans*n;/*更新部分*/
printf("n=%d,ans=%d.\n",n,ans);
return 0;
}
注意,如果省略关系表达式则被视为真。例如,以下循环会无限运行。
for (; ; )
printf("Hello World!\n");
6.6 其他赋值运算符
运算符 | 含义 |
---|---|
+= | A+=B相当于A=A+B |
-= | A-=B相当于A=A-B |
*= | A*=B相当于A=A*B |
/= | A/=B相当于A=A/B |
%= | A%=B相当于A=A%B |
6.7 逗号运算符
,
运算符将两个表达式连接成一个表达式,有两点性质:
- 最左边表达式先求值。
- 整个表达式的值是最右边表达式的值。
逗号运算符作为序列点保证左侧表达式的副作用在执行右侧表达式之前发生。示例程序;
#include<stdio.h>
int main(void)
{
int x,y;
x=(2019,2020);
y=(2020,2021);
printf("x=%d,y=%d\n",x,y);
x++;y=x*2;
printf("x=%d,y=%d\n",x,y);
return 0;
}
运行后输出结果:
x=2020,y=2021
x=2021,y=4042
在一些表达式中,,
是分隔符。例如:char a,b;
、printf("%c %c",a,b);
等等。
6.8 出口条件循环:do while
出口条件循环(exit-condition loop),即在每次迭代后检查条件,保证循环体至少执行了一次。do while通用形式:
do
statement
while(expression);
do while循环条件以;
结尾。示例程序:
#include<stdio.h>
int main(void)
{
int num=0;
do
{
printf("%d ",num);
num++;
}
while (num<=10);
return 0;
}
运行后输出结果:
0 1 2 3 4 5 6 7 8 9 10
6.9 嵌套循环
嵌套循环(nested loop)指用一个外层循环(outer loop)包含一个内层循环(inner loop),常用于按行列显示数据,外层循环控制行,内层循环控制列。示例程序:
#include<stdio.h>
int main(void)
{
const int ROWS=6;
const int CHARS=6;
int row;
char ch;
for (row = 0; row < ROWS; row++)
{
for (ch = ('A'+row); ch < ('A'+CHARS); ch++)
printf("%c",ch);
printf("\n");
}
return 0;
}
运行后输出结果:
ABCDEF
BCDEF
CDEF
DEF
EF
F