C语言函数指针的应用——自制谐波分析软件

文章目录

  • 函数指针简介
  • 格式介绍
  • 颜色头文件
  • 计算机仿真
    • 使用说明
    • 完整代码
    • 部分效果图

函数指针简介

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

格式介绍

格式为:【基类型】(*function)([参数表列])
C语言函数指针就是一个指向函数地址的指针,它和普通的指针一样也具有基类型,例如int *p,double *q,void *malloc与普通指针不同的是,它指向的不是特定类型的变量,而是函数地址,因此它后面有函数的参数表列。使用的时候需要注意,由于指针运算符比括号运算符的优先级低,因此需要把(*function)括起来(否则就是返回指针的函数)。C语言的语法比较复杂,举一个函数指针的例子:

#include <stdio.h>
#include <stdbool.h>
int max(int a,int b);//最大值函数
int min(int a,int b);//最小值函数
int main()
{int a,b;int (*p)(int,int);//函数指针pbool choice;char c[4];//字符串printf("Please enter two integer(separate by space):  ");scanf("%d%d",&a,&b); printf("Please choose a function(0: max,1: min):  ");scanf("%d%d",&choice);if(choice){p=min;c="min"}else {p=max;c="max"};//让函数指针指向选择的函数(地址)printf("%s=%d",c,p(a,b));//完成选择函数的输出return 0;
}

函数指针主要有两种使用方法:

  1. 用函数指针指向某个函数做选择(类似于上述的例子)
  2. 当做函数的参数传递(类似于下面的代码),使程序模块化更强,耦合性更弱当做函数的参数传递,使程序模块化更强,耦合性更弱

下面是我编写的一个计算一个指定方波的程序,里面的双线性积分函数对每一次谐波变量(int n)都一个返回谐波分量double amplify,在这里用到了函数指针,传递一个方波的函数给这个积分函数,如果以后这个函数不是方波而是其他函数,增添和修改代码都会非常方便!
在程序里面我指定的值是电力电子课程里面的三相全桥整流电路带阻感性负载的变压器二次侧电流波形的方波(一周期脉动6次的交流电平),方波应该没有2次和3次谐波,这样只剩下了1次谐波和6k±1(k∈N*)次谐波,每次谐波含有率(和1次谐波的比值)为1/(6k±1),可以看到后面附图里面确实非常准确,1,0.2,0.14286,…分别是1,1/5,1/7,…!
如果我们分析三相电压型桥式逆变电路的Unn’中点电压波形(一周期脉动6次的交流方波信号),可以得出同样的结果。为了让输出的谐波分析更加的美观,我们让谐波含有率低于1e-4的所有的次谐波都标蓝,剩下的白色的才是真正含有的谐波,供我们进行计算机仿真实验验证。

颜色头文件

以下链接为C语言彩色打印字符的相关头文件及其说明:

【博客链接】

计算机仿真

使用说明

在程序的开始界面输入时刻表和对应的电平表,输入分析基频以及最高的分析谐波次数,程序即可进入运算状态。由于使用的是CFT(连续傅里叶积分),可能计算会有点慢,大概3秒算10次谐波。如果谐波含有率很低会用蓝色标识出来,其余的谐波用白色标注,代表实质有的谐波含量,方便大家发现规律。输入时刻表列和电平表列的规则如下:
如果一个方波的电平以-1和1两个电平变化,并且周期为π,则输入周期为π,改变电平的时刻表列为0(不包括2个端点),电平表列为-1 1.
如果一个方波的电平以-1,0,1,0,-1,0,…变化,正负电平的持续时间是0电平的2倍,周期为π,则电平的时刻表列为-5π/12,-π/12,π/12,5π/12(不包括2个端点),电平表列为0 -1 0 1 0。
由于输入的时刻表列不包括两个端点,因此时刻表列总是比电平表列多一个数值,但是如果时刻表列加上2个端点时刻,正好形成和电平表列数目一样多的时间段和电平表列相对应。输入规则就是这样的。

完整代码

