C控制语句:循环

C的三种循环结构:while、for和do while。


==运算符是C的相等运算符。


scanf( )返回成功读入的项目的个数。如果scanf()在尝试转换一个数值前遇到了问题(例如,检测到文件的尾部或者遇到一个硬件问题),它就会返回一个特殊值EOF,这个值一般被定义为-1。


while循环:

while循环的一般形式:

<span style="font-size:18px;">while(expression)
          statement</span>

statement部分可以是一个带有分号的简单语句,也可以是花括号中的一个复合语句。

每次循环都被称为一次迭代

终止while循环:这是对while循环至关重要的一点:当构造一个while循环时,循环中必须包含能改变判断表达式的值来使表达式的值最终变为假。否则循环永远不会终止(实际上,也可以使用break和if语句来终止循环)。

while:入口条件循环。

while循环是使用入口条件的有条件循环。它被称为有条件是因为语句部分的执行要依赖于判断表达式中的条件。这个表达式是一个入口条件是因为在进入循环体之前必须满足这个条件

在使用while时要谨记,只有位于判断条件之后的单个语句(简单语句或复合语句)才是循环的部分

while语句本身在语法上算做一个单独的语句,即使它使用了复合语句。该语句从while开始,到第一个分号结束;在使用了复合语句的情况下,到终结花括号结束。


因为while循环经常要依赖于进行比较的判断表达式,所以比较表达式值得进一步研究。这样的表达式称为关系表达式,其中出现的运算符称为关系运算符

关系表达式也可以用于字符的比较。进行比较时使用的是机器的字符代码,然而,不能使用关系运算符来比较字符串

关系表达式也可以用于浮点数,但是在浮点数比较中只能使用<和>。原因在于舍入误差可能造成两个逻辑上应该相等的数不相等。例如,3和1/3的乘积应该是1.0。但是如果用6位小数来表示1/3,乘积就是.999999而不等于1。使用在math.h头文件中声明的fabs()函数可以方便地进行浮点数判断。这个函数返回一个浮点值的绝对值(即没有代数符号的值)

如下代码:

<span style="font-size:18px;">//浮点数的比较
#include<math.h>
#include<stdio.h>
int main(void){
	const double ANSWER = 3.14159;
	double response;
	printf("pi的值是多少?\n");
	scanf("%lf",&response);
	while(fabs(response - ANSWER) > 0.0001)
	{
		printf("请再次输入:\n");
		scanf("%lf",&response);
	}
	printf("Close enough!\n");
	return 0;
}</span>
运行结果如下:



C的表达式通常具有一个值。即使对关系表达式也是如此。

可以说只要while循环的判断条件的值非零,它就可以执行循环。这使得判断条件是建立在数值的基础上而不是在真/假的基础上。如果关系表达式为真,它的值就为1;如果为假,它的值就为0。因为这样的表达式实际上是数值的。


在C中,表示真/假的变量一直是由int类型来表示的。C99专门为这种类型的变量添加了_Bool类型。在编程领域,表示真或假的变量开始时被称为布尔变量。这样_Bool就是布尔变量的C类型名

一个_Bool变量只可以由具有值1(真)或0(假)。如果把一个_Bool变量赋为一个非零的数值,变量就被设置为1。这说明C把任何非零的值都认为是真


==运算符的优先级比=高。

关系运算符的优先级要低于包括+和-在内的算术运算符,但是要高于赋值运算符。


C99还提供了一个stdbool.h头文件。包含这个头文件可以使用bool来代替_Bool,并把true和false定义成值为1或0的符号变量。在程序中包含这个头文件可以写出与C++兼容的代码,因为C++把bool、true和false定义为关键字。


有些while循环的例子是不确定循环。也就是说,在表达式变为假之前不能预先知道循环要执行多少次。其他的是计数循环,它们循环执行预先确定的次数。

在建立一个重复执行固定次数的循环时涉及到三个动作:

1.必须初始化一个计数器。

2.计数器与某个有限的值进行比较。

3.每次执行循环,计数器的值都要递增。


for循环:

for循环把所有这三种动作(初始化、测试、更新)都放在一起。

for循环的一般形式:

<span style="font-size:18px;">for(initialize; test; update)
     statement</span>
在test为假(或零)之前重复执行循环。

for语句使用由分号分开的三个控制表达式来控制循环过程。for语句是一个入口条件循环,即是否再次执行循环的决定是在循环执行之前做出的。因此,有可能循环一次也不执行。该形式的statement部分可以是一个简单语句或一个复合语句。


在关键字for之后的圆括号中包含了由两个分号分开的三个表达式。

第一个表达式进行初始化,它在for循环开始的时候执行了一次。

第二个表达式是判断条件,在每次执行循环之前都要对它进行求值。当表达式为假时,循环就结束了。

第三个表达式进行改变或称为更新,它在每次循环结束时进行计算。这之后的一个简单或复合语句结束了for语句。

三个控制表达式中的每一个都是完整的表达式,所以任意一个控制表达式的任何副作用(例如把一个变量的值递增)都在程序求下一个表达式的值之前生效。


任何具有分号的表达式都可以成为一个语句。


do while循环:

C也有退出条件循环,判断条件在执行循环之后进行检查,这样就可以保证循环体中的语句至少被执行一次,这被称为do while循环

do while循环的一般形式:

<span style="font-size:18px;">do 
    statement
