C语言函数指针的应用——自制谐波分析软件
文章目錄
- 函數指針簡介
- 格式介紹
- 顏色頭文件
- 計算機仿真
- 使用說明
- 完整代碼
- 部分效果圖
函數指針簡介
如果在一個大型C語言程序中要反復調用函數,而調用的函數又不明確時,函數指針就是一個非常有用的東西。如果你的函數體內可以傳遞不同的函數,那就非得用函數指針實現不可。下面我就用一個例子給大家分享一下C語言函數指針的妙用。
格式介紹
格式為:【基類型】(*function)([參數表列])
C語言函數指針就是一個指向函數地址的指針,它和普通的指針一樣也具有基類型,例如int *p,double *q,void *malloc與普通指針不同的是,它指向的不是特定類型的變量,而是函數地址,因此它后面有函數的參數表列。使用的時候需要注意,由于指針運算符比括號運算符的優先級低,因此需要把(*function)括起來(否則就是返回指針的函數)。C語言的語法比較復雜,舉一個函數指針的例子:
函數指針主要有兩種使用方法:
下面是我編寫的一個計算一個指定方波的程序,里面的雙線性積分函數對每一次諧波變量(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); }部分效果圖
希望本文對您有幫助,謝謝閱讀。
總結
以上是生活随笔為你收集整理的C语言函数指针的应用——自制谐波分析软件的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 英语笔记:写作:Free admissi
- 下一篇: NVelocity标签使用详解