6.12 使用函数返回值的循环例子

本章中的最后一个例子使用一个函数,它计算一个数的整数次幂的结果(要进行严格的数值处理,math.h库提供了一个名为pow()的更强大的幂函数,它允许计算浮点数次幂)。在这个练习中的三个主要任务是为计算答案设计算法、在一个返回答案的函数中应用算法,以及提供一个便利的方法来测试该函数。

首先看一下算法。我们通过限制为求正整数次幂来简化函数。这样,如果您想要求n的p次幂,应该把n与自己相乘p次。很自然这可以由一个循环来完成。可以设置变量pow为1然后反复把它与n相乘:

广告:个人专属 VPN,独立 IP,无限流量,多机房切换,还可以屏蔽广告和恶意软件,每月最低仅 5 美元

阅读 ‧ 电子书库

回忆一下,*=运算符把其左边的数乘上其右边的数。在第一次循环后,pow就是n的1次幂,也就是n。第二次循环后,pow就是它的先前值(n)乘以n,也就是n的平方,等等。在这种情形中使用for循环是很自然的,因为循环执行预先确定的次数(在p已知后)。

现在您已经有了一个算法,下面应该决定使用什么数据类型。指数p是一个整数,其类型应该为int。为了允许n及其幂的值有较大的范围,n和pow使用double类型。

接下来,我们考虑如何把这些功能放在一起。需要为函数传递两个值,然后让函数返回一个值。要把信息传递给函数,可以使用两个参数,一个double和一个int,来指定求哪个数的多少次幂。如何安排函数以使它向调用程序返回一个值?写一个具有返回值的函数要做以下事情:

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

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

例如,您可以这样:

阅读 ‧ 电子书库

要声明函数类型,可以在函数名之前写出类型,就像声明一个变量时那样。关键字return使函数把跟在该关键字后面的值返回给调用函数。这里返回了一个变量的值,但是也可以返回表达式的值。例如,以下是一个合法的语句:

阅读 ‧ 电子书库

函数将计算该表达式的值并返回之。在调用函数中,可以把返回值赋给另一个变量;可以把它作为一个表达式中的值;可以把它作为另一个函数的参数,例如printf(“%f”, power (6.28,3));也可以忽略它。

现在我们在程序中使用这个函数。要测试这个函数很方便,只须向它传递一些值来看它是如何反应的。这意味着要建立一个输入循环,很自然的选择是使用while循环。可以使用scanf()来一次读入2个值。如果成功地读入了2个值,scanf()就返回值2,这样您就可以通过把scanf()的返回值与2进行比较来控制循环。还有一点:要在您的程序中使用power()函数,需要声明它,就像声明一个程序中用到的变量一样。程序清单6.20中是这个程序。

程序清单6.20 power.c程序

阅读 ‧ 电子书库

下面是一个运行示例:

阅读 ‧ 电子书库

6.12.1 程序讨论

main()程序是一个驱动程序(driver)的例子。驱动程序是被设计用来测试一个函数的短小的程序。

这里的while循环是我们以前使用过的形式的推广。键入1.2 12使scanf()成功地读入两个值并返回2,循环继续进行。因为scanf()跳过了空白字符,所以就像例子中显示的那样,输入可以在多行进行。但是键入q会使返回值为0,因为q不能使用%If说明符进行读取。这会使scanf()返回0而结束循环。与之类似,键入2.8 q会使返回值为1,也会结束循环。

现在我们来看一下与函数相关的一些事情。power()函数在这个程序中出现了三次,第一次出现是这样的:

阅读 ‧ 电子书库

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

第二次出现是这样的:

阅读 ‧ 电子书库

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

第三次出现是在函数定义的开始:

阅读 ‧ 电子书库

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

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

阅读 ‧ 电子书库

6.12.2 使用具有返回值的函数

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

在这点上您可能会有一些疑问。例如,既然在使用函数的返回值前要声明函数,为什么使用scanf()的返回值时无须声明scanf()?为什么除了在定义中说明power()的类型为double之外,还必须单独地声明这个函数?

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

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