1.1while循环
/*summing.c --根据用户的输入求和*/
#include <stdio.h>
int main()
{
long num;
long sum = 0L; //将sum初始化为0
int status;
printf("Please enter an integer to be summed ");
printf("(q to quit): ");
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.1.1程序分析
status==1
==是相等运算符,该表达式判断status是否等于1。当status=1时,循环重复,每次循环num的值被加到sum;当status不等于1时,循环结束,跳出循环。打印sum的最终值。
程序正常运行时,每次循环都要获取num的一个新值并重置status。scanf()函数实现,scanf()返回成功读取项的数量。如scanf()成功读取一个整数,则将读入的数存入num并返回1,随后返回值1赋值给status(用户的输入的值存储在num而不是status)。此时同时更新了num和status,while继续循环。当用户输入的不是数字时,scanf()读取失败,返回0,退出循环。
程序结构如下:
把程序初始化为0
提示用户输入信息
读取用户输入的信息
判断当数据为整数时,
输入添加给sum,
提示用户进行输入,
然后读取下一个输入
输入完成,打印sum的值。
这种结构也叫做伪代码,用简单的句子表示程序思路的方法。
1.2while语句
通用形式:
while(expression)
statement
statement可以是单条语句,也可以是用花括号括起来的复合语句。
expression部分使用关系表达式。
每一次循环都被称为一次迭代。
如下循环结构图
1.2.1终止while循环
想要循环终止,在构建while循环时,必须让测试表达式的值有变化,表达式最终要为假,才能跳出循环,否则会进入死循环。(也可以用break和if语句来终止循环)
例:a=1;
while(a<2)
printf("haha");
该程序就会进入死循环,因为表达式一直为真,不会跳出循环。
注:只有在对测试条件进行求值时,才决定是终止还是继续循环。
1.2.2while:入口条件循环
while循环是使用入口条件的有条件循环。有条件是指语句部分的执行取决于测试表达式描述的条件。只有该表达式满足条件才可以进入循环,如果条件一开始就为假,则跳过循环。
1.2.3语法要点
只有在测试条件后面的单独语句(简单语句或复合语句)才是循环部分。
/*while.c --注意花括号的使用*/
/*构成了一个无限循环的代码*/
#include <stdio.h>
int main()
{
int n = 0;
while (n < 3)
printf("n is %d\n", n);
n++;
printf("That's all this program does.\n");
return 0;
}
程序结果:
该例子是一个无限循环的例子,没有外部干涉就不会退出。
即使while语句本身使用复合语句,在语句构成上,他也是一条单独的语句。该语句从while开始,到第一个分号或是右花括号结束。
分号位置要注意!!!
/*while2.c --注意分号位置*/
#include <stdio.h>
int main()
{
int n = 0;
while (n++ < 3);
printf("n is %d\n", n);
printf("That's all this program does.\n");
return 0;
}
程序结果:
以上可以看出,虽然while语句后接了printf()语句,但是while()后加了;
测试条件后面的单独分号是空语句。
1.3用关系运算符和表达式比较大小
while循环经常依赖测试表达式作比较,该表达式被称为关系表达式,出现在关系表达式中间的运算符叫作关系运算符。每个关系运算符都把它的左侧和右侧的值进行比较。
在比较浮点数时,尽量使用<和>,因为浮点数的舍入误差会导致在逻辑上应该相等的两个数不相等。
1.3.1真值
表达式为真时值为1,为假时值为0。
// truth.c --哪些值为真
#include <stdio.h>
int main()
{
int n = 3;
while (n)
printf("%2d is true\n", n--);
printf("%2d is false\n", n);
n = -3;
while (n)
printf("%2d is true\n", n++);
printf("%2d is false\n", n);
return 0;
}
程序结果:
如上:一般而言,所以的非零值都视为真,只有0被视为假。只要测试条件的值为非零,就会执行while循环 ,简单的关系表达式由关系运算符和运算对象组成。关系表达式为真,求值为1;关系表达式为假,求值为0。
1.3.2新的_Bool类型
C99增加_Bool类型,叫作布尔类型,表示真假的变量称为布尔变量,_Bool类型的变量只能存储1(真)0(假)。
例:
//boolean.c --使用_Bool类型变量variable
#include <stdio.h>
#include <stdbool.h>
int main()
{
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;
}
程序结果:
1.3.3优先级和关系运算符
优先级:算术运算符 > 关系运算符 > 赋值运算符
1.4不确定循环和计数循环
不确定循环:指在测试表达式为假之前,预先不知道要执行多少次循环。
计数循环:指在执行循环之前就知道要重复执行多少次。
1.5for循环
for循环将初始化、测试和更新组合在一起。
//sweetie2.c --使用for循环的计数循环
#include <stdio.h>
int main()
{
const int NUMBER = 22;
int count;
for (count = 1; count <= NUMBER; count++)
printf("Be my Valentine!\n");
return 0;
}
程序结果:
关键字for循环后面圆括号中有3个表达式,用分号隔开。第一个初始化,只在循环开始时执行一次。第二个测试表达式,执行前对表达式求值,判断真假。第三个执行更新,循环结束时求值。
for后加简单(复合)语句。for循环括号里的表达式也叫控制表达式,每个表达式的副作用都发生在对下一个表达式求值之前。
/*for_cube.c --for循环创建一个立方表*/
#include <stdio.h>
int main()
{
int num;
printf(" n n cubed\n");
for (num = 1; num <= 6; num++)
printf("%5d %5d\n", num, num * num * num);
return 0;
}
程序结果:
1.5.1for循环的8种用法
(1)使用递减运算符递减计数器
for (sec = 10; sec > 0; sec--)
(2)计数器递增其他数字
for(n = 2; n < 100; n+=14)
(3)字符代替数字计数
for(ch = 'a'; ch < 'z'; ch++)
(4)测试其他条件
for(n = 1; n * n * n = 9; n++)
(5)增量几何增长
for(a = 10.1; a < 330; a *= 1.1)
(6)第三个表达式可以是任何合法的表达式
for(n=1;m<6;m=(n++)*5+7)
(7)省略一个或多个表达式(不能省略分号)
for(n = 1; m < 2; )
(8)第一个表达式不一定是给变量赋初值,可以使用printf()
for( printf("......"); num != 6;)
1.6其他赋值运算符:+=、-=、*=、/=、%=
用法:左侧一个变量名,右侧一个表达式。赋值变量的新值是根据右侧表达式的值调整后的值。
1.7逗号运算符
逗号运算符把两个表达式连接成一个表达式,并保证最左边的表达式最先求值。逗号运算符通常在for循环头的表达式中用于包含更多信息。整个逗号表达式的值是逗号右侧表达式的值。
1.7.1当Zeno遇上for循环
古老的悖论:
希腊哲学家Zeno曾经提出箭永远不会达到它的目标。首先,他认为箭要到达目标距离的一半,然后再达到剩余距离的一半,然后继续到达剩余距离的一半,这样就无穷无尽。
分析:假设箭用一秒走完一半路程,然后1/2秒走完剩余一半路程的半……
time=1+1/2+1/4+1/8+……
求前几项的和
/*zeno.c --求序列的和*/
#include <stdio.h>
int main()
{
int t_ct; //项计数
double time, power_of_2;
int limit;
printf("Enter the number of terms you want: ");
scanf("%d", &limit);
for (time = 0, power_of_2 = 1, t_ct = 1; t_ct <= limit; t_ct++, power_of_2 *= 2.0)
{
time += 1.0 / power_of_2;
printf("time = %f when terms = %d.\n", time, t_ct);
}
return 0;
}
程序结果:
数学家证明了当项的数目接近无穷时,总和无限接近2。
1.8出口条件循环:do while
出口条件循环:在循环的每次迭代之后检查测试条件,保证了至少执行循环体中的内容。
do while循环通用形式:
do
statement
while (expression);
do while 循环在执行完循环体之后才执行测试条件,所以至少执行循环体一次。在expression为假或0之前重复执行循环体中内容。
/*do_while.c --出口条件循环*/
#include <stdio.h>
int main()
{
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("Congratulation! You are cured!\n");
return 0;
}
程序结果:
1.9 嵌套循环
是指在一个循环内包含另一个循环。嵌套循环常用于按行和列显示,即:一个循环处理一行中的所有列,一个循环处理所有的行。嵌套循环中的内层循环在每次外层迭代时都执行完所有的循环。
例:
/*rows1.c --使用嵌套循环*/
#include <stdio.h>
#define ROWS 6
#define CHARS 10
int main()
{
int row;
char ch;
for (row = 0; row < ROWS; row++)
{
for (ch = 'A'; ch < ('A' + CHARS); ch++)
printf("%c", ch);
printf("\n");
}
return 0;
}
程序结果:
1.10数组简介
数组是按顺序存储的一系列相同的值,通过整数下标访问数组中单独的项或元素,数组元素的编号从0开始。
如果char类型的数组包含一个表示字符串末尾的空字符\0,则该数组中的内容就构成了一个字符串。
用于识别数组元素的数字被称为下标,索引或偏移量。下标必须是整数,而且要从0开始计数,数组的元素被依次存储在内存中相邻位置。数组只存储相同类型的数据。
1.10.1使用函数返回值
double power(double n, int p)
{
double pow = 1;
int i;
for(i = 1;i <= p; i++)
pow *= n;
return pow; //返回pow的值
}
要声明函数返回类型,在函数名前写出类型即可。关键字return表明该函数将把它后面的值返回给主调函数。
函数声明:
例:double power(double n,int p);
括号中的两个参数是函数的形参,函数定义后面没有“;”但是函数声明后面有。
1.10.2使用带返回值的函数
声明函数、调用函数、定义函数、使用关键字return,都是定义和使用返回值函数的基本要素。
当例中的power()函数位于main()函数之前时,就可以省略前置声明。前置声明:预先说明函数的返回值类型。当函数放在其他的文件中时,前置声明是必不可少的。
使用函数三个步骤:
1.通过函数原型声明函数;
2.在程序中通过函数调用使用函数;
3.定义函数。
注:函数原型是为了方便编译器直接查看程序中使用的函数是否正确;函数定义描述了函数如何工作。