英文原版:P99
在第5章里,我们介绍了C语言的选择语句:if语句和switch语句。
本章我们介绍C语言的循环语句。一个循环就是一条语句,该语句的作用就是重复地执行循环体。在C语言中,每个循环都有一个控制表达式。每次执行循环体时,会首先计算控制表达式的值:如果该表达式的值为真(非0值),则循环就继续执行。
C语言提供了3种迭代语句:
-
while语句
在循环体执行前,测试控制表达式; -
do语句
在循环体执行后,测试控制表达式; -
for语句
适用于有自增或者自减计数变量值的循环;
本章内容
- 6.1节介绍了
while语句 - 6.2节介绍了
do语句 - 6.3节介绍了
for语句,逗号运算符 - 6.4节介绍了
break语句、continue语句、goto语句,其中break语句的作用是跳出循环体,将控制权交给在循环后的下一条语句;continue语句跳过一次循环迭代;goto的作用是跳转到函数内部的任何一条语句; - 6.5节介绍了
null语句,用于控制有空循环体的循环。
while语句
在C语言的所有循环语句中,while语句时最简单且最基础的。
形式
while (表达式) 语句
解释:
- 在括号里的表达式是控制表达式,在括号后的语句是循环体。
- 括号是必需的,右括号跟循环体之间没有任何符号。
执行过程
- 先求控制表达式e的值。
- 如果控制表达式的值为0,则什么都不做,直接执行在while语句后的下一条语句。
- 如果控制表达式e的值为非0,则执行循环体,且再次检查控制表达式。继续这种模式:先测试控制表达式的值,再执行循环体。直到控制表达式的值为0。
例1 计算大于n的最小的2的幂次方值
i = 1;
while (i < n){
i = i * 2;
}
例2 递减计数
i= 10;
while (i > 0) {
printf("T minus and counting\n", i);
i--;
}
无穷循环
形式
while (1) 语句
程序示例1:打印平方表
源文件sqare.c
#include <stdio.h>
int main(void)
{
int i, n;
printf("This program prints a table of squares.\n");
printf("Enter number of entries in table: ");
scanf("%d", &n);
i = 1;
while (i<=n) {
printf("%10d%10d\n\n", i, i*i);
i++;
}
return 0;
}
程序示例2:对输入的数求和
源文件:sum.c
#include <stdio.h>
int main(void)
{
int n, sum = 0;
printf("This program sums a serial of integers.\n");
printf("Enter integers (0 to terminate): ");
scanf("%d", &n);
while(n!=0) {
sum += n;
scanf("%d", &n);
}
printf("The sum is : %d\n", sum);
return 0;
}
6.2节 do循环语句
形式:
do 语句 while (控制表达式);
执行:
当执行一个do语句时,首先执行循环体,然后求控制表达式的值。如果控制表达式的值为非0,则再次执行循环体,然后再次求控制表达式的值。直到某次循环体执行后,控制表达式的值为0,do语句的执行才终止。
例1 do语句示例
int i;
i = 10;
do {
printf("T minus %d and counting\n", i);
--i;
} while (i > 0);
程序示例:计算一个整数的数字个数
源文件numdigits.c
/*Calculates the number of digits in an integer */
#include <stdio.h>
int main(void){
int digits = 0, n;
printf("Enter a nonnegative integer: ");
scanf("%d", &n);
do {
n /= 10;
digits++;
}while(n>0);
printf("The number has %d digit(s).\n", digits);
return 0;
}
6.3节 for循环语句
形式
for(表达式1; 表达式2; 表达式3) 语句
例1 for循环
int i;
for (i=10; i>0;i--)
printf("T minus %d and counting\n", i);
常用for循环语句范例
- 从0到n-1
for (i=0; i<n;i++) ...
- 从1到n
for (i=1; i<=n;i++) ...
- 从n-1到0
for (i=n-1; i>=0;i--) ...
- 从n到1
for (i=n; i>0;i--) ...
逗号,运算符
形式
表达式1, 表达式2
求值
首先,对表达式1求值,然后丢弃该值;
然后,对表达式2求值,该值是整个表达式的值;
优先级
逗号运算符的优先级低于所有其他运算符
使用场合
- 某些宏定义可从逗号表达式中受益;
- for循环语句:两个或者多个初始化表达式;一次循环递增多个变量;
例1
int i,j;
i = 1;
j = 5;
++i, i+j;//整个表达式的值是7
例2
int i, sum;
sum = 0;
for (i=1; i<=N; i++){
sum += i;
}
可使用逗号运算符改写为
for (sum=0, i=1; i<=N; i++){
sum += i;
}
程序示例:打印平方数表
源文件 square2.c
/* Prints a table of squares using a for statement */
#include <stdio.h>
int main(void){
int i, n;
printf("This program prints a talbe of squares.\n");
printf("Enter number of entries in table: ");
scanf("%d", &n);
for (i=1; i<=n; i++){
printf("%10d%10d\n", i, i*i);
}
return 0;
}
square3.c
#include <stdio.h>
// This program prints a table of squares.
// Enter number of entries in table: 10
// 1 1
// 2 4
// 3 9
// 4 16
// 5 25
// 6 36
// 7 49
// 8 64
// 9 81
// 10 100
int main(void)
{
int i, n, odd, square;
printf("This program prints a table of squares.\n");
printf("Enter number of entries in table: ");
scanf("%d", &n);
i = 1;
odd = 3;
for (square = 1; i <= n; odd += 2) {
printf("%10d%10d\n", i, square);
++i;
square += odd;
}
return 0;
}
6.4节 循环退出语句
首先,从循环中退出分为两种情况:
- 正常退出;
- 从循环体中退出;
正是因为有了从循环体中退出的需求,才会有专门的循环退出语句,比如break;
其次,
break语句实现了两个循环退出需求:
- 从循环体中退出;
- 循环语句中不止有一个退出点;
continue语句实现了不跳出循环跳过一次迭代的需求。
break语句
作用:
将程序的控制权转交到循环的结束执行的下一条指令;
跳出循环;
两种用法:
- 从switch语句中退出
- 从循环语句中退出,比如while、do、for等
使用场合
- 循环的退出点是循环体的中间,而非循环开始或者结束;
- 如果一个语句嵌套有while、do、for、switch语句,则break只能从最内层跳转出来,即一次只能跳转出一层嵌套。
例1 检测一个数是不是素数
for (d=2; d<n; d++){
if (n%d == 0) {
break;
}
}
if (d < n) {
printf("%d is divisible by %d\n", n, d);
}else {
printf("%d is a prime\n");
}
例2 循环读取用户输入,直到碰到一个特殊的值
for(;;){
printf("Enter a number (enter 0 to stop): ");
scanf("%d", &n);
if (n == 0) {
break;
}
}
例3 跳出一层嵌套语句
while(...){
switch(...){
...
break;
...
}
}
continue语句
作用:
跳过当前的循环体执行,将程序的控制权转交下次循环体执行开始。
继续驻留在循环中。
使用场合:
- 只能用于循环语句;
例1 continue用法
n = 0;
sum = 0;
while(n < 10){
scanf("%d", &i);
if (i == 0) {
continue;
}
sum += i;
n++;
}
或者
n = 0;
sum = 0;
while(n < 10){
scanf("%d", &i);
if (i != 0) {
sum += i;
n++;
}
}
程序示例:账簿结算
许多交互式的程序都是基于菜单的:给用户展示一个可选择的命令列表。一旦用户选择了某个命令,该程序就执行期望的操作,然后等待着用户选择下一次命令。该程序直到用户选择了一个exit或者quit命令才结束执行。
这样一个程序的核心是一个循环。在循环内是有语句提示用户输入一条指令,读取该指令,执行该指令,比如
for (; ;) {
语句提示用户输入指令;
读取指令;
执行指令;
}
执行指令需要switch语句,比如:
for (; ;) {
语句提示用户输入指令;
读取指令;
switch(指令){
case 指令1: 执行操作1;break;
case 指令2: 执行操作2;break;
.
.
.
case 指令n: 执行操作n;break;
default: 打印错误消息; break;
}
}
开发一个账簿结算程序,需求是给用户提供给一个选择菜单:
- 清空该账户余额,用0表示;
- 向该账户里存钱,用1表示;
- 从该账户里取钱,用2表示;
- 展示余额,用3表示;
- 退出程序,用4表示;
源文件checking.c
/** Balances a checkbook */
#include <stdio.h>
int main(void)
{
int cmd;
float balance = 0.0f, credit, debit;
printf("*** ACME checkbook-balancing program ***\n");
printf("Commands: 0=clear, 1=credit, 2=debit, ");
printf("3=balance, 4=exit\n\n");
for(; ;) {
printf("Enter command: ");
scanf("%d", &cmd);
switch(cmd){
case 0:
balance = 0.0f;
break;
case 1:
printf("Enter amount of credit: ");
scanf("%f", &credit);
balance += credit;
break;
case 2:
printf("Enter amount of debit: ");
scanf("%f", &debit);
balance -= debit;
break;
case 3:
printf("Current balance: %.2f\n", balance);
break;
case 4:
return 0;
default:
printf("Commands: 0=clear, 1=credit, 2=debit, ");
printf("3=balance, 4=exit\n\n");
break;
}
}
}
6.5节 null语句
定义
除了末尾的分号外,什么都没有的语句。
比如
i = 0;
; //null语句
j = 1;
例2 使用null语句来改写循环
for (d=2; d<n; d++){
if (n%d == 0) {
break;
}
}
改写为
for (d = 2; d < n && n%d !=0; d++){
;
}
错误的使用null语句
for (d = 2; d < n && n%d !=0; d++);