第8章将详细介绍函数,但在此之前仍可以使用标准库中的一些函数。下面将简要讨论使用函数的场合和函数的一些术语。
函数是一个自包含的被命名的代码块,执行某个特定的任务,这常常要对所提供的数据执行一些操作,再把操作的结果返回给程序。如果函数返回了一个数字值,该函数就可以像一般的变量那样参与算术表达式。一般情况下,函数的调用如下:
FunctionName(argument1, argument2, …)
根据所使用的函数,可以为它提供0个、1个或多个值,在程序中调用该函数时,应把这些值放在函数名后面的括号中。以这种方式传送给函数的值称为变元。与C++中的所有值一样,传送给函数的变元和函数返回给程序的值都是有类型的,必须遵循其类型的规则,才能正确使用函数。
在源文件的开头为头文件<cstdlib>添加#include指令,就可以访问几个应用于整数的数字函数了。这个头文件的内容与原来的C库头文件stdlib.h相同。下面将通过几个例子语句来学习这些函数。
abs()函数返回变元的绝对值,其变元可以是int类型或long类型。数字的绝对值就是不包括符号的数值部分,所以负数的绝对值就是其数字,但符号是正的,而正数的绝对值是其本身。abs()函数返回的值与变元有相同的类型,例如:
int value = -20;
int result = std::abs(value); // Result is 20
头文件<cstdlib>还定义了labs()函数,它也生成long类型的变元的绝对值。包含这个函数的原因是旧式的C程序可能使用它,但最好只使用abs()函数。
div()函数有两个变元,它们的类型都是int,该函数返回第一个变元除以第二个变元的结果,相除的余数采用div_t类型的结构形式。后面将详细介绍结构,现在通过一个例子学习如何访问div()函数返回的商和余数:
int value = 93;
int divisor = 17;
div_t results = std::div(value, divisor); //Call the function
std::cout << "\nQuotient is" << results.quot; //Quotient is 5
std::cout << "\nRemainder is" << results.rem; //Remainder is 8
前两个语句定义了变量value和divisor,并给它们指定初始值93和17。下一个语句调用div()函数,对value除以divisor。函数返回的结果是div_t类型的结构,它存储在变量results中,该变量也是div_t类型。在第一个输出语句中,在results名称的后面加上quot,并用一个句点隔开,以访问results中的商,这个句点叫作成员访问运算符,这里使用它访问results结构的quot成员。同样,在最后一个语句中,使用成员访问运算符输出余数,它可以通过results结构的rem成员来获得。div_t类型的所有结构都有quot成员和rem成员,使用成员访问运算符总是可以访问它们。
注意可以直接把字面量用作div()函数的变元。此时,调用函数的语句如下:
div_t results = std::div(93, 17);
ldiv()函数执行的操作与div()函数相同,但其变元是long类型。返回的结果是ldiv_t类型的结构,其成员quot和rem也是long类型。
注意:
<cstdlib>头文件是从C继承来的,所以许多实现方式包含了原来C函数的定义,它们没有在std命名空间中定义,所以函数名不使用std限定符。这将允许C程序在相同的环境下编译和执行,但在C++中编码时,应给这些函数加上std限定符。
生成随机数
在程序中生成随机数是非常有用的。例如游戏程序中就需要有随机性,否则它们很快让人厌烦。<cstdlib>头文件定义了一个生成随机整数的函数rand()。更明确地说,该函数会生成伪随机整数。根据定义,随机数是不能预测的,所以数字算法生成的任意序列数字都不是真正随机的,只是表面上看起来像是随机的而已。但是,理解了这一点后,就可以把rand()函数生成的数字看作随机数。注意rand()不是一个杰出的随机数生成器,许多应用程序都使用更专业的随机数生成器。
rand()函数把一个随机整数返回为int类型。该函数不需要任何变元,所以可以按照如下方式使用它:
int random_value = std::rand(); //A random integer
这里把rand()函数返回的整数存储在变量random_value中,也可以在算术表达式中使用它,如下所示:
int even = 2 * std::rand();
rand()函数返回的值是从0到RAND_MAX之间的一个值。RAND_MAX是一个在<cstdlib>中定义的符号。在代码中使用RAND_MAX时,编译器会用一个整数值代替它。在一些系统中,它表示值0x7fff,在另外一些系统中,它有不同的值,它至多可以是0x3fffffff,这是可以存储为int类型的最大整数。如果RAND_MAX的值是0x3fffffff,就不能像以前那样,把rand()生成的值乘以2,这可能会生成不正确的结果。下一章将解决这个问题。
RAND_MAX由一个预处理的宏定义(第10章介绍预处理的宏),它不在std命名空间中,所以使用时不需要限定名称。由宏定义的任何符号都不在std命名空间中,因为它不是一个表示什么的名称。在编译器开始编译代码时,这样的符号就不再出现,因为它已经在预处理阶段被其他内容替代了。
数字序列的随机化
使用前面介绍的rand(),数字序列总是相同的,这是因为该函数在生成随机数的算法中使用默认的种子值。这非常适合于测试,但一旦有了可以工作的游戏出现,就希望每次运行程序时都有不同的序列。为此,可以修改用于生成随机数的种子值,方法是把一个新的种子值作为整数变元传送给在<cstdlib>中定义的srand()函数,例如:
std::srand(13); //Set send for rand to 13
srand()函数的变元必须是unsigned int类型的值。前面的语句将使rand()产生一个与默认不同的序列,但我们真正需要的是在每次执行程序时,都要从rand()函数中用一个随机种子生成不同的序列。幸好,计算机的时钟是随机种子值的一个很好的来源。
<ctime>标准库头文件定义了几个与日期和时间相关的函数。这里要介绍time()函数,因为这就是获得随机种子值的方式。time()函数返回自从1970年1月1日以来过去的秒数。如果使用这个秒数作为种子,每次执行程序时都会使用不同的种子值,这个值返回为time_t类型,这个类型是在标准库中定义的,等价于一个整数类型,通常是long类型。返回类型指定为time_t类型,就为不同C++实现方式处理返回值类型提供了一定的灵活性。可以使用time()函数为随机数序列创建种子,如下所示:
std::srand((unsigned int)std::time(0));
这里要注意几个问题。time()函数的变元是0,该变元还有另外一种可能,但这里不需要,所以忽略它。子表达式(unsigned int)把time()函数的返回值转换为unsigned int类型,这是srand()方法需要的变元类型。没有它,这个语句就不会编译。类型转换在以后介绍。
下面用一个例子来说明随机数的生成。
程序示例2.5—— 生成随机整数
下面是代码:
//Program 2.5 Using Random Integers
#include <iostream>
#include <cstdlib>
#include <ctime>
using std::cout;
using std::endl;
using std::rand;
using std::srand;
using std::time;
int main() {
const int limit1 = 500; //Upper limit for on set of random values
const int limit2 = 31; //Upper limit for another set of values
cout << "First we will use the default sequence from rand(). \n ";
cout << "Three random integer from 0 to " << RAND_MAX << ": "
<< rand() << " " << rand() << " " <<rand() << endl;
cout << endl << "Now we will use a new seed for rand().\n ";
srand((unsigned int)time(0)); //Set a new seed
cout << "Three random integer from 0 to " << RAND_MAX <<": "
<< rand() << " " <<rand()<<" " << rand()<<endl;
return 0;
}
结果如下:
First we will use the default sequence from rand().
Three random integer from 0 to 32767: 6334 18467 41
Now we will use a new seed for rand().
Three random integer from 0 to 32767: 4610 32532 28452
例子的说明
这是rand()函数的一个简单用法,首先使用默认种子开始序列:
cout << "A random integer from 0 to " << RAND_MAX << ": "
<< rand() << endl;
对rand()的每次调用都返回一个0到RAND_MAX之间的数值,这个函数调用三次,就会获得三个随机整数序列。
接着,使用下面的语句把种子值设置为系统时钟的当前值:
srand((unsigned int)time(0)); //Set a new seed
在每次执行程序时,这个语句都会设置一个不同的种子,接着重复前面用默认种子集执行的语句,因此,每次运行这个程序时,第一组总是生成相同的结果,而第二组的输出应是不同的。





