五.函数
1.数值传递与地址传递
参数按数值传递和按地址传递(Arguments passed by value and byreference)到目前为止,我们看到的所有函数中,传递到函数中的参数全部是按数值传递的(byvalue)。也就是说,当我们调用一个带有参数的函数时,我们传递到函数中的是变量的数值而不是变量本身。例如,假设我们用下面的代码调用我们的第一个函数 addition :
int x=5, y=3, z;
z = addition ( x , y );
在这个例子里我们调用函数 addition 同时将 x 和 y 的值传给它,即分别为 5 和 3,而不是两个变量:这样,当函数addition被调用时,它的变量a和b的
值分别变为5和3,但在函数addition内对变量 a 或 b 所做的任何修改不会影响变量他外面的变量 x 和 y 的值,因为变量 x和 y 并没有把它们自己传递给函数,而只是传递了他们的数值。
但在某些情况下你可能需要在一个函数内控制一个函数以外的变量。要实现这种操作,
我们必须使用按地址传递的参数(arguments passed by reference),就象下面例子中
的函数 duplicate:
// passing parameters by reference
#include
void duplicate (int& a, int& b, int& c)//采用按地址传递的方式传入参数
{
a*=2;
b*=2;
c*=2;
}
int main ()
{
int x=1, y=3, z=7;
duplicate (x, y, z);
x=2, y=6, z=14
cout << "x=" << x << ", y=" << y << ", z=" << z;
return 0;
}
第一个应该注意的事项是在函数 duplicate 的声明(declaration)中,每一个变量的类型后面跟了一个地址符 ampersand sign (&),它的作用是指明变量是按地址传递的(byreference),而不是像通常一样按数值传递的(by value)
按地址传递(Passing by reference)是一个使函数返回多个值的有效方法。例如,下面是一个函数,它可以返回第一个输入参数的前一个和后一个数值。
参数的默认值(Default values n n n in arguments)
当声明一个函数的时候我们可以给每一个参数指定一个默认值。如果当函数被调用时没有给出该参数的值,那么这个默认值将被使用。指定参数默认值只需要在函数声明时把一个数值赋给参数。如果函数被调用时没有数值传递给该参数,那么默认值将被使用。但如果有指定的数值传递给参数,那么默认值将被指定的数值取代。例如:
// default values in functions
#include
int divide (int a, int b=2)
{
int r;
r=a/b;
return (r);
}
int main () {
cout << divide (12);
cout << endl;
cout << divide (20,4);
return 0;
}
6
5
我们可以看到在程序中有两次调用函数 divide。第一次调用:
divide (12)
只有一个参数被指明,但函数 divide 允许有两个参数。因此函数 divide 假设第二个参数的值为2,因为我们已经定义了它为该参数缺省的默认值(注意函数声明中的int b=2)。因此这次函数调用的结果是 6 (12/2)。
在第二次调用中:divide (20,4)这里有两个参数,所以默认值 (int b=2) 被传入的参数值 4 所取代,使得最后结果为 5(20/4).
函数重载(Overloaded functions)
两个不同的函数可以用同样的名字,只要它们的参量(arguments)的原型(prototype)不同,也就是说你可以把同一个名字给多个函数,如果它们用不同数量的参数,或不同类型的参数。例如:
// overloaded function即当存在两个相同的函数时,编译器会自动选择匹配的函数。
#include
int divide (int a, int b) {
return (a/b);
}
float divide (float a, float b) {
return (a/b);
}
int main () {
int x=5,y=2;
float n=5.0,m=2.0;
cout << divide (x,y);
cout << "\n";
cout << divide (n,m);
cout << "\n";
return 0;
}
2
2.5
在这个例子里,我们用同一个名字定义了两个不同函数,当它们其中一个接受两个整型(int)参数,另一个则接受两个浮点型(float)参数。编译器 (compiler)通过检查传入的参数的类型来确定是哪一个函数被调用。如果调用传入的是两个整数参数,那么是原型定义中有两个整型(int)参量的函数被调用,如果传入的是两个浮点数,那么是原型定义中有两个浮点型(float)参量的函数被调用。为了简单起见,这里我们用的两个函数的代码相同,但这并不是必须的。你可以让两个函数用同一个名字同时完成完全不同的操作。
Inline 函数(inline functions)
inline 指令可以被放在函数声明之前,要求该函数必须在被调用的地方以代码形式被编译。这相当于一个宏定义(macro)。它的好处只对短小的函数有效,这种情况下因为避免了调用函数的一些常规操作的时间(overhead),如参数堆栈操作的时间,所以编译结果的运行代码会更快一些。
它的声明形式是:
inline type name ( arguments ... ) { instructions ... }
它的调用和其他的函数调用一样。调用函数的时候并不需要写关键字 inline ,只有在函数声明前需要写
六.数组
注意:同时给数组赋多个值只有在数组初始化时,也就是在声明数组时,才是合法的。
象下面代码现实的表达式都是错误的:
mystring = "Hello";
mystring[ ] = "Hello";
mystring = { 'H', 'e', 'l', 'l', 'o', '\0' }
给字符数组的赋值
因为赋值运算的 lvalue 只能是数组的一个元素,而不能使整个数组,所以,用以下方
式将一个字符串赋给一个字符数组是合法的:
mystring[0] = 'H';
mystring[1] = 'e';
mystring[2] = 'l';
mystring[3] = 'l';
mystring[4] = 'o';
mystring[5] = '\0';
但正如你可能想到的,这并不是一个实用的方法。通常给数组赋值,或更具体些,给字符序列赋值的方法是使用一些函数,例如 strcpy。strcpy (string copy) 在函数库
cstring (string.h) 中被定义,可以用以下方式被调用:
strcpy (string1, string2);
这个函数将 string2 中的内容拷贝给 string1。string2 可以是一个数组,一个指针,
或一个字符串常量 constant string。因此用下面的代码可以将字符串常量"Hello"赋给mystring:
strcpy (mystring, "Hello");
例如:
// setting value to string
#include
#include
int main () {
char szMyName [20];
strcpy (szMyName,"J. Soulie");//给数组元素赋值
cout << szMyName;
return 0;
}
J. Soulie
注意:我们需要包括头文件才能够使用函数 strcpy。
虽然我们通常可以写一个像下面 setstring 一样的简单程序来完成与 cstring 中
strcpy 同样的操作:
// setting value to string
#include
void setstring (char szOut [ ], char szIn [ ])//作用等同于strcpy函数
{
int n=0;
do {
szOut[n] = szIn[n];
} while (szIn[n++] != '\0');
}
int main ()
{
char szMyName [20];
setstring (szMyName,"J. Soulie");
cout << szMyName;
return 0;
}
另一个给数组赋值的常用方法是直接使用输入流(cin)。在这种情况下,字符序列的值是在程序运行时由用户输入的。
当 cin 被用来输入字符序列值时,它通常与函数 getline 一起使用,方法如下:
cin.getline ( char buffer[], int length, char delimiter = ' \n');
这里 buffer 是用来存储输入的地址(例如一个数组名),length 是一个缓存 buffer 的最大容量,而 delimiter 是用来判断用户输入结束的字符,它的默认值(如果我们不写这个参数时)是换行符 newline character ('\n')。
下面的例子重复输出用户在键盘上的任何输入。这个例子简单的显示了如何使用
cin.getline 来输入字符串:
// cin with strings
#include
int main () {
char mybuffer [100];
cout << "What's your name? ";
cin.getline (mybuffer,100);
cout << "Hello " << mybuffer << ".\n";
cout << "Which is your favourite team? ";
cin.getline (mybuffer,100);//给数组元素赋值
What's your name? Juan
Hello Juan.
Which is your favourite
team? Inter Milan
I like Inter Milan too.
cout << "I like " << mybuffer << " too.\n";
return 0;
}
注意上面例子中两次调用 cin.getline 时我们都使用了同一个字符串标识
(mybuffer)。程序在第二次调用时将新输入的内容直接覆盖到第一次输入到 buffer 中
的内容。
你可能还记得,在以前与控制台(console)交互的程序中,我们使用 extraction operator(>>) 来直接从标准输入设备接收数据。这个方法也同样可以被用来输入字符串,例如,
在上面的例子中我们也可以用以下代码来读取用户输入:
cin >> mybuffer;
这种方法也可以工作,但它有以下局限性是 cin.getline 所没有的:
•
它只能接收单独的词(而不能是完整的句子),因为这种方法以任何空白符为分隔
符,包括空格 spaces,跳跃符 tabulators,换行符 newlines 和回车符 arriage
returns。
•
它不能给 buffer 指定容量,这使得程序不稳定,如果用户输入超出数组长度,输入信息会被丢失。
因此,建议在需要用 cin 来输入字符串时,使用 cin.getline 来代替 cin >>。
字符串和其它数据类型的转换(Converting strings to other types)
鉴于字符串可能包含其他数据类型的内容,例如数字,将字符串内容转换成数字型变量的功能会有用处。例如一个字符串的内容可能是"1977",但这一个 5 个字符组成序列,并不容易转换为一个单独的整数。因此,函数库 cstdlib (stdlib.h) 提供了 3 个有用
的函数:
•
atoi: 将字符串 string 转换为整型 int
•
atol: 将字符串 string 转换为长整型 long
•
atof: 将字符串 string 转换为浮点型 float
所有这些函数接受一个参数,返回一个指定类型的数据(int, long 或 float)。这三个函数与 cin.getline 一起使用来获得用户输入的数值,比传统的 cin>> 方法更可靠:
// cin and ato* functions
Enter price: 2.75
#include
#include
int main ()
{
char mybuffer [100];
float price;
int quantity;
cout << "Enter price: ";
cin.getline (mybuffer,100);
price = atof (mybuffer);
cout << "Enter quantity: ";
cin.getline (mybuffer,100);
quantity = atoi (mybuffer);
cout << "Total price: " << price*quantity;
return 0;
}
字符串操作函数(Functions to manipulate strings)
函数库 cstring (string.h) 定义了许多可以像 C 语言类似的处理字符串的函数 (如前
面已经解释过的函数 strcpy)。这里再简单列举一些最常用的:
•
strcat: char* strcat (char* dest, const char* src); //将字符串 src 附加到字符串 dest 的末尾,返回 dest。
•
strcmp: int strcmp (const char* string1, const char* string2); //比较两个字符串 string1 和 string2。如果两个字符串相等,返回 0。
•
strcpy: char* strcpy (char* dest, const char* src); //将字符串 src 的内
容拷贝给 dest,返回 dest 。
•
strlen: size_t strlen (const char* string); //返回字符串的长度。
注意:char* 与 char[] 相同。
用户1359192 2015-2-4 11:17
用户403664 2014-2-13 10:22