• 沒有找到結果。

f = p * w * s * (1  d);

printf("freight = %15.4f\n", f);

}

注意:c、s 是整型变量,因此 c s / 250 为整数。当 s≥3000时,令 c 12 ,而不使 c 随 s 增大,这是为了在 switch 语句中便于处理,用一个 case 就可以处理所有 s≥3000的情况。

随堂练习

编程:从键盘上输入一百分制成绩,要求输出成绩相应的等级 A、B、C、D 和 E。其中 90 分以上为 A,80~89 分为 B,70~79 分为 C,60~69 分为 D,60 分以下为 E。

3.5 循环结构程序设计

如果要计算“1+2+3+…+100”的值,根据现有的知识,只能一项一项地求和,这是一件非常 烦琐的事情,如果数据更大点,就更加烦琐,甚至根本无法完成。要解决这类问题,就需要用到 循环。循环结构是结构化程序设计的基本结构之一,它和顺序结构、选择结构共同作为各种复杂 程序的基本构造单元。C 语言中提供的循环语句有 while、do…while 以及 for 语句。

3.5.1 从 while 语句学自增和自减运算符

程序 3_9.c 使用 while 循环来求“1+2+3+…+100”的值。

程序清单 3.9 3_9.c 程序

#include <stdio.h>

void main() {

int i = 1, sum = 0;

while(i <= 100) {

sum += i;

i++;

}

sum 的初始值一定 要赋 0 值

while 循 环 语 句 , 循 环 体 为

“sum+=i;i++;”。其中“i++”

等价于“i= i+1”

printf("1+ 2 + 3 + … + 100 = %d\n", sum);

}

程序 3_9.c 的流程图如图 3.16 所示,运行结果如图 3.17 所示。

图 3.16 程序 3_9.c 的流程图 图 3.17 程序 3_9.c 的运行结果

while 语句用来实现“当型”循环结构,其一般形式如下:

while(表达式) {

语句组;

}

当语句组只有一条语句的时候可以省略大括号。在语句组中必须包含能改变表达式的值 的语句来使表达式的值最终变为假,否则循环永远不会中止。例如:

index = 1;

while(index < 5) {

printf("Hello,C Program!\n");

}

上面的代码段就会陷入“死循环”,程序会无休止地输出“Hello,C Program!”。因为变 量 index 的值为 1,如果 index 的值不发生变化,index < 5 这个条件将永远成立,while 语句 也就会一直循环下去。所以在循环体中应该添加能够使循环正常结束的语句。如程序 3_10.c 所示。

程序清单 3.10 3_10.c 程序

#include <stdio.h>

void main() {

int index = 1;

while(index < 5) {

printf("index = %d\n", index);

index++;

printf("after index++ index = %d\n", index);

}

printf("The loop has finished.\n");

}

每 次 循 环 的 时 候 , 执 行 index++,index 增加 1,当 index<5 不成立的时候就会 退出循环

i = 1

i ≤ 100

sum += i i++

程序 3_10.c 的运行结果如图 3.18 所示。从图 3.18 可以看出在第 4 次循环中,执行完 index++