//#include <stdio.h>	//color.h已包括
#include <math.h>
#include <ctype.h> 
#include <malloc.h>
//#include <windows.h>	//color.h已包括
#include "color.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正在计算中...%.2lf%%",100*(float)i/Nc);}printf("\n\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("\n\r|谐波含有率如下:\n");for(i=0;i<=Nc;i++){if(AP[i]/AP[1]<1e-4){setcolor(LIGHTBLUE);//无该次谐波的显示为黄色 printf("|%d:\t%7.3lf%%",i,100*AP[i]/AP[1]);}else{setcolor(WHITE);//有该次谐波显示为蓝色 printf("|%d:\t%7.3lf%%",i,100*AP[i]/AP[1]); 	} if((i+1)%5==0)printf("\n");}setcolor(WHITE);//还原默认色 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);	
} 

部分效果图

输入

输出
希望本文对您有帮助,谢谢阅读。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/544566.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PHP5.5四种序列化性能对比

2019独角兽企业重金招聘Python工程师标准>>> 结论&#xff1a; 1、小数组用msgpack,无论空间和性能都最好 2、大数组&#xff0c;考虑空间用igbinary,考虑性能用msgpack json_encode&#xff0c;serialize&#xff0c;igbinary&#xff0c;msgpack四种序列化方式&am…

多线程循环输出abcc++_C ++循环| 查找输出程序| 套装2

多线程循环输出abccProgram 1: 程序1&#xff1a; #include<iostream>using namespace std;int main(){ for(;;){cout<<"Hello ";}return 0;}Output: 输出&#xff1a; Hello Hello .... Infinite loopExplanation: 说明&#xff1a; In the above co…

MyBatis Plus 批量数据插入功能,yyds!

作者 | 王磊来源 | Java中文社群&#xff08;ID&#xff1a;javacn666&#xff09;转载请联系授权&#xff08;微信ID&#xff1a;GG_Stone最近 Review 小伙伴代码的时候&#xff0c;发现了一个小小的问题&#xff0c;小伙伴竟然在 for 循环中进行了 insert &#xff08;插入&a…

C语言打印彩色字符——以(枚举法+字符串查找)为例展示

文章目录C语言颜色头文件——自制非常简单的调用函数实战演练——一个基础的枚举变量小程序牛刀小试——查找字符小程序C语言颜色头文件——自制非常简单的调用函数 显然&#xff0c;C语言是不会提供打印彩色字符的标准函数&#xff0c;而我们有时候为了强调C语言打印的部分字…

人工智能ai 学习_学习代理| 人工智能

人工智能ai 学习Learning is an important part of human behavior. It is the first step in the development phase of any human. When the concept of Artificial Intelligence was proposed, the main approach of the developers was to build a system which could reac…

sql server中同时执行select和update语句死锁问题

原始出处 http://oecpby.blog.51cto.com/2203338/457054 最近在项目中使用SqlServer的时候发现在高并发情况下&#xff0c;频繁更新和频繁查询引发死锁。通常我们知道如果两个事务同时对一个表进行插入或修改数据&#xff0c;会发生在请求对表的X锁时&#xff0c;已经被对方持有…

再见 Spring Task,这个定时任务框架真香!

最近有朋友问到定时任务相关的问题。于是&#xff0c;我简单写了一篇文章总结一下定时任务的一些概念以及一些常见的定时任务技术选型。希望能对小伙伴们有帮助&#xff01;个人能力有限。如果文章有任何需要补充/完善/修改的地方&#xff0c;欢迎在评论区指出&#xff0c;共同…

C语言实现动画控制

文章目录原材料说明一场革命原材料 下载原材料网址: https://www.easyx.cn/downloads/ 下载easyx2014冬至版&#xff0c;将lib文件放在编译器默认的lib文件夹&#xff0c;h头文件放在编译器默认的include文件夹即可 说明 C语言可以用系统内部的定时函数sleep和usleep定时(需…

mcq 队列_MCQ | 8086微处理器中的寻址模式

mcq 队列Question 1: 问题1&#xff1a; You are given the following instruction: ADD AX , [1024] You are provided the following data: DS 3423H ; SS 1234H ; CS 4567H Find the effective address location for the given instruction. 您得到以下指示&#xff1a;…

