首页 > 其他分享 >第19节 指针与函数

第19节 指针与函数

时间:2024-07-06 11:28:47浏览次数:18  
标签:10 函数 19 double int 引用 指针

文章目录

第19节 指针与函数

1.指针作为函数的参数
1、指针作为函数的参数
►指针最重要的应用是作为函数参数,它使得被调函数除了返回值之外,能够将更多的运算结果返回到主调函数中。 
    ►因此: 
    	►指针是函数参数传递的重要工具。
    
►函数形参可以是指针类型,一般形式为: 
    返回类型 函数名(指向类型 *指针变量名,...) 
    { 
        函数体 
    }
【例19.1】设计一个函数swap,用于交换两个变量的值。 
    1 #include <iostream> 
    2 using namespace std; 
    3 void swap(int *p1, int *p2) 
    4 { 
    5 		int t; 
    6 		t=*p1 , *p1=*p2, *p2=t; //交换*p1和*p2 
    7 } 
    8 int main() 
    9 { 
    10 		int a, b; 11 cin>>a>>b; //输入 
    12 		if (a>b) swap(&a, &b); 
    13 		cout<<"min="<<a<<",max="<<b; //输出 
    14 		return 0; 
    15 }
【例19.1】以下方法是错误的。 
    1 #include <iostream> 
    2 using namespace std; 
    3 void swap(int p1, int p2) 
    4 { 
    5 		int t; 
    6 		t=p1 , p1=p2, p2=t; 
    7 } 
    8 int main() 
    9 { 
    10 		int a, b; 
    11 		cin>>a>>b; 
    12 		swap(a, b); 
    13 		cout<<"min="<<a<<",max="<<b; 
    14 		return 0; 
    15 }
►通过将指针作为函数参数的方法,既可以返回多个运算结果,又避免了使用全局变量。
【例19.2】计算a和b的平方和、自然对数和、几何平均数、和的平方根。 
    1 #include <iostream> 
    2 #include <cmath> 
    3 using namespace std; 
    4 double fun(double a, double b, double *sqab, double *lnab, double *avg) 
    5 { 
    6 		*sqab=a*a+b*b; //*sqab返回平方和 
    7 		*lnab=log(a)+log(b); //*lnab返回自然对数和 
    8 		*avg=(a+b)/2; //*avg返回几何平均数 
    9 		return (sqrt(a+b)); //函数返回和的平方根 
    10 } 
    11 int main() 
    12 { 
    13 		double x=10,y=12,fsq,fln,favg,fsqr; 
    14 		fsqr=fun(x, y, &fsq, &fln, &favg); 
    15 		cout<<x<<","<<y<<","<<fsq<<","<<fln<<","<<favg<<","<<fsqr<<endl; 
    16 		return 0; 
    17 }
