计算机程序设计C++ 第五周

发布于 2020-03-14  130 次阅读


问题的模块化求解

主要内容

模块化程序设计
函数定义和声明
函数调用
递归函数
内联函数
函数重载
变量的作用域和存储类型

模块化程序设计

一个程序由若干模块组成
函数的概念 main() 函数
由多个函数组成的程序
程序的执行循序: 程序总是从主函数开始执行

库函数

标准输入输出函数 #include<iostream>
数字库函数 #incude<cmath>
字符串处理函数 #include<sring>
... ...

用户定义函数

C++中允许用户自定义函数


函数的定义和声明

函数的定义

函数定义的一般格式

<函数值类型> <函数名> (<形式参数表>)  //函数头
{
    语句序列
}

一个函数通常由函数头和函数体两部分组成

  • 函数头中通常包含函数名 形式参数表以及函数的返回值类型,其中形式参数表必须包含在一对圆括号中。
  • 函数体由一对花括号括号括起的语句序列组成。

函数值类型 即函数的返回值类型

  1. 返回简单类型
  2. 返回结构类型
  3. 返回指针类型
  4. 返回引用类型

注意: 如果函数无任何返回值类型,这时函数的返回值类型应标记为void。void类型称为无类型或空类型。

形式参数表(即形参表)

函数的参数表用于实现函数间的数据联系。形参的说明格式:类型 参数名
当有多个形参时,各参数说明直间用逗号分隔。如 类型 形参名1, 类型 形参名2,.....
注意 每个形参必须同时给出形参的类型和名称。

  • 定义函数时需要考虑设置形参,形参的个数及类型根据需要设定(也可以没有参数,称为无参函数) 。
  • 形参可以接收主调函数传递的实参的值。在参数中对形参进行处理,并将处理结果返回到主调参数。
  • 形参是在函数调用时分配存储空间,同时接收实参的值。当函数执行结束后,系统将自动释放形参所分配的存储空间。因此,形参属于函数的局部变量,只能在该函数中使用。
  • 当形参为引用类型或指针类型时,利用形参不仅可以访问实参的值,还可以改变实参的值。

函数体

  • 由{}括起来的语句序列结构,是实现函数结构功能的主体。
  • 函数的编写过程类似与主函数。在函数中可以调用其他函数。
  • 在函数体中,使用return语句返回函数的执行结果。
    • 语句格式:return 表达式; 其中表达式类型应与函数返回值类型一致
  • 对于无返回值的函数,也可使用return;将控制返回到主调函数。

说明 在一个函数中允许出行多个return语句,但在函数执行期间只能有一个语句起做用。在函数体的最后位置,一个无返回值的return;语句可以省略。

例 编写半径为r的圆的面积的函数area。

doube area(doube r){
    doube s;
    s=3.14*r*r;
    return s;
}

函数的声明

  • 在C++中,程序编译的单位是源程序文件(即源文件),一个由多个函数构成的程序可以组织存放在一个或多个源文件中。
  • 在源文件中,函数之间的排列顺序美没有固定要求,但要满足“先定义后使用”的原则。
  • 对于标准库函数的使用,在程序开头使用#include命令将所需要的头文件包含进来即可。
  • 对于用户自定义的函数,要么在调用之前定义,要么在调用之前作函数声明。
  • 函数的声明是指函数在被调用之前对函数的类型、名称以及参数等信息所作的说明。格式
    类型名 函数名 (类型1 形参1,类型2 形参2,.....);或
    类型名 函数名(类型1,类型2,.....); //可省略形参

在形式上就是在函数定义的首部后加分号构成。函数声明说明了函数所采用的形式,称为函数原型。


函数的调用格式

函数定义后并不能自定执行,必须通过函数调用来实现函数的功能。
函数调用,即控制执行某个函数。
C++中,主函数可以调用其他子函数,而其他函数之间也可以互相调用。

函数调用的一般格式
<函数名> (<实际参数表>) //有参调用
<函数名> () //无参调用
实参表与形参表中参数的个数、类型、次序应保持一致。
当调用无参函数时,后面的圆括号不可省略。

实参的几种形式

  • 形参为简单类型变量,对应的实参可以是:常量、变量及表达式。
  • 形参为数组,对应的实参为数组(名)。
  • 形参为结构类型,对应的实参为结构类型变量。

函数调用形式1
函数调用作为一个独立的语句(用于无返回值的函数)
调用形式
函数名 (实参表);函数名 ();
函数调用形式2
函数调用出现在表达式中。

函数的嵌套调用
函数的嵌套调用是指函数在调用一个函数的过程中,被调用的函数又调用了另一个函数。


参数的传递方式

C++中参数有三种传递方式
* 值传递
* 引用传递
* 指针传递

