原创 C++学习之路(三) 函数与数组

2014-2-14 10:00 2549 10 11 分类: 软件与OS 文集: C++ 学习之路

五.函数

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[] 相同。

文章评论1条评论)

登录后参与讨论

用户1359192 2015-2-4 11:17

呵,路上抢苹果的会越来越多吧

用户403664 2014-2-13 10:22

好文章。没见着四啊?
相关推荐阅读
用户420622 2014-02-17 16:01
C++学习之路(九) 多态
多态 (Polymorphism) 1.基类的指针(Pointers to base class)      继承的好处之一是一个指向子类(derived class)的指针与一个指向基类...
用户420622 2014-02-17 15:45
C++ 学习之路(五) 类的构成
类(Classes)       类(class)是一种将数据和函数组织在同一个结构里的逻辑方法。定义类的关键字为 class ,其功能与 C 语言中的 struct 类似,不同之处是 c...
用户420622 2014-02-15 15:43
C++ 学习之路(八) 类之间的继承
类之间的继承     类的一个重要特征是继承,这使得我们可以基于一个类生成另一个类的对象,以便使后 者拥有前者的某些成员,再加上它自己的一些成员。例如,假设我们要声明一系列类型 的多边...
用户420622 2014-02-15 09:32
C++学习之路 (七) 类之间的关系
类之间的关系(Relationships between classes)   1.友元函数(Friend functions)      前面的章节中我们已经看到了对 class 的不同成员存...
用户420622 2014-02-14 10:01
C++学习之路(二)控制台交互
四.控制台交互(Communication through console) 在 C++的 iostream 函数库中,一个程序的标准输入输出操作依靠两种数据流:cin 给输入使用和 cout...
用户420622 2014-02-14 10:00
C++ 学习之路(一)
前言:    大家好,我是来自南京的一名大四学生,专业是电子信息工程。最近在学习Qt的过程中回顾了C++的相关知识,感觉收获很多。这是我第一次发文章,在文章中我将重点关注C++中与C的异同之处...
我要评论
1
10
关闭 站长推荐上一条 /2 下一条