⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ex9.cpp

📁 这里有大量的习题解答
💻 CPP
字号:

     //        第9章   函数指针
//	[例9.1]函数指针间接调用函数
	#include<stdio.h>	
    int max(int x,int y){return x>y?x:y;}
    int min(int x,int y){return x<y?x:y;}
	void main()
	{ int (*f)(int,int)=max;  //定义int (*)(int,int)型的函数指针f并初始化为函数名max
	  printf("%d,%d\t",max(2,3),f(5,4));// max(2,3)是函数的直接调用,f(5,4)相当于max(5,4)
	  f=&min;                    //f获得min的入口地址, min(2,3)是函数的直接调用
      printf("%d,%d\t",min(2,3),f(5,4)); //f(5,4) 是min函数的间接调用
	}      //输出:3,5	2,4	
//	[例9.2] 根据近似公式=[f(a)+f(a+h)+...+f(b)]h求定积分
    #include<stdio.h>	   
    #include <math.h>
    double f(double x){   return exp(x)/(2.5+x*x);  }  
    double g(double x){   return (1+x);       }
    double IntegralEny(double (*f)(double),double a,double b,int n=300)
	{   const double h=(b-a)/n;		double sum=0;	
		  for( double x=a;x<=b;x+=h) sum+=f(x);		 
		 return sum*h;	
	}	//积分函数算法过于简单,不足以解决复杂的收敛性和精度问题。
	double IntegralOne(double a,double b,int n=300)
	{   const double h=(b-a)/n;     double sum=0;	
		  for( double x=a;x<=b;x+=h) sum+=f(x);		 
		 return sum*h;	
	}
	 void main(void)
	 { 	printf("%f\t",IntegralEny(&f,1,2)); 	printf("%f\n",IntegralEny(f,1,2,500));	
	    printf("%f\n",IntegralOne(1,2));	
	    printf("%f\t",IntegralEny(g,1,2));		printf("%f\n",IntegralEny(&g,1,2,600));
	 }
//[例9.3]区间二分法求单变量实函数的根(选讲)
	#include<stdio.h>	
	#include<math.h>
	typedef double real;
	int  single(real(*f)(real),real a,real b,real& x)
	{     const real eps=1.0e-12;
 	     if(f(a)*f(b)>0.0 )   return 0;
 	     for(;;)
		  { x = (a+b) / 2.0;
		   if (f(a)*f(x)<0.0)   b = x;
		   else 	            a = x;
		   if(b-a <= eps) {  x =(a+b)/2.0;   return 1; }	     
		  } //程序要求b>a
	}
	int  muliply(real(*f)(real),real a,real b,int n,real xr[])
	{   const real dx=(b-a)/n;          // const 关键字冻结区间的步长增量dx
	    int m=0;                     //纪录区间的根的个数m
		real x;                      //局部变量x用于传递分区间的实根
	    for(int k=0;k<n;k++)           //从左到右搜寻每一个分区间
		{  b=a+dx;                  //右端点
	      if(single(f,a,b,x)==1) //分区间求根成功
				{    xr[m]=x;             //实根存入数组中
                     m++;                 //根的个数加1
                }
		  a=b;                    //右端点变为下一个迭代中的左端点
		}
		return m;
	}
	real f1(real x){ 		return ((x-2.0)*x-4.0)*x-7.0;}     //三个示范的单变元函数
	real f2(real x){ 		return exp(x)+x-2;		   }
	real fm(real x){ 	return (((x-29.1)*x+196.2)*x+114.2)*x-782.6;   }
	void main(void)
	{   real root;
  	  single(f1,3,4,root);		   printf("f1(%f)=%16.13f\t",root,f1(root));  	 
  	  single(f2,0,2,root); 		   printf("f2(%f)=%16.13f\n",root,f2(root));     
 	  real* const p=new real[4];   //四次多项式最多四个根,因此开辟四个元素的堆空间
	  int m=muliply(fm,0,100,100,p);     //区间[0,100]中搜寻,步长为1
	  for(int k=0;k<m;k++)                       //显示所有求得的根
	       printf("fm(%9.6f)=%016.13f\n",p[k],fm(p[k]));
	  delete []p;    
	}          /////////////程序运行输出结果://///////////////////
