本文共 13814 字,大约阅读时间需要 46 分钟。
本节书摘来自异步社区《21天学通C语言(第7版)》一书中的第6章,第6.2节,作者 【美】Bradley Jones , Peter Aitken , Dean Miller,更多章节内容可以访问云栖社区“异步社区”公众号查看
21天学通C语言(第7版)
C程序默认的执行顺序是自上而下。从main()函数的起始位置开始,逐条执行语句,直至main()函数的末尾。然而,在实际的C程序中,很少严格按这样的顺序执行。C语言提供了各种程序控制语句,方便程序员控制程序的执行顺序。第4课介绍了一种程序控制语句——if语句,接下来介绍另外3种有用的控制语句:for语句;
while语句;do...while语句。for语句是由一条或多条语句组成的块。for语句有时也被称为for循环,因为程序会循环执行for语句多次。本书在前面的程序示例中使用过for语句。下面介绍for语句是如何工作的。
for语句的结构如下:
for ( 初值部分; 循环条件; 更新部分 ) 语句
初值部分、循环条件和更新部分都是C语言的表达式。语句可以是C语言的任意语句。程序执行到for语句时,将按以下步骤进行。
1.对初值部分求值。通常,初值部分是给变量设置特定值的赋值表达式。
2.对循环条件求值。通常,循环条件是关系表达式。
3.如果循环条件的求值结果为假(即,该表达式等于0),则for语句结束,并接着执行语句后面(即,跳过语句)的第1条语句。
4.如果循环条件的求值结果为真(即,该表达式等于非0),则执行for语句中的语句。
5.对更新部分求值。接着返回第2步继续执行。
图6.1清楚地演示了执行for语句的过程。注意,如果第1次对循环条件求值为假,则直接结束for语句,完全不执行其中的语句。
图6.1 for语句的原理图
程序清单6.1是一个简单的示例,用for语句打印数字1~20。读者会发现,使用for语句的代码比使用20个printf()语句打印20个值的代码要紧凑得多。
输入
程序清单6.1 forstate.c:简单的for语句1: /* 简单的for语句示例 */2: 3: #include4: #define MAXCOUNT 205: int count;6: 7: int main(void)8: {9: /* 打印数字1~20 */10: 11: for (count = 1; count <= MAXCOUNT; count++)12: printf("%d\n", count);13: 14: return 0;15: }
输出
1234567891011121314151617181920
图6.2演示了程序清单6.1中执行for循环的过程。
图6.2 程序清单6.1中执行for循环的过程
分析
第3行是标准输入/输出头文件。第5行声明了一个int类型的变量count,将用于for循环。第11行和第12行是for循环。程序执行到for语句时,首先对初值部分求值。在本例中,初值部分是count = 1。必须先初始化count或为其赋值,才能在for语句中使用它。接着对for语句中的循环条件(count <= 20)求值。因为count被赋值为1(count小于20),所以执行for语句中的printf()函数。执行完printf()函数后,对更新部分(count++)求值,把count递增1,其值为2。现在,程序回到循环条件,并再次检查循环条件。如果循环条件为真,则再次执行printf(),然后把count递增1(此时count的值为3)。接着再次检查循环条件。这一过程将一直循环下去,直至循环条件的求值结果为假。当循环条件的求值结果为假时,程序将退出循环,并继续执行第14行。该行在结束程序之前返回0。
for语句频繁用于“向上计数”,将计数器变量的值递增1成为另一个值,如上例所示。也可以用for语句来“向下计数”,将计数器变量递减1,如下所示:
for (count = 100; count > 0; count--)
递增量或递减量不一定是1,如下所示,每次循环把count递增5:
for (count = 0; count < 1000; count += 5)
for语句非常灵活。例如,如果程序前面已经初始化了待测试的变量或者已给待测试变量赋值,便可省略初值部分,如下所示。但是,不能省略初值部分后面的分号分隔符。
count = 1; for ( ; count < 1000; count++)
初值部分可以是任意有效的C表达式,只会在程序运行至for语句时被执行一次。如下代码所示,Now sorting the array...只会被打印一次:
count = 1; for (printf("Now sorting the array..."); count < 1000; count++) /* 排序语句已省略 */
如果把更新的步骤放在for语句体中,更新部分也可以省略。例如,要打印数字0至99,可以这样写:
for (count = 0; count < 100; ) printf("%d", count++);
用于判断是否终止循环的循环条件也可以是任意C表达式。只要它的求值结果为真(非零),for语句会一直执行下去。用C语言的逻辑运算符可以构建复杂的循环条件。例如,下面的for语句打印数组array[]中的元素,在打印完所有元素后或元素的值为0时,将停止打印:
for (count = 0; count < 1000 && array[count] != 0; count++) printf("%d", array[count]);
可以进一步简化该for循环,如下所示(如果不理解这样的循环条件,请复习第4课的内容)。
for (count = 0; count < 1000 && array[count]; ) printf("%d", array[count++]);
在for语句中可以使用空语句(null statement)。记住,空语句指的是分号独占一行。如果要把数组中的1000个元素都赋值为50,可以这样写:
for (count = 0; count < 1000; array[count++] = 50) ;
该for语句把给数组中每个元素赋值50的操作放在更新部分。如果像下面这样写更好:
for (count = 0; count < 1000; array[count++] = 50) { ; }
将分号放在块中(即,花括号中),突出for语句体中不执行任何工作的意图。
第4课介绍过,逗号运算符常用于for语句中。可以创建一个表达式,用逗号运算符分隔两个子表达式。按照从左至右的顺序,依次对两个子表达式被求值,整个表达式的值是右边子表达式的值。使用逗号运算符,可以让for语句的每个部分都完成多个任务。
假设有两个各包含1000个元素的数组a[]和b[]。如果想把a[]中的内容倒序拷贝给b[](即完成拷贝操作后,b[0] = a[999]、b[1] = a[998],以此类推),可以使用下面的for语句:
for (i = 0, j = 999; i < 1000; i++, j--) b[j] = a[i];
逗号运算符分隔了两个子赋值表达式,分别将0和999赋值给变量i和j,然后在每次循环时分别递增两个变量。
语法
for语句
for ( 初值部分; 循环条件; 更新部分 ) 语句;
初值部分是任意有效的C表达式。通常是将变量设置为特定值的赋值表达式。
循环条件是任意有效的C表达式。通常是关系表达式。循环条件的值为假(0)时,结束for语句,并执行语句后面的第1条语句;循环条件的值为真(非0)时,执行语句中的C语句。
更新部分是任意有效的C表达式。通常是递增或递减变量(已初始化的变量)的表达式。
语句是任意的C语句,只要循环条件为真,就执行该部分的语句。
for语句是一个循环语句。语句头包括初值部分、循环条件和更新部分。for语句首先执行初值部分,然后检查循环条件。如果循环条件为真,则执行语句。执行完语句后,对更新部分求值。然后,for语句再次检查循环条件,确认是否继续循环。
示例1
/* 打印0至9的值 */int x;for (x = 0; x < 10; x++) printf( "\nThe value of x is %d", x );``` 示例2
/ 获取用户输入的数字,除非用户输入99 /
int nbr = 0;for ( ; nbr != 99; )scanf( "%d", &nbr );
示例3
/ 提示用户输入10个整型值 /
/ 将用户输入的值储存在value数组中 // 如果用户输入的数是99,则停止循环 /int value[10];int ctr, nbr = 0;for (ctr = 0; ctr < 10 && nbr != 99; ctr++){puts("Enter a number, 99 to quit ");scanf("%d", & nbr);value[ctr] = nbr;
}
###6.2.2 嵌套for语句在一个for语句中执行另一个for语句,称为嵌套(在第4课中介绍过嵌套if语句)。利用嵌套的for语句,可以完成一些复杂的程序设计。程序清单6.2不是一个复杂的程序,但是它演示了如何嵌套for语句。输入下三角程序清单6.2 nestfor.c:嵌套的for语句
1: // 嵌套for循环的程序示例
2: 3: #include 4: void print_ttable(int outer, int inner);5: 6: main()7: { 8: int inner = 10;9: int outer = 10;10: 11: printf("The times table:n");12: print_ttable(outer, inner);13: return(0);14: }15: 16: void print_ttable(int outer, int inner)17: { 18: int a, b;19: for (a = 1; a <= outer; a++)20: { 21: for (b = 1; b <= inner; b++)22: { 23: printf("%dt", a*b);24: }25: printf("n");26: }27: return;28: }输出![_](https://yqfile.alicdn.com/7fde54254c8065236562755adec90d75c433e754.png)
The times table:
1 2 3 4 5 6 7 8 9 102 4 6 8 10 12 14 16 18 203 6 9 12 15 18 21 24 27 304 8 12 16 20 24 28 32 36 405 10 15 20 25 30 35 40 45 506 12 18 24 30 36 42 48 54 607 14 21 28 35 42 49 46 63 708 16 24 32 40 48 56 64 72 809 18 27 36 45 54 63 72 81 9010 20 30 40 50 60 70 80 90 100分析![_](https://yqfile.alicdn.com/7fde54254c8065236562755adec90d75c433e754.png)是否还记得小学必须背诵的乘法表1?现在,使用C语言和嵌套循环,可以轻松地将它们打印出来。最初先设置10×10的表,可以通过更改这些数字让乘法表更小或更大(循环的代码不会因此减少或增多)。因此,可以创建10×5或12×9的表,但是,如果数字太大,一行容纳的数字过多会影响布局的美观。无论如何,现在先来分析程序的细节。在程序清单6.2中,第4行声明了print_ttable()的函数原型。该函数需要两个int类型的变量outer和inner,储存乘法表显示的尺寸。第12行,在main()调用print_ttable()并传递outer变量和inner变量。对于print_ttable()函数,有两点读者可能不太明白。第一,为什么要声明局部变量a和b?第二,为什么要在第25行再次使用printf()函数?仔细分析循环就会明白。第19行开始外层(第1个)for循环。循环开始时,将变量a赋值为1,因为a小于outer(outer的值是10),所以程序继续执行到第21行。查看循环条件发现,在a大于outer之前,将一直执行这个for循环。第21行是内层(第2个)for语句。这里要用到第2个局部变量b,同样为其赋值为1,并与传递给print_ttable()函数的第2个变量inner作比较。因为b小于inner(inner的值是10),所以程序执行到第23行,打印a*b的值和一个制表符(\t,告诉C编译器向后移一个制表单位)。在计算结果后面添加制表符,这样打印出的表格式比较美观(表格中的数字之间有一定的空白),如程序示例的输出所示。然后递增b,继续执行内层的for循环。当b的值递增为11时,内层循环结束。控制转到第25行,在屏幕上另起一行开始打印(printf()函数的相关内容将在第7课中详细介绍)。然后,程序执行到外层for循环的末端,因此回到第19行对更新部分求值,此时a的值为2(递增了1)。然后对该行的循环条件求值,因为a仍小于outer,循环条件为真,所以转到执行第21行。注意,此时b的值被重新赋值为1。如果b还保留原来的值(11),b的值大于10,则该行的循环条件为假,就只会打印乘法表的第1行。###6.2.3 while语句while语句(也称为while循环)不断执行一个语句块,直至指定的循环条件为假。while语句的格式如下:
while (循环条件)
语句
循环条件是任意的C表达式,语句是任意有效的C语句。程序执行到while语句时,将进行以下过程。1.对循环条件求值。2.如果循环条件为假(0),则结束while语句,程序将转至执行语句后面的第1条语句。3.如果循环条件为真(非0),则执行语句中的C语句。4.执行将返回第1步。while语句的运行过程如图6.3所示。图6.3 while语句的运行过程程序清单6.3使用了一个while语句打印1~20(与程序清单6.1使用for语句完成的任务相同)。输入![_](https://yqfile.alicdn.com/7fde54254c8065236562755adec90d75c433e754.png)程序清单6.3whilest.c:简单的while语句
1: // while语句的简单示例
2: 3: #include 4: #define MAXCOUNT 205: int count;6: 7: int main(void)8: { 9: // 打印数字1~2010: 11: count = 1;12: 13: while (count <= MAXCOUNT)14: { 15: printf("%dn", count);16: count++;17: }18: return 0;19: }输出![_](https://yqfile.alicdn.com/7fde54254c8065236562755adec90d75c433e754.png)
1
234567891011121314151617181920分析![_](https://yqfile.alicdn.com/7fde54254c8065236562755adec90d75c433e754.png)程序清单6.3与程序清单6.1完成的任务相同。第11行,把1赋值给count。因为while语句没有初始化变量或给变量赋值的部分,所以必须在while循环之前完成初始化或赋值工作。第13行是while语句,其中包含的循环条件(count <= 20)与程序清单6.1中for语句的循环条件相同。在while循环中,第16行将count递增1。如果遗漏了第16行会发生什么情况?此时,由于count始终为1(小于20),程序将一直循环下去不会停止。注意,while语句实际上是没有初值部分和循环条件的for语句,因此,
for ( ; 循环条件 ; )
相当于
while (循环条件)
因此,在for语句中完成的任何工作都能在while语句中完成。使用while语句时,必须在while语句前面完成必要的初始化或赋值工作,而且必须将更新变量值的部分放进while循环体中。警告记得在while循环内部的代码块中改变循环条件的值,否则该循环将成为一个无限循环。这是新手程序员(甚至经验丰富的程序员)常犯的错误。如果需要初始化和更新变量,大部分经验丰富的C语言程序员都更倾向于使用for语句而不是while语句。这是基于源代码的可读性做出的选择。使用for语句时,初值部分、循环条件和更新部分都放在一起,便于阅读和修改;而使用while语句,初始化部分和更新变量部分位于不同的地方,不方便查找。语 法while语句
while (循环条件)
语句
循环条件是任意有效的C表达式,通常是一个关系表达式。循环条件的值为假(0)时,结束while语句,并执行语句后面的第1条语句;循环条件的值为真(非0)时,执行语句中的C语句。语句是任意的C语句,只要循环条件为真,就执行该部分的语句。while语句是一个循环语句。只要循环条件为真(非0),就重复执行语句块中的语句。如果循环条件为假,则完全不执行(一次也不执行)语句。示例1
int x = 0;
while (x < 10){ printf("\nThe value of x is %d", x ); x++;}
示例2
/ 获取数字,直至输入的数字是99 /
int nbr = 0;while (nbr <= 99) scanf("%d", &nbr );
示例3
/ 提示用户输入10个整型数 /
/* 将用户输入的值储存在value数组中 *//* 如果用户输入的数是99,则停止循环 */int value[10];int ctr = 0;int nbr;while (ctr < 10 && nbr != 99){ puts("Enter a number, 99 to quit "); scanf("%d", &nbr); value[ctr] = nbr; ctr++;}
###6.2.4 嵌套while语句与for语句和if语句类似,while语句也可以嵌套使用。程序清单6.4是一个使用嵌套while语句的示例。虽然这不是使用while语句的最好示例,但是该例提供了一些新的思路。输入![_](https://yqfile.alicdn.com/7fde54254c8065236562755adec90d75c433e754.png)程序清单6.4nestwhile.c:嵌套的while语句
1: / 嵌套while语句示例 /
2: 3: #include 4: 5: int array[5];6: 7: int main(void)8: { 9: int ctr = 0,10: nbr = 0;11: 12: printf("This program prompts you to enter 5 numbersn");13: printf("Each number should be from 1 to 10n");14: 15: while (ctr < 5)16: { 17: nbr = 0;18: while (nbr < 1 || nbr > 10)19: { 20: printf("nEnter number %d of 5: ", ctr + 1);21: scanf("%d", &nbr);22: }23: 24: array[ctr] = nbr;25: ctr++;26: }27: 28: for (ctr = 0; ctr < 5; ctr++)29: printf("Value %d is %dn", ctr + 1, array[ctr]);30: 31: return 0;32: }输出![_](https://yqfile.alicdn.com/7fde54254c8065236562755adec90d75c433e754.png)
This program prompts you to enter 5 numbers
Each number should be from 1 to 10Enter number 1 of 5: 3Enter number 2 of 5: 6Enter number 3 of 5: 3Enter number 4 of 5: 9Enter number 5 of 5: 2Value 1 is 3Value 2 is 6Value 3 is 3Value 4 is 9Value 5 is 2分析![_](https://yqfile.alicdn.com/7fde54254c8065236562755adec90d75c433e754.png)与前面的程序清单相同,第1行的注释描述了该程序的用途。第3行是#include指令,用于包含标准输入/输出头文件。第5行声明一个可储存5个整型值的数组array。main()函数中声明了两个局部变量ctr和nbr(第9行和第10行)。注意,这两个变量在声明的同时已初始化为0。另外,第9行将逗号运算符用作分隔符,这样便不用重复使用int关键字将nbr声明为int类型。许多C语言的程序员都习惯用这种方式来声明。第12行和第13行打印该程序的信息和提示用户输入数字。第15~26行是第1个(外层)while语句。第18~22行是嵌套的while语句,它也是外层while语句的一部分。如果ctr小于5(第15行),就一直执行外层while循环。只要ctr小于5,第17行都将nbr设置为0,第18~22行(嵌套的while语句)提示用户输入一个数字,以获取nbr变量中的值。第24行将获取的数字放入array数组中,第25行把ctr递增1。然后再次循环,回到第15行。因此,外层循环获取5个数字并放入array数组中,该数组以ctr作为索引。内层循环(第18~22行)很好地利用了while语句的特点,保证了用户输入的数字有效(该例中,只有数字1~10是有效的)才会继续执行程序中的语句。内层while语句的意思是,如果nbr小于1或大于10,就打印一条消息提示用户输入一个有效的数字,然后获取该数字。第28行和第29行打印储存在array数组中的值。注意,因为while语句中使用ctr变量来完成循环,所以for语句也可以复用该变量。ctr从0开始,每次循环递增1,for语句一共循环5次。打印ctr加1的值(因为count从0开始),并打印array数组中相应的值(索引为ctr)。另外,读者可以改动程序中的两处,作为额外的练习。一处是程序接收的值,将1~10改成1~100;另一处是改变程序接收值的数量,该例只能接收5个数字,读者可以尝试改成接收10个数字。###6.2.5 do...while循环C语言提供的第3个循环是do...while循环,只要循环条件为真,便不断执行一个语句块。do...while循环在循环底部测试循环条件,而for循环和while循环则在循环的顶部进行测试。do...while循环的结构如下: do 语句 while (循环条件);循环条件是任意的C表达式,语句是任意的C语句。当程序执行到do...while语句时,将进行以下步骤。1.执行语句中的语句。2.对循环条件求值。如果结果为真,执行将回到第1步。如果结果为假,则结束循环。do...while循环的执行过程如图6.4所示。图6.4 do...while循环的运行过程do...while循环中的语句至少会被执行一次。这是因为do...while在底部测试循环条件,而非顶部。而for循环和while循环都是在循环的顶部对循环条件求值,所以对于这两个循环,如果循环条件的结果为假,则完全不会执行循环体中的语句。do...while循环没有while循环和for循环使用频繁。只有在循环体中的语句要至少被执行一次,才会使用do...while循环。当然,如果能确保在第1次执行到while循环时,其循环条件为真,也可以在while循环中完成相同的任务。但是,使用do...while循环更加简单明了。程序清单6.5是do...while循环的示例。输入![_](https://yqfile.alicdn.com/7fde54254c8065236562755adec90d75c433e754.png)程序清单6.5dowhilestate.c:简单的while语句
1: / 简单的do...while语句示例 /
2: 3: #include 4: 5: int get_menu_choice(void);6: 7: int main(void)8: { 9: int choice;10: 11: choice = get_menu_choice();12: 13: printf("You chose Menu Option %dn", choice);14: 15: return 0;16: }17: 18: int get_menu_choice(void)19: { 20: int selection = 0;21: 22: do23: { 24: printf("n");25: printf("n1 - Add a Record");26: printf("n2 - Change a record");27: printf("n3 - Delete a record");28: printf("n4 - Quit");29: printf("n");30: printf("nEnter a selection: ");31: 32: scanf("%d", &selection);33: 34: } while (selection < 1 || selection > 4);35: 36: return selection;37: }输出![_](https://yqfile.alicdn.com/7fde54254c8065236562755adec90d75c433e754.png)
1 - Add a Record
2 - Change a record3 - Delete a record4 - QuitEnter a selection: 81 - Add a Record2 - Change a record3 - Delete a record4 - QuitEnter a selection: 4You chose Menu Option 4分析![_](https://yqfile.alicdn.com/7fde54254c8065236562755adec90d75c433e754.png)该程序提供了一个带有4个选项的菜单,用户可以选择其中一个。然后,程序将打印用户选择的数字。现在,读者应该能理解该程序清单中的大部分内容,本书在后面将会扩展这个程序。main()函数(第7~16行)中的内容在前面都介绍过。注意main()函数体中的代码(第9~13行)可写成一行,如下所示:
printf( "You chose Menu Option %d", get_menu_option() );
如果你打算扩展该程序,并根据用户选择的选项执行相应的操作,就会用到get_menu_choice()的返回值,因此将其赋给一个变量(如本例中的chioce)是明智之举。第18~37行是get_menu_choice()函数,该函数在屏幕上显示一个菜单(第24~30行),然后获取用户输入的选项。因为至少要在屏幕上显示一次菜单,用户才能据此输入选择的数字,所以在这种情况下使用do...while循环很合适。该程序会一直显示菜单,直至用户输入有效的选项。第34行是do...while语句中的while部分,用于确保用户输入数字的有效性,因此将其使用的变量命名为selection很合适。如果用户输入的值不在1~4之间,将重复显示菜单,并提示用户输入新的值。当用户输入了有效的选项,程序将继续执行至第36行,返回selection变量的值。语 法do...while语句
{
语句
}while (循环条件)
循环条件是任意有效的C表达式,通常是一个关系表达式。循环条件的值为假(0)时,结束while语句,并执行while语句后面的第1条语句;循环条件的值为真(非0)时,程序回到do部分,执行语句部分的C语句。语句是任意的C语句。程序首次执行到do...while循环时,将执行语句,然后只要循环条件为真,就会再次执行该部分的语句。do...while语句是一个循环语句。只要循环条件为真(非0),便会重复执行其中的语句或语句块。与while语句不同,do...while语句至少要执行语句一次。示例1
/ 即使循环条件为假,也会打印一次! /
int x = 10;do{printf("\nThe value of x is %d", x );
}while (x != 10);
示例2
/ 获取用户键入的数字,除非用户输入的值大于99 /
int nbr;do{scanf("%d", &nbr );
}while (nbr <= 99);
示例3
/ 提示用户输入10个整型值 /
/ 将用户输入的值储存在value数组中 // 如果用户输入的数是99,则停止循环 /int value[10];int ctr = 0;int nbr;do{puts("Enter a number, 99 to quit ");scanf( "%d", &nbr);value[ctr] = nbr;ctr++;
}while (ctr < 10 && nbr != 99);ch
转载地址:http://etaal.baihongyu.com/