值传递

调用时,将实参的值传递给对应的形参,这就是值传递。
由于形参有自己独立的存储空间,又作为函数的局部变量使用,因此在函数中对形参的任何修改都不会改变实参变量的值。
好处:减少函数之间的数据依赖,增强函数自身的独立性。
注意:函数的类型声明为简单类型或结构类型变量,实参与形参将采用值方式传递。
在值传递过程中,改变形参的值并不会改变实参的值。

void swap(int x,int y){
    int tmp;
    tmp=x;
    x=y;
    y=tmp;
}

引用传递

引用 是一种特殊的变量,他被认为是一个变量的别名。
引用定义的格式如下:
<数据类型> &<引用名>=<目标变量名>;
其中:&为引用(变量)的标志符号,<引用名>是一个标识符。<数据类型><目标变量>的类型。
例如 int a,&b=a;
该例说明了a是一个整型变量,b是一个引用整型变量a的引用,即b是a变量的一个别名。这时,使用a与b是等价的。

对引用的说明:

  • 定义一个引用,其实是为目标变量起一个别名。引用并不分配独立的内存空间,它与目标变量共用其内存空间。
  • 定义一个引用(变量)时,如果该引用不是作为函数的参数或返回值,则必须提供该引用的初值(即必须提供引用的目标变量名)。
  • 使用引用与使用目标变量效果相同。

引用传递
为实现引用传递,这时函数的形参应定义为引用类型变量,而对应的实参为变量名,该变量作为引用的目标变量名。
函数调用时,作为形参的引用变量并不分配新的内存空间,它将作为实参变量的别名与其共用内存。

使用引用参数可以直接操作实参变量,从而实现通过修改形参的值而达到修改对应实参值的目的。
通过设置多个引用参数,可以通过函数中带回多个结果值。
说明:引用作为函数形参,其引用的目标变量默认为调用该函数时对应的实参变量名,所以,在定义函数时,对于引用类型参数不必提供引用的初值。

void swap(int &x,int &y){
    int tmp;
    tmp=x;
    x=y;
    y=tmp;
}

为形参指定默认值

C++允许在函数定义时为形参指定默认参数值。这样,在函数调用时,如果没有提供实参,则形参自动使用默认值。
如:void f(int x=0,int y=0);

函数原型 正确or错误
void f(int i,int j=2,int k=3); 正确
void f(int i,int j,int k=3); 正确
void f(int i=1,int j,int k=3); 错误
void f(int i=1,int j,int k); 错误

注意 指定参数默认值可以在函数定义中进行,也可以在函数原型中进行。通常写在函数名在程序第一次出现的位置。


数组名作为函数的参数

  • 数组元素作实参,对应的形参为变量,一次传递一个元素,采用值传递。
  • 数组名作实参,对应的形参为一-个数组,一次传递整个数组。
  • 数组作参数,其参数传递可理解为形参数组与实参数组共用同一数组空间(即共用实参数组空)。因此,在函数中,使用形参数组就是在使用实参数组,改变形参数组元素的值就是在改变实参数组元素的值,这一点与引用传递非常相似。

一维数组的传递

声明格式: <类型> <数组名>[]
其中,[]中可以省略数组的长度。
对应的实参应为同类型的一维数组名。(仅用数组名)

数组名做函数参数

二维数组传递

声明格式: <类型> <数组名>[][<列数>]
其中:<列数>作为常数,不能省略,行数可以省略。
调用时的实参应为同类型的二维数组名。
注意:用做实参的二维数组,其列数必须与形参中的<列数>相同。


结构体变量作为函数的参数

  • 实参为结构体类型变量
  • 形参为同类型的结构变量
  • 传递方式为值传递
    在函数调用时,系统首先为形参变量( 即结构变量)分配存储空间,接着将实参变量(结构变量)各成员值传递给形参变量的各个成员。对形参成员的修改不会影响实参成员值的变化。

例如:
定义一个结构体类型:

struct student{
    int stno;
    char name[20];
    int age;
}
void print(student s){
    cout<<s.stno<<endl;
    cout<<s.name<<endl;
    cout<<s.age<<endl;
}
int main(){
    student stu={1001,"li",19};
    print(stu);   //实参为结构变量
    return 0;
}

实例

求三个实数中的最大数

#include<iostream>
using namespace std;
double maxThree(double a,double b,double c){
    double max;
    max=a>b?a:b;
    max=max>c?max:c;
    return max;
}
int main(){
    double x1,x2,x3,max;
    cout<<"x1 x2 x3 ?"<<endl;
    cin>>x1>>x2>>x3;
    max=maxThree(x1,x2,x3);
    cout<<"最大数: "<<max<<endl;
    return 0;
}

我们都要做生活的高手。