//[例9.4]   牛顿迭代法(选讲)
	#include<stdio.h>	
	#include<math.h>
	typedef double real;
    int newtonroot(real(*f)(real),real(*df)(real),real x, real & root)
    {  	 root=88888.8888;          //设置一个醒目的初始值,仅求根成功该值重定义
		const real eps = 1e-15, maxiterations=616, nearzero = 1e-20;
		real  lastx;     
		int i=0;                                // i控制循环的迭代变量
		int erinfo = 0;                           // erinfo循环状态信息亦用于跳出循环
		do{
          //**/ if (fabs(x) > nearzero) {         //**///程序屏蔽0向量解			
			   if (fabs(df(x)) > nearzero)         //算法要求切线刚度不靠近零	        
			    {  lastx = x;
                   x -= f(x) / df(x);        //牛顿法核心迭代公式x = x -f(x) /df(x);
		          if(fabs(x-lastx)<=eps||fabs(f(x))<eps)//逻辑或收敛判断
					{erinfo =1; root=x; }     //收敛成功返回信息1且纪录收敛后的根
	              i++;                         //循环控制次数步进
				}
			    else  erinfo =111;                //切线刚度靠近零返回信息111	
           //**/} else  erinfo = 222;            //**///0向量解返回信息222
		} while ( i < maxiterations && erinfo == 0);   //两个逻辑与约束,终止循环
         if( i == maxiterations)  erinfo = 333;       //超过最大迭代次数返回信息333
		 return erinfo;
     }                                        //程序尽量在else分支下处理异常
	real funct(real x)  {	 return ((x-2.0)*x-4.0)*x-7.0;		}
	real dfunct(real x)  {	 return (3.0*x-4.0)*x-4.0;		}	
	void main(void)
	{  real root;
	   switch(newtonroot(funct,dfunct,4,root))
	  { case 111:		printf("df/dx is near zero\n");               break;
	   //**/case 222:  printf("root may be near zero\n");            break;
	   case 333:      printf("iteration number passed max\n");      break;
	   case  1:      printf("funct(%f)=%19.17e\n",root,funct(root));break;
	   }
  }					//输出:funct(3.631981)=2.66453525910037570e-015
//[例9.5]指针与重载函数,函数指针根据重载函数名的入口类型匹配
	#include<stdio.h>                    
	double& max(double& x,double& y){printf("&"); return x>y?x:y; }//引用版本求极大值
	double* max(double* x,double* y){printf("*"); return *x>*y?x:y; }//指针版本求极大值
    double* (*pmax)(double* ,double*) =max;         //pmax获得指针版本的max地址
	double& (*rmax)(double&,double& )=max;        // rmax获得引用版本的max地址
	void main(void)
	{   const char* fmt="max(x=%2.0f,y=%2.0f)=%2.0f;";
		double x=10, y=10;  
		 rmax(x,y)+=10;                  // rmax(x,y)等价于(*rmax)(x,y)
		printf(fmt,x,y,(*rmax)(x,y));
		*pmax(&x,&y)+=10;              //*pmax(&x,&y)等价于*(*pmax)(&x,&y)
		printf(fmt,x,y,*(*pmax)(&x,&y));		
	    typedef double* (*PFD)(double* ,double*);     //声明函数指针别名PFD
	    rmax=(double&(*)(double&,double&))(PFD)max;//取重载函数地址并类型转换
   	    *(( PFD)rmax)(&x,&y)+=10;                 //调用时函数指针予以复原
	    printf(fmt,x,y,*(*(( PFD)rmax))(&x,&y));	
	}   //输出:&&max(x=10,y=20)=20; **max(x=10,y=30)=30;**max(x=10,y=40)=40