while(expression);</span>
statement部分可以是简单语句或复合语句。do while循环本身是一个语句,因此它需要一个结束的分号。

do while循环至少要被执行一次,因为在循环体被执行之后才进行判断。


for(; test;)和while(test)这两种写法是相同的。


嵌套循环:

嵌套循环是指在另一个循环之内的循环。

通常使用嵌套循环来按行按列显示数据。也就是说一个循环处理一行中的所有列,而另一个循环则处理所有的行。

内部循环在外部循环的每次单独循环中都完全执行它的所有循环。


使用具有返回值的函数:

写一个具有返回值的函数要做以下事情:

1.当定义函数时,说明它的返回值类型。

2.使用关键字return指示要返回的值。

例如:

<span style="font-size:18px;">double power(double n, int p)    //返回double类型的值
{
	double pow = 1;
	int i;
	
	for(i = 1; i<=p; i++)
	     pow *=n;
	return pow;   //返回pow的值 
} </span>
要声明函数类型,可以在函数名之前写出类型,就像声明一个变量时那样。关键字return使函数把跟在该关键字后面的值返回给调用函数。这里返回了一个变量的值,但是也可以返回表达式的值。例如,以下是一个合法的语句:

<span style="font-size:18px;">return 2*x+b;</span>
函数将计算该表达式的值并返回之。

在调用函数中,可以把返回值赋给另一个变量;可以把它作为一个表达式中的值;可以把它作为另一个函数的参数;也可以忽略它。

<span style="font-size:18px;">/* 计算数值的整数次幂 */
#include <stdio.h>
double power (double n, int p);  //  ANSI 原型
int main (void)
{
    double x,xpow;
    int exp;

     printf ("输入一个数和一个正整数,求这个数的乘幂。输入q结束。\n");
     while (scanf ("%lf %d",&x,&exp) == 2 )
     {
         xpow = power (x,exp);     //   函数调用
         printf ("%.3g 的 %d 次幂是 %.5g\n",x,exp,xpow);
         printf ("输入下一对数或者输入q停止。\n");
     }
     printf ("--- bye ---\n");
     getchar();
     return 0;
}

double power (double n, int p)
{
     double pow = 1;
     int i;

     for (i = 1; i<= p; i++)
       pow *= n;
     return pow;               // 返回 pow 的值
}
</span>
该main( )程序是一个驱动程序的例子。驱动程序是被设计用来测试一个函数的短小的程序。

power()函数在这个程序中出现了三次。

第一次:     double power (double n, int p); // ANSI 原型

这个语句声明程序将使用一个名为 power()的函数。

开始的关键字 double 表明 power()函数会返回一个类型为 double 的值。编译器需要知道 power( )的返回值类型,这样它才能知道需要多少字节的数据以及如何解释它们,这也是必须声明函数的原因。括号中的 double n, int p 说明power()接受两个参数,第一个参数应是类型为 double 的值,第二个参数的类型应为 int 。

第二次:    xpow = power (x,exp); // 函数调用

程序在这里调用了这个函数,并传递给它两个值。函数计算 x 的 exp 次幂,然后把结果返回给调用程序,接着返回值又被赋给变量 xpow 。

第三次:    double power (double n,int p) // 函数定义

在这里 power( )接受由变量 n 和 p 表示的两个参数,一个 double 和一个 int 。注意在函数定义时,power( )后面没有分号,而在函数声明时是有分号的。在函数头之后就是完成 power()所做事情的代码。

回忆一下,函数使用了 for 循环来计算 n 的 p 次幂并把它赋值给 pow 。下面这行使 pow 成为函数的返回值。

<span style="font-size:18px;">return pow;     // 返回 pow 的值</span>


声明函数,调用函数,定义函数,使用 return 关键字,这些就是在定义并使用具有返回值的函数时的基本要素。


为什么除了在定义中说明 power( )的类型为 double 之外,还必须单独地声明这个函数?

编译器在程序中第一次遇到 power( )时,它需要知道 power( )是什么类型。而此时编译器还没有遇到 power( )的定义,所以它并不知道定义中说明了返回类型为 double 。

为了帮助编译器,要通过一个前向声明来预先说明它是什么类型。这个声明通知编译器power( )在其他地方定义而且它的返回值类型为 double。如果你把 power( )函数的定义放在 main( )之前,就可以省略向前声明,因为编译器在到达 main( )之前已经知道了关于power( )的所有信息。但是这不是标准 C 的风格。因为main( )通常提供一个程序的整体框架,所以最好是首先给出 main( )函数。此外,函数经常放在单独的文件中,所以向前声明是必不可少的。


既然在使用函数的返回值前要声明函数,为什么使用 scanf()的返回值时无须声明 scanf()?

这是因为已经声明过了。stdio.h 头文件中含有 scanf(),printf()以及其他一些 I/O 函数的函数声明。scanf()的声明说明它的返回类型为 int。


使用一个函数需要完成三个单独的步骤:

1.使用函数原型声明该函数。

2.在程序中通过函数调用来使用该函数。

3.定义函数。

原型使编译器可以检查是否正确地使用了函数,而定义则规定了函数如何工作。现代的编程习惯是把程序的元素分为接口实现部分,原型定义就是这样的例子。接口部分描述了如何使用一个特性,这正是原型所做的;而实现部分说明了采取的具体动作,这正是定义所做的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值