后,index 的值已经是 5,然而循环此时并不结束,继续执行下面的输出语句 printf("after index++

index = %d\n", index)。执行完输出语句后,再去判断表达式 index < 5 是否成立,此时发现该 表达式为假,才结束 while 循环,执行 while 后面的语句。

图 3.18 程序 3_10.c 的运行结果

如果 while 语句的表达式刚开始就不成立,如将程序清单 3.10 中的 index 的初始值改成 10,

这时,程序永远不会执行循环体,因为条件 index < 5 一开始就为假。

1.自增、自减运算符

在程序 3_10.c 中使用了自增运算符“++”,其作用是使变量的值增 1。与之对应的还有自 减运算符“”,其作用是使变量的值减 1。

自增、自减运算符的使用有两种方式:

前缀模式:++变量,变量(在使用变量之前,先使变量的值加(减)1)。

后缀模式:变量++,变量(在使用变量之后,使变量的值加(减)1)。

从表上看,“++变量”和“变量++”的作用都是使变量的值增 1,但是它们还是有区别的。

“++变量”是先让变量增 1 后,再使用变量的值;而“变量++”则是先使用变量的值,变量 再增 1。自减运算符“”的原理一样。

程序清单 3.11 3_11.c 程序

#include <stdio.h>

void main() {

int a = 1, b = 1;

int aplus, plusb;

aplus = a++;

plusb = ++b;

printf("a = %d\naplus = %d\nb = %d\nplusb = %d\n", a, aplus, b, plusb);

}

程序 3_11.c 的运行结果如图 3.19 所示。从图 3.19 可以看出,执行“aplus = a++”是先将 a 的值 1 复制给 aplus,aplus 的值为 1,然后 a 的值再增 1 变成 2。而“plusb = ++b”则是先使 b 的值增 1 变成 2,然后再将 b 的值赋值给 plusb,plusb 的值为 2。

循环体被执行了 4 次,循环结束 时,index 值为 5

图 3.19 程序 3_11.c 的运行结果

自增和自减运算符有很高的优先级,常用的运算符只有圆括号比它们的优先级高。其结 合性是“自右向左”。所以“x * y++”代表“x * (y++)”而不是“(x * y)++”。而后者也不是一 个合法的表达式,自增、自减运算符只能用于变量,而不能用于常量或表达式。“5++”或“(x

* y)++”都是不合法的。

2.含有自增、自减运算符的表达式的不确定性

C 语言提供的运算符和表达式使用非常灵活,这种灵活性往往也会带来麻烦。由于 ANSI C 并未规定表达式中的子表达式的求解顺序,由各个编译系统自己决定,则表达式:

a = fun1() + fun2()

并非所有的编译系统都是先求解 fun1(),然后再求解 fun2()。在一般的情况下,可能先求 解 fun1()或者先求解 fun2()的结果是一样的,但是在很多时候也是不一样的,如:

n = 2;

a = fun1(n) + fun2(n++);

如果先求解函数 fun1,则 a = fun1(2) + fun2(2),如果先求解 fun2,则 a = fun1(3)+fun2(2)。

又如:

n = 2;

y = n++ + n++;

当该语句被执行后,n 的值变成 4,但是 y 的值是不确定的。有的编译器可能将 n = 2 作 为表达式中所有 n 的值,从而求出 y 为 4。但也有的编译器按照自左向右的顺序来求解表达式,

先求解第一个 n++,这个时候 n++先使用 n 的值 2,然后 n 再增 1,变成 3。在求解第二个 n++

的时候,同理,先使用 n 的值 3,然后 n 再变成 4。此时 y 值为 5。

对于这类问题,在 C 语言中还有一些,例如:

n = 2;

printf("%d, %d\n",n,n++);

在调用函数时,C 语言并未规定对实参的求解顺序,对于上例,有的系统从左到右求解,

输出“2, 2”,而多数系统则是从右向左进行求解,输出“3, 2”。

对于上述的一些不确定性,我们在写程序的时候一定要避免,不要写出别人看不懂,也 不知道系统会怎样执行的代码。在使用自增或自减运算符的时候,要遵循以下两个原则:

(1)如果一个变量出现在同一个函数的多个参数中时,不要用自增或自减运算符。

(2)如果一个变量多次出现在一个表达式里时,不要用自增或自减运算符。

3.5.2 do…while 语句

下面使用 do…while 语句来改写程序 3_9.c(求 1+2+3+…+100 的值)。程序清单如下:

程序清单 3.12 3_12.c 程序

#include <stdio.h>

void main() {

int i = 1, sum = 0;

do {

sum += i;

i++;

}while(i <= 100);

printf("1 + 2 + 3 + ... + 100 = %d\n", sum);

}

程序的运行结果与图 3.17 相同。其流程图如图 3.20 所示。从图 3.20 可以看出,程序先执 行循环体语句,然后再判断 while 后面的条件是否成立。当表达式为真,则返回重新执行循环 体语句,如此反复,直到 while 后面的表达式为假才结束循环。

图 3.20 程序 3_12.c 的流程图 可以看到 do…while 语句的一般形式如下:

do {

循环体语句组;

}while(表达式);

可以看到,对于同一个问题,可以使用 while 语句,也可以使用 do…while 语句,二者可 以互相替换。但是它们还是有区别的,while 语句先判断条件是否成立,然后根据条件的结果 来决定是否执行循环体,而 do…while 语句先执行循环体一次,然后再判断表达式成立与否。

即 do…while 语句至少要执行循环体一次。例如:

程序清单 3.13 3_13.c 程序

/*程序 A*/ /*程序 B*/

#include <stdio.h> #include <stdio.h>

void main() void main() 分号“;”不能少

注意分号“;”不能少

i ≤ 100

sum = 0 i = 1

sum += i i++

{ {

int sum = 0, i; int sum = 0, i;

scanf("%d", &i); scanf("%d", &i);

while(i <= 100) do { {

sum += i; sum += i;

i++; i++;

} }while(i <= 100);

printf("sum = %d\n", sum); printf("sum = %d\n", sum);

} }

程序的运行结果如图 3.21 所示。可以看出,当输入的 i 值都满足 i≤100的时候,程序 A 和程序 B 的运行结果相同。而当输入的 i 值不满足 i≤100的时候,二者的结果就不同了,因 为此时对于 while 语句来说,循环体一次也不会被执行,而 do…while 语句则会执行循环体 一次。

(a)程序 A 的运行结构 (b)程序 B 的运行结构

图 3.21 程序 3_13.c 的运行结果

3.5.3 灵活强大的循环语句——for 语句

C 语言中的 for 语句是使用最为灵活的语句。同样,先使用 for 语句来改写程序 3_9.c 求 1+2+3+…+100 的值。程序清单如下:

程序清单 3.14 3_14.c 程序

#include <stdio.h>

void main() {

int i, sum = 0;

for(i = 0; i <= 100; i++) {

sum += i;

}

printf("1 + 2 + 3 + ... + 100 = %d\n", sum);

}

程序的运行结果与图 3.17 相同。可以看出,for 语句的一般形式如下:

for(表达式 1;表达式 2;表达式 3) {

循环体语句组;

}

for 语句,注意括号中的三个 表达式是用“;”分隔的

循环体语句 i = 1 的结果

i = 101 的结果

i = 1 的结果

i = 101 的结果

当循环体语句组只有一条语句的时候,大括号可以省略。建议初学者不要省略,以避免 出错。for 语句的流程如图 3.22 所示。从图中可以看出,其执行过程如下:

(1)求解表达式 1;

(2)求解表达式 2,如果为真,则执行循环体语句组,执行结束后转步骤(3);如果表 达式的结果为假,则结束循环,转步骤(5);

(3)求解表达式 3;

(4)转步骤(2);

(5)循环结束,执行循环语句之后的其他语句。

图 3.22 for 语句执行流程

for 语句的 3 个表达式均可省略,但是里面的分号“;”不能省略。需要注意的是,省略相 应的表达式,就需要在其他地方弥补相应表达式的功能,以保证程序的正常运行。

3.5.4 逗号运算符和逗号表达式

逗号运算符扩展了 for 循环语句的灵活性,它可以使 for 循环语句使用多个初始化或循环 变量更新表达式。例如:

程序清单 3.15 3_15.c 程序

#include <stdio.h>

void main() {

int i, sum;

for(i = 1, sum = 0; i <= 100; sum += i,i++);

printf("sum = %d\n", sum);

}

程序 3_15.c 也是求 1+2+3+…+100 的值,其运行结果如图 3.23 所示。可以看到,在 for 语句中使用了逗号表达式,使得 for 语句非常简练。

有“;”,表示 for 语句没有 循环体语句。

逗号表达式

求解表达式 1

表达式 2

循环体语句组

求解表达式 3

循环语句的下 一语句

图 3.23 程序 3_15.c 的运行结果

从程序 3_15.c 可以看出,用逗号运算符可以将两个或两个以上的表达式连接起来,称为 逗号表达式,其一般形式如下:

表达式 1,表达式 2,…,表达式 n

逗号表达式的求解过程为:按照先后顺序,依次求解表达式 1,表达式 2,……,最后求 解表达式 n。并将最后求解的表达式 n 的值作为整个逗号表达式的值。如程序 3_15.c 中的:

i = 1, sum = 0;

先求解赋值表达式 i = 1,然后再求解表达式 sum = 0,并将表达式 sum = 0 的值作为整个 逗号表达式的值,所以该逗号表达式的值为 0。

从附录三可知,逗号运算符是所有运算符中级别最低的,所以“a = 3 * 5, a * 2”应理解成

“(a = 3 * 5), (a * 2)”而不是“a = (3 * 5, a * 2)”。在逗号表达式的子表达式可以是任意的表达 式,包括逗号表达式。如(a = 3 * 5, a * 2), a4。

逗号运算符并不只限于在 for 语句中使用。同时,需要引起注意的是,在定义时变量之间 的分隔符,以及在 printf()函数和 scanf()函数中一些分隔符不属于逗号运算符。如下面语句中 的“,”都不是逗号运算符。

int i, j, k;

printf("%d,%d,%d\n", i, j, k);

小提示:几种循环语句的比较

(1)while 语句、do…while 语句和 for 语句都可以用来处理同一问题,很多时候,它们 之间可以互换。

(2)在 while 和 do…while 语句中,只是在 while 后的括号里指定了循环条件,应该在循 环体内包含使循环能够正常结束的语句,避免出现死循环。而 for 语句在表达式 3 中含有使循 环趋于结束的操作,甚至可以将循环体中的操作全部放到表达式 3 中,因此 for 语句使用更为 灵活,功能更为强大。

(3)用 while 和 do…while 语句循环时,循环变量的赋初值应该在 while 和 do…while 语

(3)用 while 和 do…while 语句循环时,循环变量的赋初值应该在 while 和 do…while 语

相關文件