文章目录[隐藏]
对于计算机科学而言,一门语言应该改提供以下三种形式的程序流:
- 执行语句序列;
- 如果满足某些条件就重复执行语句序列(循环)
- 通过测试选择执行哪一个语句序列(分支)
6.1 再探while循环
// summing.c 根据用户键入的整数求和
#include<stdio.h>
int main(void)
{
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;
}
6.1.1 程序注释
status == 1;
==运算符是C的相等运算符(equality operator)该表达式判断status是否等于1.scanf会返回成功读取数量。如果用户输入的不是数字,则返回1.
//该程序的答题思路
把sum初始化为0
提示用户输入数据
读取用户输入的值
当输入的数据为整数时,
输入的值添加给sum,
提示用户进行输入,
然后继续读取下一个输入
输入完成以后,打印sum的值
上面这种表达形式叫做伪代码(pseudocode),简单句子表达程序思路的方法。伪代码有助于设计程序的逻辑。
//while
获得第一个用于测试的值
当测试为真时
处理值
获取下一个值
6.1.2 C风格读取循环
// 伪代码
status = scanf("%ld",&num);
while(status==1)
{
//循环
status = scanf("%ld",&num);
}
//可以下代替
whlie(scanf("%ld",&num)==1)
{
//循环
}
C语言特性:
当获取值和判断值都成功
处理该值
#include<stdio.h>
int main()
{
int s,n,p;
p=0;
printf("Enter a num(q to quit):");
while(scanf("%d",&n)==1)
{
p = p+n;
printf("Enter a num(q to quit):");
}
printf("sum = %d\n",p);
return 0;
}
6.2 while语句
while循环的通用形式如下:
while(expression)
statement
statement部分可以使以分号结尾的简单语句,也可以是花括号括起来的复合语句。
6.2.1 终止while循环
while循环最终目的是要跳出去(即条件为假)
6.2.2 何时终止循环
只有对测试条件求值时,才决定是终止还是继续。
// when.c -- 何时退出循环
#include<stdio.h>
int main(void)
{
int n = 5;
while(n<7)
{
printf("n = %d\n",n);
n++;
printf("Now n =%d\n",n);
}
printf("The loop has finished.\n");
return 0;
}
6.2.3 while:入口条件循环
入口条件(entry condition)
6.2.4 语法要点
//while1.c -- 注意花括号的使用
// 糟糕的代码创建了一个无限的循环
#include<stdio.h>
int main(void)
{
int n = 0;
while(n < 3)
printf("n is %d\n",n);
n++;
printf("That's all this program does\n");
return 0;
}
无限循环(infinite loop)
// while2.c --注意分号的位置
#include<stdio.h>
int main(void)
{
int n;
while(n++<3);
printf("n is %d\n",n);
printf("That's all this program does.\n");
return 0;
}
再while后加分号,while也被认为是一条语句。为假以后,执行一次while再进入下一个语句!!!
空语句(null statement)在C语言中,单独的分号表示空语句。
// 跳过整数输入
while(scanf("%d",&num)==1)
6.3 用关系运算符和表达式比较大小
关系表达式(relational expression)
关系运算符(relation operator)
while(number<6)
{
printf("Your number is too small.\n");
scanf("%d",&number);
}
while("ch!='$'")
{
count++;
scanf("%c",&ch);
}
while(scanf("%f",&num) == 1)
{
sum = sum+1;
}
注意:比较浮点数时,尽量只使用<和>.因为浮点数的舍入误差会导致在逻辑上应该相等的两数不相等。例如:
3乘1/3的积为1.0。如果把1/3表示成小数点后6位数字,乘积则是.999999.不等于1.使用fabs()函数(math.h)可以方便的比较浮点数,该函数返回一个浮点数的绝对值(即,没有代数符号的值)
// cmpflt.c --浮点数比较
#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;
}
6.3.1 什么是真?
// t_and_f.c --C中的真和假的值
#include<stdio.h>
int main(void)
{
int true_val;
int false_val;
true_val=(2<10);
false_val=(2 == 10);
printf("t=%d f=%d",true_val,false_val);
return 0;
}
一直循环的结构
while(1)
{
...
}
6.3.2 其他真值
// truth.c --哪些值位真值
#include<stdio.h>
int main(void)
{
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);
return 0;
}
熟悉while(goats)
6.3.3 真值的问题
// trouble.c --无用=会导致无线循环
#include<stdio.h>
int main(void)
{
long num;
long sum=0;
printf("Enter num(q to quit):");
while(scanf("%ld",&num)==1)
{
sum=sum+num;
printf("%d\n",sum);
}
printf("%d",sum);
return 0;
}
当while中的为等号时,为赋值语句,在执行一次真后就变成while(1)了。。。
canoes = 5 //赋值,把5赋给canoes
canoes == 5 //检查canoes的值是否为5
5 = canoes //语法错误
5 == canoes //检查canoes的值是否为5
非零为真,零为假
6.4.4 新的_BOOl类型
C99专门针对真假新增加了_Bool类型
表示真假的变量称为布尔变量(Boolean variable)
_Bool类型的变量只能存储0或1,其他非0数字传给_Bool,该变量会被设置为1.
// boolean.c --使用\_Bool类型的变量variable
#include<stdio.h>
int main(void)
{
long num;
long sum=0;
_Bool input_is_good;
printf("Please Enter num(q to quit):");
input_is_good=scanf("%d",&num);
while(input_is_food)
{
...
input_is_good=scanf("%d",&num);
}
printf("%d",sum);
return 0;
}
C99提供了stdbool.h头文件,该头文件让bool称为_Bool的别名,而且还把true和false分别定义为0和1的符号常量,且写出来的代码与c++兼容。在c++中bool、true、false为关键字。
6.3.5 优先级和关系运算符
关系运算符的优先级比算术运算符低,比赋值运算符高。意味着:
x>y+2和x>(y+2)相同
x=y>2和x=(y>2)如果y>2赋1给x否则赋给x=0。
高优先级组:<\<= >>=
低优先级组:== !=
ex != wye ==zee与(ex !=wye)==zee相同
6.4 不确定循环和技术循环
不确定循环(indefinite loop)
计数循环(counting loop)
// sweetie1.c --一个计数循环
#include<stdio.h>
int main(void)
{
const int MUMBER = 22;
int count = 1;
while(count<=MUMBER)
{
printf("be my valentine!\n");
count++;
}
return 0;
}
在创建一个重复执行固定次数的循环中涉及了3个行为:
- 必须初始化计数器
- 计数器与有限的值做比较
- 每次循环时递增计数器
6.5 for循环
// sweetie2.c --使用for循环的计数循环
#include<stdio.h>
int main(void)
{
const int NUMBER = 22;
int count;
for (count =1;count<=NUMBER;count++)
{
printf("Be my Valentine!\n");
return 0;
}
}
for 圆括号中的表达式也叫控制表达式,它们都是完整表达式,所以每个表达式的副作用(如,递增变量)都发生在对下一个表达式求值之前。
// for_cube.c --使用for循环创建一个立方表
#include<stdio.h>
int main(void)
{
int num;
printf("n n cubed\n");
for(num=1;num<=6;num++)
{
printf("%-4d %-4d\n",num,num*num*num);
}
return 0;
}
6.5.1 利用for的灵活性
-
可以使用递减运算符来递减计数器
// for_down.c #include<stdio.h> int main(void) { int secs; for(secs=5;secs>0;secs--) { printf("%d secondes!\n",secs); } printf("We have ignition!\n"); return 0; }
-
可以让计数器递减2、10等
// for_13s.c #include<stdio.h> int main(void) { int n; for(n=2;n<60;n=n+13) { printf("%d\n",n); } return 0; }
-
可以让字符串代替数字
// for_Char.c #include<stdio.h> int main(void) { char ch; for(ch='a';ch<='z';ch++) { printf("The ASCII value for %c is %d.\n",ch,ch); } return 0; }
-
除了测试迭代次数外,还可以测试其他条件。
for(num = 1;num<=6;num++) //替换成 for(num = 1;num*num*num<=216;num++)
如果与控制循环次数相比,你更关心限制立方的大小,就可以使用这样的测试条件。
-
可以让递增的量几何增长,而不是算术增长。
// for_geo.c #include<stdio.h> int main(void) { double debt; for(debt=100.0;debt<150.0;debt=debt*1.1) { printf("Your debt is now $%.2f.\n",debt); } return 0; }
-
第3个表达式可以使用仍以合法的表达式。无论是什么表达式,每次迭代都会更新该表达式的值。
// for_wild.c #include<stdio.h> int main(void) { int x; int y = 55; for(x=1;y<=75;y=(++x*5)+50) { printf("%10d %10d\n",x,y); } return 0; }
-
可以省略一个或多个表达式(不能省略分号),只要在循环中包括能结束循环的语句即可
#include<stdio.h> int main(void) { int ans,n; ans = 2; for(n = 3;ans<=25;) { ans=ans*n; } printf("n = %d.ans=%d.\n",n,ans); return 0; }
下面的循环会一直运行
for( ; ; )
{
printf("im so boring");
}
-
第1个表达式不一定是给变量赋初值,也可以使用printf()
// for_show.c #include<stdio.h> int main(void) { int num = 0; for(printf("Keep entering numbers!\n);num!=6;) { scanf("%d",&num); } printf("That's the one I want!\n"); return 0; }
-
循环体中的行为可以改变循环头中的表达式
for(n = 1;n<10000;n \= n+delta)
经过几次的带以后发现delta太小,循环语句中的if可以改变delta的大小。
小结
6.6 其他赋值运算符
更加复杂:
x*=3*y+12与x = x*(3*y+12)
以上提到的赋值运算符与=的优先级相同
优点:让代码紧凑。组合形式的赋值运算比一般形式赋值运算生成的机器代码更高效。
当需要在for循环中塞一些复杂的表达式时,这些赋值运算符都特别有用。
6.7 逗号运算符
// postage.c --一类邮咨
#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;
}
逗号保证了表达式从左往右求值。
其次,整个表达式的值是右侧的值:
x = (y=3,(z=++y+2)+5)
效果:先把3赋给y,++y=4,+2=6,z=6,x=6+5=11;
houseprise =249,500
表示houseprise =249;
500;
而
houseprise =(249,500)
表示为:houseprise =500
逗号也可以作为分隔符,在下面语句中的逗号都是分隔符,不是逗号运算符:
char ch,date;
printf("%d %d\n",a,b);
小结
6.7.1 当Zero遇到for循环
// zeno.c --求序列的和
#include<stdio.h>
int main(void)
{
int t_ct;
double time,power_of_2;
int limit;
printf("Enter the number of term 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;
}
叨叨几句... NOTHING