//[例9.6]返回函数指针的函数,工程文件分为两个源程序a.cpp和b.cpp
    #include<stdio.h>//	main程序在a.cpp源文件中
    typedef void (*VFV)(void); 
    typedef void (*VFI)(int);
	extern inline VFV 	GetFunct(int); //不能写成extern void (*)(void) 	GetFunct(int);	
    VFV pfm[]={GetFunct(3),GetFunct(2),GetFunct(1)};//定义全局函数指针数组并初始化
	void main()
	{ 	 VFV pfn=GetFunct(1);
	     pfn();   (*GetFunct(2))(); GetFunct(3)();
         ((VFI)pfm[0])(2);  (*pfm[1])();pfm[2]();
	}     //输出: f1();		f2();		f3();   f3();   f2();	f1();
   #include<stdio.h>	//如下程序在b.cpp源文件中
   static void f1(void)		{	printf("f1();\t");	}
   static void f2(void)		{	printf("f2();\t");	}
   static void f3(int)		   {	printf("f3();\t");	} 
   typedef void (*VFV)(void); //内部连接属性的函数通过extern函数过渡到其它模块  
   extern inline  VFV 	GetFunct(int m)             //返回函数指针的函数GetFunct
	{	if(m==1)     return f1;                   //返回类型为 void (*)(void)
	    else 	if(m==2) return &f2;
	    else         return (void (*)(void))&f3;    //函数指针的强制类型转换
	}                                         // GetFunct返回静态函数的地址
//	[例9.7] 多路分支模拟函数菜单驱动
	#include<stdio.h>	
	void f1(long x)	{	printf("f1(%d);\t",x);	}
	void f2(long y)		{	printf("f2(%d);\n",y);	}
	void main(void)
	{ 	void (*ppfn[2])(long) ;     //定义函数指针数组ppfn[2]
	    ppfn[0]=&f1;  ppfn[1]=&f2;
	    void (**pfp)(long)=ppfn;
		 (*pfp++)(3);  (**pfp)(2);   
		printf("请输入一个整数:");  int k;
		scanf("%d",&k);                     //程序运行结果如下:
		switch(k)                           //f1(3); 	f2(2);
		{  case 1: (*ppfn[0])(k);  break;        //请输入一个整数:1(
	      case 2:   ppfn[1](k);  break;         // f1(1);
  		  default :break;
		}     
	}
  //  [例9.8] 循环实现函数的动态绑定
	#include<stdio.h>	
	typedef   void  (*PPFUNC)(long);//函数指针类型别名声明语句
	void f1(long x)   {  printf("f1(%d);\t",x);  }
	void f2(long y)   {  printf("f2(%d);\t",y);  }
	void main(void)
    {  PPFUNC fn[]={&f1,f2};  //等价于void (*fn[])(long)={f1,f2};
	   int num_fn=sizeof(fn)/sizeof(fn[0]);
	   int k=0;
      do                                      //运行结果如下:
      {  (*fn[k])(k);                            // f1(0);请输入一个整数:1(
	     printf("请输入一个整数:");             // f2(1);请输入一个整数:2(
	     scanf("%d",&k);                        /*程序退出循环*/
	   }while(0<=k && k< num_fn);
    }
//[例9.9] 函数指针的指针形参和引用形参(多学时选讲)
    #include<stdio.h>	
    typedef void (*VFI)(int);
    void f(int x)		{	printf("f(%d);\t",x);	    }
    void g(int x)		{	printf("g(%d);\n",x);	}	
    void  	SetFunctB(void (**ppf)(int),int m)    //函数指针的指针形参ppf
	{	if(m==1)    *ppf= f;         //ppf匹配void (*)(int)型的函数指针的地址
	    else 	        *ppf= &g;	  //*ppf是void (*)(int)型的函数指针
	}
    void  	SetFunctA(VFI& pf,int m)   //函数指针的引用形参pf
	{	if(m==1) pf= f;              //形参pf匹配void (*)(int)型的左值函数指针
	    else 	    pf= &g;	  
	}
	void main()
	{ 	 VFI fp,gp;
	     SetFunctA(fp,1);		(*fp)(10);
	     SetFunctB(&gp,2);		gp(20);
	}						//输出结果:f(10);		g(20);






⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -