C语言函数指针的应用——利用双线性积分求一个自定义方波函数的谐波分析

简介

如果在一个大型C语言程序中要反复调用函数,而调用的函数又不明确时,函数指针就是一个非常有用的东西。如果你的函数体内可以传递不同的函数,那就非得用函数指针实现不可。下面我就用一个例子给大家分享一下C语言函数指针的妙用。

格式介绍

C语言函数指针的格式为(*function)([参数表列])。函数指针主要有两种使用方法:①用函数指针指向某个函数做选择②当做函数的参数传递,使程序模块化更强,耦合性更弱

代码


    #include <stdio.h>
    #include <math.h>
    #include <ctype.h> 
    #include <malloc.h>
    #include <windows.h>
    #define pi 3.14159265
    double amplify(double (*function)(double x),int n);//双线性积分函数,参数为函数指针、上界、下界 
    double RMS(double (*function)(double x));//对一个函数在周期内求有效值 
    double square_wave(double x);
    double period;//被分析方波的周期
    double time[30]={0};//方波的时间时刻数组,首地址是从0附近的周期最左边的坐标开始的依次改变的电平处的值,只保留一个周期的 
    double level[30]={0};//方波的电平数组,表示与时间区别对应的电平
    int fund_f;//指定傅里叶分解时的基频 
    int count=0;//统计输入个数 
    //以上为声明 
    int main()
    {
    	char t;//用于检测字符是否数字,实现动态输入 
    	int i=0;//扫描计数偏移量
    	int Nc;//截止谐波次数 
    	double *AP=NULL;//用于存放幅值数组的指针 
    	//以上为定义变量部分 
    	printf("***对用户定义的方波进行傅里叶级数展开***\n请输入方波的周期: ");
    	scanf("%lf",&period);
    	fflush(stdin);
    	printf("请输入方波的在(-T/2,T/2)周期改变电平的时间时刻(不含±T/2的时刻,用空格分隔):\n");
    	while((t=getchar())!='\n')
    	{
    		if(isdigit(t)||t=='-')//浮点数都是以负号或者数字开头的 
    		{
    			ungetc(t,stdin);
    			scanf("%lf",time+i);//扫描的浮点数一次存入 
    			count++;//统计输入时间节点的个数 
    			i++; 
    		}
    	 } 
    	 *(time+i+1)=period/2;
    	printf("请输入方波的在上述改变时间时刻对应的电平值\n【说明】第一个电平对应(-T/2,t0),最后一个电平对应(tn,T/2),用空格分隔:\n");
    	fflush(stdin);//循环结束,刷新标准输入口 
    	i=0;//偏移量清零 
    	while((t=getchar())!='\n')
    	{
    		if(isdigit(t)||t=='-')//浮点数都是以负号或者数字开头的 
    		{
    			ungetc(t,stdin);
    			scanf("%lf",level+i);//扫描的浮点数一次存入 
    			i++;
    		}
    	 } 
    	fflush(stdin);//循环结束,刷新标准输入口  
    	printf("请输入傅里叶分解的基频: ");
    	scanf("%d",&fund_f);
    	printf("请输入分析的谐波最高次数: ");
    	scanf("%d",&Nc);
    	AP=(double *)calloc(Nc,sizeof(double));
    	if(AP==NULL)
    	{
    		printf("\n\r意外错误:内存分配失败!\n");
    		return 1;
    	}
    	printf("\n\r动态内存分配成功!\n");
    	 for(i=0;i<=Nc;i++)
    	 {
    	 	AP[i]=amplify(square_wave,i);
    	 	printf("\r正在计算中...%lf%%",100*(float)i/Nc);
    	 }
    	 printf("\r|谐波次数:\t振幅\n");
    	 for(i=0;i<=Nc;i++)
    	 {
    	 	printf("|%d:\t%8.5lf",i,AP[i]);
    	 	if((i+1)%5==0)printf("\n");
    	 }
    	 printf("\r\n|N次谐波含有率如下:\n");
    	 for(i=0;i<=Nc;i++)
    	 {
    	 	printf("|%d:\t%7.3lf%%",i,100*AP[i]/AP[1]);
    	 	if((i+1)%5==0)printf("\n");
    	 }
    	 printf("\n\rRMS=%7.4lf,Fundamental=%7.4lf",RMS(square_wave),AP[1]);
    	 system("pause");
    	return 0;
    } 
    //根据电平数组和时间间隔数组查找对应时间的方波的电平 
    double square_wave(double x)
    {
    	int i;
    	for(i=0;i<count;i++)
    	{
    		if(x<*(time+i))return *(level+i);
    	}
    	return *(level+count);//如果均不是,返回level数组的最后一个值,即[tn,T/2]的值 
    } 
    double amplify(double (*function)(double x),int n)
    {
    	double sin_integral=0,cos_integral=0;//积分值
    	double x0,x1;//双线性积分需要两个变量迭代计算
    	for(x1=-period/2;x1<period/2;x0=x1,x1+=1e-5)
    	{
    		sin_integral+=0.5*1e-5*((*function)(x1)*sin(n*2*pi*fund_f*x1/period)+(*function)(x0)*sin(n*2*pi*fund_f*x0/period));
    		cos_integral+=0.5*1e-5*((*function)(x1)*cos(n*2*pi*fund_f*x1/period)+(*function)(x0)*cos(n*2*pi*fund_f*x0/period));
    	 } 
    	 return sqrt(pow(sin_integral,2)+pow(cos_integral,2))/period;
    }
    double RMS(double (*function)(double x))
    {
    	double integral=0;
    	double x0,x1;//采用双线性积分
    	for(x1=-period/2;x1<period/2;x0=x1,x1+=1e-5)
    	{
    		integral+=0.5*1e-5*(pow((*function)(x1),2)+pow((*function)(x0),2));		
    	}
    	return sqrt(integral/period);	
    } 

分析带阻感负载的三相全桥电路变压器二次侧电流的谐波含量如下:
C语言函数指针的应用——利用双线性积分求一个自定义方波函数的谐波分析