暑假期间继续写博客。
全书共分17章,这是关于本书第6章内容的博客,本章主要介绍了循环语句,还介绍了一些运算符,也介绍了后面函数的数组的一些内容。博客的目录和书上目录是相似的。此系列博客的代码都在Visual Studio 2022环境下编译运行。
我目前大一刚刚结束,水平有限,博客中若有错误或者总结不到位的地方也请见谅。
目录
6.1 再探while循环
6.2 while语句
6.2.1 终止while循环
6.2.2 何时终止循环
6.2.3 while:入口条件循环
6.2.4 语法要点
6.3 用关系运算符和表达式比较大小
6.3.1 什么是真
6.3.2 其他真值
6.3.3 真值的问题
6.3.4 新的_Bool类型
6.3.5 优先级和关系运算符
6.4 不确定循环和计数循环
6.5 for循环
6.6 其他赋值运算符:+=、-=、*=、/=、%=
6.7 逗号运算符
6.8 出口条件循环:do while
6.9 如何选择循环
6.10 嵌套循环
6.11 数组简介
6.12 使用函数返回值的循环示例
下面是使用while循环的示例,该程序计算输入数字的和,在输入非数字时结束循环。
#include
int main(void)
{
long num;
long sum = 0L;
int status;
printf("Please enter an integar to be summed ");
printf("(q to quit):");
status = scanf("%ld", &num);
while (status = 1) {
sum = sum + num;
printf("Please enter next integar (q to quit):");
status = scanf("%ld", &num);
}
printf("Those integars sum to %ld\n", sum);
return 0;
}
==运算符是C语言的相等运算符,判断两侧值是否相等。
伪代码是用简单的句子表示程序思路的方法。伪代码有助于设计程序的逻辑。
while循环的通用形式是:
while ( expression )
statement
statement可以是分号结尾的一条语句,也可以是用花括号括起来的复合语句。
如果expression为真,执行statement部分一次,然后再次判断expression,在expression为假之前重复进行循环的判断和执行。每次循环称为一次迭代。
构建while循环时,如果表达式的值无法为假,则循环不会终止(在不使用break的情况下)。
只有在对测试条件求值时,才决定是终止还是继续循环。
while循环必须满足表达式的条件才能进入循环体,这是入口条件循环。
只有在测试条件后面的单独语句(简单语句或复合语句)才是循环部分。循环从while开始执行,到第1个分号结束,使用复合语句到右花括号结束。
如果在测试条件就完成了循环的任务,循环体就可以使用空语句。这种情况下最好让分号独占一行。
关系运算符可以用来比较数值(整数、浮点数、字符都可),但是不能用于比较字符串。比较浮点数时尽量只使用<和>,因为浮点数有舍入误差可能导致逻辑相等的两数不相等。
对C语言而言,表达式为真的值是1,表达式为假的值为0。
所有的非零值都为真,只有0是假。
关系表达式为真,值为1,关系表达式值为假,值为0。
不要混淆=和==。
C99新增了_Bool类型。编程中,表示真或假的变量被称为布尔变量。_Bool类型的变量只能存储1(真)或0(假)。如果将其他非负值赋给_Bool类型变量,该变量会被置为1。
C99提供了stdbool.h头文件。该头文件让bool成为_Bool的别名,而且把true和false分别定义为1和0的符号常量。
关系运算符的优先级比算术运算符低,比赋值运算符高。关系运算符中,> >= < <=这四个比==和!=高。
关系运算符的结合律也是从左向右。
一些while循环是不确定循环,这类循环在测试表达式为假前预先不知道要执行多少次循环。
一些while循环是计数循环,预先知道会执行多少次。
重复执行固定次数的循环需要先初始化计数器,然后将计数器与有限的值进行比较,并且每次循环时递增计数器。
for循环把初始化,比较和更新组合在一处。
下面是使用for循环的示例,该程序计算并输出1-6的立方。
#include
int main(void)
{
int num;
printf(" n n cubed\n");
for (num = 1; num <= 6; num++)
printf("%5d %5d\n", num, num * num * num);
return 0;
}
for循环的形式是:
for( initialize; test; update )
statement
先执行initialize(只会在这里执行一次),然后对test求值,如果表达式为真,则执行循环一次,接着对update求值,并再次检查test是否为真,在test为假前重复进行先statement后update的循环。
for循环是入口条件循环。statement可以是简单语句或复合语句。
for循环可以省略圆括号内三个表达式的一个或多个,但是不能省略分号。
这些赋值运算符也可用于更新变量,用法都是左侧是一个变量名,右侧是一个表达式,赋给变量的值是根据右侧表达式调整后的值。
+=把右侧的值加到左侧的变量上。-=从左侧的变量中减去右侧的值。*=把左侧的变量乘以右侧的值。/=把左侧的变量除以右侧的值。%=将左侧变量的值赋为左侧除以右侧值后得到的余数。
这些赋值运算符的优先级和=相同。
这些赋值运算符让代码更紧凑,可以生成更高效的机器代码。
逗号运算符用逗号分隔表达式,对被分隔的表达式从左向右求值(逗号是一个序列点)。整个逗号表达式的值是最右侧表达式的值。
while循环和for循环都是入口条件循环,可能不会执行循环体的内容。
C语言还有出口条件循环,循环在每次迭代后检查测试条件,可以执行循环体的内容至少一次。
下面是一个示例,要求用户输入数字直至输入13为止。
#include
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;
}
do while循环是出口条件循环,通用形式是:
do
statement
while( expression );
do while循环在expression为假之前重复执行循环体的内容。
statement可以是一条简单语句或复合语句。do while循环以分号结尾。
通常情况下入口条件循环用得多,因为一般原则下执行循环之前测试条件比较好,很多情况下要求一开始不满足条件就直接跳过循环,并且可读性更高。
入口条件循环for循环和while循环都可,如果循环涉及初始化和更新变量,用for循环更合适,其他情况下用while循环更好。
嵌套循环是指一个循环内包含另一个循环。
数组是按顺序存储的一系列类型相同的值。数组有数组名,通过整数下标便可访问单独的项或元素(数组名[下标值])。数组下标从0开始(不是从1开始),最大值是数组元素总个数-1。
C编译器不会检查下标是否越界,下标越界会导致数据被放在其他地方,可能导致程序异常中断。
使用循环可以较好地处理数组。
程序能重复显示刚读入的数据是一个很好的编程习惯,有利于确保处理的数据与期望相符。
程序设计时要注意模块化的原则,要把程序分为一些独立单元,每个单元执行一个任务,这样不仅可以提高程序的可读性,还可以方便后续更新或修改程序。可以通过函数(后面第9章内容)提高模块化。
数组在第10章会详细介绍。
该程序可以计算乘方。
#include
double power(double n, int p);
int main(void)
{
double x, xpow;
int exp;
printf("Enter a number and the positive integar power");
printf("to which\nthe 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;
}
用于测试函数的程序是驱动程序。
一般自定义函数在程序中出现三次:函数声明,函数调用,函数定义。
函数声明的格式是
返回类型 函数名(定义形参);
函数声明告诉编译器函数返回值类型。
如果函数定义在函数调用上面,就可以省略函数声明,因为编译器已经知道函数的所有信息。但是因为程序一般从main()函数开始,最好把main()函数放最上面。如果函数在不同源文件中,函数声明必不可少。
函数调用的格式是:函数名(实参)。如果左侧用=连接,会把返回值赋给左侧变量。函数最后用return 进行返回,返回return右侧表达式的值。
函数定义的格式是
返回类型 函数名(定义形参)
{
具体语句
}