一,深入while循环
-
#include <stdio.h>
int main(void)
{
long num;
long sum = 0L;
int status;
printf("Please enter an integer to be summed ");
printf("(q to quit):\n");
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;
}
1,程序注释
-
status == 1
- ==运算符是C的相等运算符,该表达式判断status是否等于1。
-
scanf()
- scanf()返回成功读取项的数量。如果scanf()成功读取一个整数,就把该数存入num并返回1,随后返回值将被赋给status。如果用户输入的不是数字,scanf()会读取失败并返回0.此时,status的值就是0,循环结束。
- 如果scanf()在转换之前出了问题(如:检测到文件结尾或遇到硬件问题),会返回一个特殊值EOF(其值通常被定义为**-1**)。这个值也会引起循环终止。
-
伪代码
-
每次循环都被称为一次迭代(iteration)
2,观察下面程序输出并分析
-
#include <stdio.h>
int main(void) {
int n = 0;
while (n++ < 3)
printf("n is %d\n",n);
printf("That's all this program does.\n");
return 0;
}
-
#include <stdio.h>
int main(void) {
int n = 0;
while (n++ < 3);
printf("n is %d\n",n);
printf("That's all this program does.\n");
return 0;
}
-
#include <stdio.h>
int main(void) {
int n = 0;
while (n++ < 3)
{
printf("n is %d\n", n);
printf("That's all this program does.\n");
}
return 0;
}
-
while语句本身使用复合语句,在语句构成上,它也是一条单独的语句。该语句从while开始执行,到第1个分号结束。在使用了复合语句的情况下,到右花括号结束。
二,用关系运算符和表达式比较大小
-
while循环经常依赖测试表达式作比较,这样的表达式被称为关系表达式(relational expression),出现在关系表达式中间的运算符叫做关系运算符(relational operator)。C语言中的所有关系运算符如下:
-
运算符 | 含义 |
---|
<
<
< | 小于 |
<
=
<=
<= | 小于或等于 |
=
=
==
== | 等于 |
>
=
>=
>= | 大于或等于 |
>
>
> | 大于 |
!
=
!=
!= | 不等于 |
-
虽然关系运算符可用来比较浮点数,但是要注意:比较浮点数时,尽量只使用**<和>**。因为浮点数的舍入误差会导致在逻辑上应该相等的两数却不相等。 -
使用fabs()函数(声明在math.h头文件中)可以方便地比较浮点数,该函数返回一个浮点值的绝对值。
-
#include <stdio.h>
#include <math.h>
int main(void)
{
const double ANSWER = 3.14159;
double response;
printf("What is the value of pi?\n");
scanf("%lf",&response);
while (fabs(response - ANSWER) > 0.0001)
{
printf("Try again!\n");
scanf("%lf",&response);
}
printf("Close enough!\n");
return 0;
}
1,什么是真
-
#include <stdio.h>
int main(void)
{
int true_val,false_val;
true_val = (10 > 2);
false_val = (10 == 2);
printf("true = %d; false = %d",true_val,false_val);
return 0;
}
-
一些C程序使用下面的循环结构,由于1为真,所以循环会一直进行。
-
一般而言,所有的非零值都视为真,只有0被视为假。只要测试条件的值为非零,就会执行while循环。
2,_Bool类型
-
C99新增了**_Bool类型,表示真或假的变量被称为布尔变量**(Boolean variable)。 -
_Bool类型的变量只能存储1(真)或0(假)。如果把其他非零数值赋给布尔类型的变量,该变量会被设置为1。 -
#include <stdio.h>
int main(void)
{
long num;
long sum = 0L;
_Bool input_is_good;
printf("Please enter an integer to be summed ");
printf("(q to quit):");
input_is_good = (scanf("%ld",&num) == 1);
while (input_is_good)
{
sum = sum +num;
printf("Please enter next integer (q to quit):");
input_is_good = (scanf("%ld",&num) == 1);
}
printf("Those integers sum to %ld.\n", sum);
return 0;
}
- C99提供了stdbool.h头文件,该头文件让bool成为**_Bool的别名,而且把true和false分别定义为1和0**的符号常量。包含该头文件后,写出的代码可以与C++兼容。
- 如果系统不支持布尔类型,导致无法运行该程序,可以把布尔替换成int即可。
3,优先级和关系运算符
三,不确定循环和计数循环
- 不确定循环(indefinite loop),指在测试表达式为假之前,预先不知道要执行多少次循环。如前面用户输入数字计算示例,不知用户何时结束。
- 计数循环(counting loop),这类循环在执行循环之前就知道要重复执行多少次。
四,for循环
五,逗号运算符
-
逗号运算符扩展了for循环的灵活性,以便在循环头中包含更多的表达式。 -
#include <stdio.h>
int main(void)
{
const int FIRST_OZ = 46;
const int NEXT_OZ = 20;
int ounces,cost;
printf("ounces cost\n");
for (ounces = 1,cost = FIRST_OZ;ounces<=16;ounces++,cost+=NEXT_OZ)
printf("%5d $%4.2f\n",ounces,cost / 100.0);
return 0;
}
-
其次,逗号也可用作分隔符。在下面语句中的逗号都是分隔符,不是逗号运算符。
六,出口条件循环:do while
-
出口条件循环(exit-condition loop),即在循环的每次迭代之后检查测试条件,保证了至少执行循环体中的内容一次。 -
#include <stdio.h>
int main(void)
{
const int secret_code = 13;
int code_entered;
do
{
printf("To enter the triskaidekaphobia therapy club,\n");
printf("please enter the secret code number: ");
scanf("%d",&code_entered);
}while (code_entered!=secret_code);
printf("Congratulations! You are cured!\n");
return 0;
}
1,do while格式
七,如何选择循环
-
首先确定需要入口条件循环还是出口条件循环。一般而言入口条件循环用得比较多。 -
当循环涉及初始化和更新变量时,用for循环比较合适,而在其他情况下用while循环更好。例如:
-
对于涉及索引计数的循环,用for循环更适合。例如:
八,嵌套循环
-
嵌套循环(nested loop)指在一个循环内包含另一个循环。嵌套循环常用于按行和列显示数据。 -
#include <stdio.h>
#define ROWS 6
#define CHARS 10
int main(void)
{
int row;
char ch;
for (row = 0; row < ROWS; row++)
{
for (ch = 'A'; ch < ('A' + CHARS); ch++)
printf("%c", ch);
printf("\n");
}
return 0;
}
-
嵌套循环中的内层循环在每次外层循环迭代时都执行完所有的循环。
九,数组
-
数组可以作为一种存储多个相关项的便利方式。 -
数组(array)是按照顺序存储的一系列类型相同的值,整个数组有一个数组名,通过整数下标访问数组中单独的项或元素(element)。如,以下声明:
-
考虑到影响执行的速度,C编译器不会检查数组的下标是否正确。下面的代码,都不正确。
-
数组的类型可以是任意数据类型。 -
如果char类型的数组末尾包含一个表示字符串末尾的空字符**\0**,则该数组中的内容就构成了一个字符串。 -
用于识别数组元素的数字被称为下标(subscript),索引(index)或偏移量(offset)。下标必须是整数,而且要从0开始计数。数组的元素被依次存储在内存中相邻的位置。
1,在for循环中使用数组
-
#include <stdio.h>
#define SIZE 10
#define PAR 72
int main(void)
{
int index,score[SIZE];
int sum = 0;
float average;
printf("Enter %d golf scores:\n",SIZE);
for (index = 0;index<SIZE;index++)
scanf("%d",&score[index]);
printf("The scores read in are as follows:\n");
for (index = 0;index < SIZE;index++)
printf("%5d",score[index]);
printf("\n");
for (index = 0; index < SIZE;index++)
sum += score[index];
average = (float) sum / SIZE;
printf("Sum of scores = %d, average = %.2f\n",sum,average);
printf("That's a handicap of %.0f\n",average - PAR);
return 0;
}
- 注意,int类型数组元素的用法与int类型变量的用法类似。要读取int类型变量fue,应该这样写
scanf("%d",&fue) 。上面程序是因为要读取int类型的元素score[index] ,所以写成scanf("%d",&score[index]) 。
2,使用函数返回值的循环示例
-
编写有返回值的函数,要完成以下内容。
- 定义函数时,确定函数的返回类型。
- 使用关键字return表明待返回的值。
-
#include <stdio.h>
double power(double n,int p);
int main(void)
{
double x,xpow;
int exp;
printf("Enter a number and the positive integer power");
printf("to which\n the number will be raised. Enter q");
printf(" to quit.\n");
while (scanf("%lf%d", &x,&exp) == 2)
{
xpow = power(x , exp);
printf("%.3g to the power %d is %.5g\n",x,exp,xpow);
printf("Enter next pair of numbers or q to quit.\n");
}
printf("Hope you enjoyed this power trip -- bye!\n");
return 0;
}
double power(double n,int p)
{
double pow = 1;
int i;
for (i = 1;i <= p; i++)
pow *= n;
return pow;
}
-
**power()**函数在程序中出现了3次。首次出现是:
-
第二次出现:
-
xpow = power(x,exp);
- 程序调用power(),把两个值传递给它。该函数计算x的exp次幂,并把计算结果返回给主调函数。在主调函数中,返回值将被赋给变量xpow。
-
第三次出现:
-
为什么在使用scanf()的返回值之前没有声明scanf()?为什么在定义中说明power()的返回类型为double,还要单独声明这个函数?
- 编译器在程序中首次遇到power()时,需要知道power()的返回类型。此时,编译器尚未执行到power()的定义,并不知道函数定义中的返回类型是double。因此,必须通过前置声明预先说明函数的返回类型。前置声明告诉编译器,power()定义在别处,其返回类型为double。如果把power()函数的定义置于main()的文件顶部,就可以省略前置声明,因为编译器在执行到main()之前已经知道power()的所有信息。但是,这不是C的标准风格。因为**main()通常只提供整个程序的框架,做好把main()**放在所有函数定义的前面。另外,通常把函数放在其他文件中,所以前置声明必不可少。
- stdio.h头文件中已经包含了scanf(),printf()和其他I/O函数的原型。
|