2、数组作为函数的参数
►1.(一维或多维)数组作为函数的形参,例如: 
        double average(double *a, int n) 
        { … //函数体 } 
    ►函数调用形式如下: 
        double X[100], f; 
        f = average(X, 100);
         
    【例19.3】编写函数average,返回数组n个元素的平均值。 
       1 #include <iostream>
       2 using namespace std;
       3 double average(double *a, int n)
       4 { // 等价于average(double a[], int n)
       5     double avg = 0.0, *p = a;
       6     int i;
       7     for (i = 1; i <= n; i++, p++)
       8         avg = avg + *p; // 等价于avg=avg+p[i]
       9     return n <= 0 ? 0 : avg / n;
       10 }
       11 int main()
       12 {
       13     double x[10] = {66, 76.5, 89, 100, 71.5, 86, 92, 90.5, 78, 88};
       14     cout << "average=" << average(x, 10) << endl;
       15     return 0;
       16 }
         
    ►要想在子函数中改变主调函数中的数组元素,实参与形参的对应关系有如下4种,这4种情况作用相同。 
        ►(1)形参和实参都用数组名,例如:
                void fun(int x[100], int n); //函数原型 
                int a[100]; 
                fun(a, 100); //函数调用
        ►(2)形参用指针变量,实参用数组名,例如:
                void fun(int *x, int n); //函数原型 
                int a[100]; 
                fun(a, 100); //函数调用
        ►(3)形参与实参都用指针变量,例如: 
                void fun(int *x, int n); //函数原型 
                int a[100], p=a; 
                fun(p, 100); //函数调用
        ►(4)形参用数组,实参用指针变量,例如:
                void fun(int x[100], int n); //函数原型 
                int a[100], p=a; 
                fun(p, 100); //函数调用

►2.字符指针变量作为函数形参 
    ►将一个字符串传递到函数中,传递的是地址,则函数形参既可以用字符数组,又可以用指针变量,两种形
    式完全等价。在子函数中可以修改字符串的内容,主调函数得到的是变化后的字符串。
    
    【例19.4】自定义函数实现strcpy函数的字符串复制功能。 
        1 #include <iostream> 
        2 using namespace std; 
        3 char *stringcpy(char *strDest, const char *strSrc) 
        4 { 
        5 		char *p1=strDest; 
        6 		const char *p2=strSrc; 
        7 		while (*p2!='\0') *p1=*p2, p1++ , p2++; 
        8 		*p1='\0'; 
        9 		return strDest; //返回实参指针 
       10 }
       11 int main() 
       12 { 
       13 		char s1[80],s2[80],s3[80]="string="; 
       14 		cin>>s1; //输入字符串 
       15 		stringcpy(s2,s1); //复制s1到s2 
       16 		cout<<"s2:"<<s2<<endl; 
       17 		stringcpy(&s3[7],s1); //复制s1到s3的后面 
       18 		cout<<"s3:"<<s3<<endl; 
       19 		return 0; 
       20 }
2.引用和指向函数的指针
3、引用
直接访问--►通过对象名称直接访问对象,优点是直观,操作哪个对象一目了然,缺点一个函数内部
		 不能使用另一个函数的局部变量; 
    
间接访问--►通过指针(或地址)间接访问对象,优点是无所不能,缺点是程序中大量出现的间接访
		 问,实在分不清具体是哪个对象,需要通过上下文去分析。 
    
►C++扩充了C语言对象访问方式,提供了引用访问。通过引用访问对象,结合了按名访问和按地址访
问各自的优点,非常适合作为函数参数。
    
►1.引用作为函数参数
	►简单地说,引用(reference)就是一个对象的别名(alias name),其声明形式为:
    	引用类型 &引用名称=对象名称 , ......; 
		int x; //定义整型变量x
		int &r=x; //声明r是x的引用
	►在C++中,引用全部是const类型,声明之后不可更改(即不能再是别的对象的引用)。

►引用的规则
	►(1)声明一个引用类型变量时,必须同时初始化它,声明它是哪个对象的别名,即绑定对象。例如:
		int &r; //错误,引用是const类型,必须在声明时初始化
		int x, &r=x; //正确 声明r是x的引用
	►(2)不能有空引用,引用必须与有效对象的内存单元关联。
	►(3)引用一旦被初始化,就不能改变引用关系,不能再作为其他对象的引用。例如:
		int x, y; //定义整型变量x,y
		int &r=x; //正确 声明r是x的引用
		int &r=y; //错误 r不能再是别的对象的引用
	►(4)指定类型的引用不能初始化到其他类型的对象上,例如:
		double f; //定义浮点型变量f
		int &r=f; //错误 r值整型的引用,不能绑定到浮点型的对象上
	►(5)引用初始化与对引用赋值含义完全不同,例如:
		int x; //定义整型变量x 
		int &r=x; //初始化 指明r是x的引用,即将r绑定到x 
		r=100; //引用赋值100赋值到r绑定的内存单元中(即x)
	►(6)取一个引用的地址和取一个对象的地址完全一样,都是用取地址运算。例如:
        int x, &r=x; //定义整型变量x,y 
        int *p1=&x; //p1指向x 
        int *p2=&r; //p2指向r,本质上指向x

►引用作为函数形参 
    ►C++之所以扩充引用类型,主要是把它作为函数形参,使得C++中给一个函数传递参数有三种方法: 
        ►①传递对象本身; 
        ►②传递指向对象的指针; 
        ►③传递对象的引用。

【例19.5】变量、指针、引用作为函数参数比较。 
    1 //程序① 传递对象本身 
    2 #include <iostream> 
    3 using namespace std; 
    4 //对象作为函数形参 
    5 void swap(int a,int b) 
    6 { 	int t; 
    7 		t=a, a=b, b=t; 
    8 } 
    9 int main() 
   10 { 	int x=10, y=20; 
   11 		swap(x,y); 
   12 		cout<<x<<","<<y; 
   13 		return 0; 
   14 }
***************************************
    1 //程序② 传递对象的指针 
    2 #include <iostream> 
    3 using namespace std; 
    4 //指针作为函数形参 
    5 void swap(int *a,int *b) 
    6 { 	int t; 
    7 		t=*a, *a=*b, *b=t; 
    8 } 
    9 int main() 
   10 { 	int x=10, y=20; 
   11 		swap(&x,&y); 
   12 		cout<<x<<","<<y; 
   13 		return 0; 
   14 }
***************************************
    1 //程序③ 传递对象的引用 
    2 #include <iostream> 
    3 using namespace std; 
    4 //引用作为函数形参 
    5 void swap(int &a,int &b) 
    6 { 	int t; 
    7 		t=a, a=b, b=t; 
    8 } 
    9 int main() 
   10 { 	int x=10, y=20; 
   11 		swap(x,y); 
   12 		cout<<x<<","<<y; 
   13 		return 0; 
   14 }

►显然,函数引用传递方式也可以实现多个数据结果返回到主调函数中,其功能与指针方式相同。但指针方式返回数
据结果必须: 
    ►①实参为地址,即进行“&”取地址运算; 
    ►②形参分配指针变量接受实参地址; 
    ►③函数内部使用指针间接访问,即进行“*”间接访问运算。而引用传递方式把这个过程简化了。 
    
►使用引用作为函数形参,比使用指针变量简单、直观、方便,特别是避免了在被调函数中出现大量指针间接访问时,
所指对象究竟是哪个具体对象伤脑筋的问题,从而降低了编程的难度。
    
►引用作为函数返回值 
    ►函数的返回值可以是引用类型,即函数返回引用,其定义形式为: 
        引用类型& 函数名(形式参数列表) 
        { 
            函数体 
        }
【例19.6】引用作为函数返回值举例。 
    1 //程序① 函数返回值 
    2 #include <iostream> 
    3 using namespace std; 
    4 int max(int a,int b) 
    5 { return (a>b?a:b); } 
    6 int main() 
    7 { 	int x=10,y=20,z; 
    8 		z = max(x,y); 
    9 		cout << z; 
   10 		return 0; 
   11 }
***************************************
    1 //程序② 函数返回指针 
    2 #include <iostream> 
    3 using namespace std; 
    4 int* max(int a,int b) 
    5 { return (a>b? &a:&b); } 
    6 int main() 
    7 { 	int x=10,y=20,*z; 
    8 		z = max(x,y); 
    9 		cout << *z; 
   10 		return 0; 
   11 }
*************************************** 
    1 //程序③ 函数返回引用 
    2 #include <iostream> 
    3 using namespace std; 
    4 int& max(int &a,int &b) 
    5 { return (a>b? a:b); } 
    6 int main() 
    7 { 	int x=10,y=20,z; 
    8 		z = max(x,y); 
    9 		cout << z; 
   10 		return 0; 
   11 }

►可以看出,函数返回引用与函数返回值有重大区别,它不是返回一个临时对象,而是相当于返回实体对象本身。正
因为如此,函数返回引用可以作为左值。例如: 
    int& fun(int &a,int &b) 
    { return (a>b? a:b); } 
    int x=10,y=20,z=5; 
    fun(x,y)=z; //调用fun函数后相当于y=z; 
    cout << y;
4、指向函数的指针
►函数是实现特定功能的程序代码的集合,实际上,函数代码在内存中也要占据一段存储空间(代码区内),这段存
储空间的起始地址称为函数入口地址。C++规定函数入口地址为函数的指针,即函数名既代表函数,又是函数的指针
(或地址)。
    
►C++允许定义指向函数的指针变量,定义形式为: 
    返回类型 (*函数指针变量名)(形式参数列表),...; 
►它可以指向如下形式的函数: 
    返回类型 函数名(形式参数列表) 
    { 
        函数体 
    }
    int (*p)(int a, int b); //定义函数指针变量

►使函数指针指向函数 
	►可以将函数的地址赋值给函数指针变量,形式为
    	函数指针变量 = 函数名; 
	►它要求函数指针变量与指向函数必须有相同的返回类型、参数个数、参数类型。
        
    ►例如假设: 
        int max(int a, int b); //max函数原型 
        int min(int a, int b); //min函数原型 
        int (*p)(int a, int b); //定义函数指针变量 
    ►则
        p=max; 
    ►称p指向函数max。它也可以指向函数min,即可以指向所有与它有相同的返回类
    型、参数个数、参数类型的函数。  

►通过函数指针调用函数 
	►对函数指针间接引用即是通过函数指针调用函数,一般形式为: 
        函数指针(实参列表) 
	►通过函数指针调用函数,在实参、参数传递、返回值等方面与函数名调用相同。例如: 
        c=p(a,b); //等价于c=max(a,b);

►函数指针的用途 
    ►指向函数的指针多用于指向不同的函数,从而可以利用指针变量调用不同函数,相当于/*将函数调用由静态方
    式(固定地调用指定函数)变为动态方式(调用哪个函数是由指针值来确定)。*/熟练掌握函数指针的应用,有
    利于程序的模块化设计,提高程序的可扩展性。
    
【例19.7】编写程序计算如下公式。
    说明:这里用梯形法求定积分M的近似值。如图所示,求 f(x) 的定积分就是求f(x)曲线与x轴包围图形的面积,
    梯形法是把所要求的面积垂直分成n个小梯形,然后面积求和。

<img src="Typora-picture/%E5%BE%AE%E4%BF%A1%E6%88%AA%E5%9B%BE_20240706103911.png" alt="微信截图_20240706103911 #pic_center=50x10/>
在这里插入图片描述

    1 #include <iostream> 
    2 #include <cmath> 
    3 using namespace std; 
    4 double integral(double a,double b,double (*f)(double x)) 
    5 { //求定积分 
    6 		int n=1000, i; 
    7 		double h, x, s=0.0; 
    8 		h=(b-a)/n; 
    9 		for(i=1;i<=n;i++) { 
   10 			x=a+(i-1)*h; 
   11 			s=s+(f(x)+f(x+h))*h/2; //调用f函数求f(x)、f(x+h) 
   12 		} 
   13 		return s; 
   14 }
   15 double f1(double x) 
   16 { 	return 1+x; 
   17 } 
   18 double f2(double x) 
   19 { 	return exp(-x*x/2); 
   20 } 
   21 double f3(double x) 
   22 { 	return x*x*x; 
   23 } 
   24 int main() 
   25 { 
   26 		double a,b; 
   27 		cin>>a>>b; 
   28 		cout<<(integral(a,b,f1)+integral(a,b,f2)+integral(a,b,f3))<<end l;
   29 		return 0; 
   30 }

标签:10,函数,19,double,int,引用,指针
From: https://blog.csdn.net/m0_69088645/article/details/140225874

相关文章

  • 字符串函数库的经典使用学习
    <?php//1.单引号定义字符串//2.双引号定义字符串//3.定界符定义字符串//1.单引号定义字符串//echo'thisis'my'mother';echo'thisis\'my\'mother<br>';//单引号不能解析转义符\n换行\t缩进echo'this\nisasimple\tstr......
  • 51单片机定时器实现delay函数
    参考内容:不记得原作地址了,很尴尬啊,1.确定时钟周期、机器周期。时钟周期由单片机的晶振频率Fclk决定。那么时钟周期就是1/Fclk(比如:11.0592MHz)。确定单片机的机器周期是n个时钟周期(n在51单片机下一般是12)。2.确定需要单次定时器最大的计时时间长度如果是16位的计数器,16位最大......
  • matlabGUI绘制一个函数与其导数的图像
    ......
  • 【三变量联合分布函数copula】利用AIC BIC确定单变量最优拟合函数、利用AIC确定三变量
            ......
  • [每日一题] - CF1982E
    校内作业多,一直忘记写blog现在开始补上量赛后几天秒掉了,场上真是困糊涂了,没想到分治#include<bits/stdc++.h>usingnamespacestd;constintmod=1e9+7;#definelllonglong#definenodepair<int,pair<ll,ll>>#definemp(x,y,z)make_pair(x,make_pair(y,z))#definefi......
  • Mysql中常用函数的使用示例
    场景基础知识回顾:mysql中常用函数的使用示例。注:博客:https://blog.csdn.net/badao_liumang_qizhi实现数学函数--ABS(x)返回x的绝对值SELECTABS(-1),ABS(2);--PI()返回圆周率SELECTPI();--SQRT(x)返回非负数x的二次方根SELECTSQRT(4);--MOD(x,y)返回x被y除之后的余......
  • 函数进阶应用1
    VLOOKUP函数返回多列结果通过混合引用,match函数查找以及Vlookup函数,使用填充柄拖拽行列填充操作演示:说明首先我们可以写一个普通的VLOOKUP函数通过match函数找到要填充的符合条件的内容所在单元格的位置在拖拽时,分析哪些需要绝对引用,哪些需要混合引用,这里请参考九九......
  • 【leetcode】双指针算法题
    文章目录1.算法思想2.移动零3.复写零方法一方法二4.快乐数5.盛水最多的容器方法一(暴力求解)方法二(左右指针)6.有效三角形的个数方法一(暴力求解)方法二(左右指针)7.两数之和8.三数之和9.四数之和1.算法思想常见的双指针有两种形式,⼀种是左右指针,⼀种是快慢指针。左右......
  • 可视化二维函数的拉普拉斯算子 - 使用有限差分法来近似计算二维标量函数的拉普拉斯算
    可视化二维函数的拉普拉斯算子-使用有限差分法来近似计算二维标量函数的拉普拉斯算子flyfish算子(Operator)是指的是一个将函数、向量或其他对象映射到另一对象的数学实体。简单来说,算子就是一种“操作”或“变换”,它把一个输入(通常是函数或向量)变换成另一个输出。算子可......
  • 【LinuxC语言】手撕Http协议之accept_request函数实现(一)
    文章目录前言accept_request函数作用accept_request实现解析方法根据不同方法进行不同操作http服务器响应格式unimplemented函数实现总结前言在计算机网络中,HTTP协议是一种常见的应用层协议,它定义了客户端和服务器之间如何进行数据交换。在这篇文......