聊聊redis分布式锁的8大坑

前言在分布式系统中&#xff0c;由于redis分布式锁相对于更简单和高效&#xff0c;成为了分布式锁的首先&#xff0c;被我们用到了很多实际业务场景当中。但不是说用了redis分布式锁&#xff0c;就可以高枕无忧了&#xff0c;如果没有用好或者用对&#xff0c;也会引来一些意想…

python 唯一元素_检查所有元素在Python中是否唯一

python 唯一元素Here, we are implementing a python program to check whether all elements of a list are unique or not? 在这里&#xff0c;我们正在实现一个python程序来检查列表的所有元素是否唯一&#xff1f; Its very simple to check, by following two steps 按…

MyBatis 批量插入数据的 3 种方法!

作者 | 王磊来源 | Java中文社群&#xff08;ID&#xff1a;javacn666&#xff09;转载请联系授权&#xff08;微信ID&#xff1a;GG_Stone批量插入功能是我们日常工作中比较常见的业务功能之一&#xff0c;之前我也写过一篇关于《MyBatis Plus 批量数据插入功能&#xff0c;yy…

MongoDB: The Definitive Guide

第一章 简介 MongoDB是面向文档的数据库&#xff0c;不是关系型数据库。内置对MapReduce的支持&#xff0c;以及对地理空间索引的支持。 丰富的数据模型容易扩展&#xff0c;它所采用的面向文档的数据模型可以使其在多台服务器之间分割数据丰富的功能&#xff0c;索引、存储Jav…

Python联网下载文件

声明 Python版本2.7.3所需Py文件——urllib22.7.3版本的Python Shell即可直接执行&#xff0c;但需要联网若程序执行成功&#xff0c;则会下载以下网址的txt文本并打印在shell中 http://helloworldbook2.com/data/message.txt 本代码来源于《父与子的编程之旅——与小卡特一起…

java 生产者消费者代码_Java生产者和消费者代码

java 生产者消费者代码This also helps us to understand the concept of synchronised multi-threading in java, the basic work of our code is that the producer will produce a thread and load it into the memory and after producing the producer thread we would be…

如何给SpringBoot配置轻松加密?

在实践中&#xff0c;项目的某些配置信息是需要进行加密处理的&#xff0c;以减少敏感信息泄露的风险。比如&#xff0c;在使用Druid时&#xff0c;就可以基于它提供的公私钥加密方式对数据库的密码进行加密。但更多时候&#xff0c;比如Redis密码、MQ密码等敏感信息&#xff0…

secureFX上传文件的时候报错,secureFX崩溃

SecureFX experienced a fatal error and must close.A crash dump file has been......打开注册表&#xff0c;HKEY_CURRENT_MACHINE->SOFTWARE->Vandyke中的secureCRT和secureFX中的license是secureCRT、secureFX的注册信息&#xff0c;不能删除&#xff0c;删除后需要…

C语言将循环小数/有限小数转换为分数

文章目录数学基础编程思路代码数学基础 早在小学的时候我就对循环小数非常感兴趣&#xff0c;加上初中和高中对循环小数可以说有一定基础研究&#xff0c;因此想到写一个将循环下小数转换为分数的程序&#xff0c;非常有意思&#xff0c;并且对初学者来说&#xff0c;它的输入…

c#中将整数转化为字符串_在C#中将字符串转换为字节数组

c#中将整数转化为字符串Prerequisite: How to declare and use byte[] in C#? 先决条件&#xff1a; 如何在C&#xff03;中声明和使用byte []&#xff1f; C&#xff03;中的字符串到字节数组的转换 (String to Byte Array Conversion in C#) In C#, it is possible that a …

升级了 Windows 11 正式版,有坑吗?

作者 | 王磊来源 | Java中文社群&#xff08;ID&#xff1a;javacn666&#xff09;转载请联系授权&#xff08;微信ID&#xff1a;GG_Stone&#xff09;今天磊哥去公司上班&#xff0c;惊喜的发现 Windows 提示更新了&#xff0c;并且是 Windows 11 正式版&#xff0c;这太让人…