• ベストアンサー

C言語でのFFT(構造体とポインタの使用)

今、VC++2008 Express Editionを使用して先日、作成したFFTのプログラムを構造体とポインタを使用して書き換えました。 ビルド&コンパイルは通ったのですが、実行するとエラーが起きます。何がおかしいのでしょうか。 ソースコードを掲載しますので、教えてください。 //main.c #include <stdio.h> #include "stdlib.h" #include "fft.h" #include <math.h> #include "data.h" #define PI 3.1415926 FILE *ifp, *ofp; struct DATA f; double dT, dF; double *amp; int main (void) { //波形の生成と配列入力 for(i=0;i<1024;i++){ dumx[i]=(double)i/1024; dumy[i]=sin(2.0*PI*50*(double)i/1024); } DN=1024; //FFT用データ配列に配列のコピー time = (double*)calloc(DN,sizeof(double)); f.Re =(double*)calloc(DN,sizeof(double)); f.Im =(double*)calloc(DN,sizeof(double)); for(i=0;i<DN;i++){ time[i]=dumx[i]; f.Re[i]=dumy[i]; f.Im[i]=0.00; } //サンプリング周期 dT = time[1]; //サンプリング周波数 dF = 1.0/dT; //FFT FFT(f); //大きさを出力するための配列の確保 amp=(double*)calloc(DN,sizeof(double)); for(i=0;i<DN;i++){ amp[i]=sqrt(Sqr(f.Re[i])*Sqr(f.Im[i])); } //FFT用データ配列の初期化 free(f.Re),f.Re=NULL; free(f.Im),f.Im=NULL; //出力データの書き込み ofp=fopen("c:\\make\\data\\output.csv","w"); for(i=0;i<DN/2;i++){ fprintf(ofp,"%lf,%lf\n",i*dF, amp[i]); } fclose(ofp); return 0; } //fft.h extern void FFT(struct DATA); #define Sqr(x) ((x)*(x)) data.h int g, h, i, j, k, l, m, n, p, q, DN; double a, b, tmp; double dumx[1024]; double dumy[1024]; double *time; struct DATA { double *Re; double *Im; }; struct ROT { double *c; double *s; }; //FFT解析用ソースコード //analysis.c #include "data.h" #include <math.h> #include <stdlib.h> #define PI 3.1415926 void Table( struct ROT); void swap( double*, double*); void FFT(struct DATA in) { struct ROT r; r.c=NULL; r.s=NULL; in.Re=(double*)calloc(DN,sizeof(double)); in.Im=(double*)calloc(DN,sizeof(double)); n=DN; m = (int)(log10(n)/log10(2)); //回転因子テーブルの作成 Table(r); l=n,h=1; //バタフライ演算 for(g=1;g<=m;g++){ l/=2,k=0; for(q=1;q<=h;q++){ p=0; for(i=k;i<=l+k-1;i++){ j=i+l; a=in.Re[i]-in.Re[j], b=in.Im[i] - in.Im[j]; in.Re[i] = in.Re[i] + in.Re[j], in.Im[i] = in.Im[i] + in.Im[j]; if(p==0){ in.Re[j]=a,in.Im[j]=b; }else{ in.Re[j] = a * (r.c[p]) + b * (r.s[p]), in.Im[j] = b * (r.c[p]) - a * (r.s[p]); } p+=h; } k+=l+l; } h+=h; } j=n/2; for(i=1;i<=n-1;i++){ k=n; if(j<i){ //ビットリバース swap(&(in.Re[i]),&(in.Re[j])); swap(&(in.Im[i]),&(in.Im[j])); } k/=2; while(j>=k){ j=j-k,k /=2; //無限ループ回避(ここを消すと無限ループに陥ります。)ここから if((j==0)&&(k==0)){ break; } //ここまで } j += k; } } void Table( struct ROT w) { w.c = (double*)calloc(DN/2,sizeof(double)); w.s = (double*)calloc(DN/2,sizeof(double)); a=0.00, b = 2.0 * PI /DN; for(i=0;i<DN/2;i++) { (w.c[i])=cos(a+i*b), (w.s[i])=sin(a+i*b); } } void swap(double *var1, double *var2) { tmp = *var1, *var1=*var2, *var2=tmp; }

質問者が選んだベストアンサー

  • ベストアンサー
  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.4

nda23氏へ yf491224氏は『C』でやりたいのかも メインやサブのファイル名も『.c』ですし ・・・ 『Data.h』での変数宣言でこけそうな気がします 『analysis.c』『main.c』両方に同名の変数宣言を行うことになるので おかしなことになるかと 実体を main.c(またはanalysis.c)で宣言して data.hでは 各変数を externを使って外部変数ですとした方がいいように思います 関数 FFTの中で in.Reやin.Imを再確保していますがこれでは 引数で元データを与える意味がありません

yf491224
質問者

お礼

>yf491224氏は『C』でやりたいのかも >メインやサブのファイル名も『.c』ですし ・・・ あはは。C言語のほうが私には、わかりやすいのでCを扱っていました。 C++に関しては、基礎的なところは本を持っていますが、それ以外のところはさっぱりです。 >『Data.h』での変数宣言でこけそうな気がします >『analysis.c』『main.c』両方に同名の変数宣言を行うことになるの>実体を main.c(またはanalysis.c)で宣言して data.hでは 各変数を >externを使って外部変数ですとした方がいいように思います >関数 FFTの中で in.Reやin.Imを再確保していますがこれでは >引数で元データを与える意味がありません わかりました。ご指摘のとおりに変更して再度やってみます。 回答ありがとうございます

その他の回答 (3)

  • nda23
  • ベストアンサー率54% (777/1415)
回答No.3

せっかくなんで、C++っぽく void Table( struct ROT* );     ↓ void Table( struct ROT &); これで、呼び出し側がTable(r)と書いても参照渡しになります。 関数側もw.c = ~ のように記述します。つまり、現在のままで 良いということです。 あとはredfox63さんの意見を参考になさってください。

  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.2

すみません ・・・ これは誤りですね Im側の計算もなされていました m(__)m > in.Im側の計算がされていないようですので出力はすべて0になってしまうようです 関数FFTも ポインタで参照渡しにしないと FFTでの計算結果が反映されませんよ

  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.1

関数Tableに対して struct ROTで引数を渡していますが これだと『値渡し』ですので ここで確保した構造体ROTのメンバーc,sは呼び出し元に反映されません したがって r.c[p]などとアクセスすると不正メモリーのアクセスで停止するでしょう void Table( struct ROT* ); と宣言 void Table( struct ROT* w) {   // ポインター用に『.』を『->』に変更   w->c = (double*)calloc(DN/2,sizeof(double));   w->s = (double*)calloc(DN/2,sizeof(double));   a=0.00, b = 2.0 * PI /DN;   for(i=0;i<DN/2;i++)   {     (w->c[i])=cos(a+i*b), (w->s[i])=sin(a+i*b);   } } また、 ROT用に確保したメモリーの解放が見当たりません in.Im側の計算がされていないようですので出力はすべて0になってしまうようです log10の引数に intを使うオーバーロードがないので(double)などでキャストしましょう

yf491224
質問者

お礼

なるほどです。ご指摘のとおりに修正して実行してみます。 回答ありがとうございます。

関連するQ&A

  • C言語でのFFTについて

    http://tsuyu.cocolog-nifty.com/blog/2007/03/publi.html に掲載されているVBAのFFTプログラムをC言語に書き換えて 実行しているのですがうまくいきません。 どこが、間違っているか教えてください。 ======以下FFTのサブルーチンソースコード===== void FFT(float Xr[], float Xi[]) { i=0,j=0,k=0,l=0,m=0,n=0,p=0,q=0; n=DN; m = log10(n)/log10(2); Table(c,s); l=n,h=1; for(g=1;g<=m;g++){ l/=2,k=0; for(q=1;q<=h;q++){ p=0; for(i=k;i<=l+k-1;i++){ j=i+l; a=Xr[i]-Xr[j], b=Xi[i]-Xi[j]; Xr[i] = Xr[i] + Xr[j], Xi[i] = Xi[i] + Xi[j]; if(p==0){ Xr[j]=a,Xi[j]=b; }else{ Xr[j] = a * c[p] + b * s[p], Xi[j] = b * c[p] - a * s[p]; } p+=h; } k+=l+l; } h+=h; } j=n/2; for(i=1;i<=n-1;i++){ k=n; if(j<i){ //ビットリバース swap(&Xr[i],&Xr[j]); swap(&Xi[i],&Xi[j]); } k=k/2; while(j>=k){ j=j-k; k /=2; } j = j + k; } }

  • FFTをc言語でプログラミング

    助けてください↓c言語でFFTをプログラミングしているのですがバグが発見できずに困り果て居ます。 プログラミングは以下の通りです。画像はカラーではなく、グレースケールのMANDRILLに対して行っています。 for(n=0;n<M;n++){    for(i=0;i<N;i++){ for(j=0;j<N;j++){ Imbatx[n][i][j]=0; } } } //行FFT //まずはソート for(i=0;i<N;i++){ int x=1; for(j=0;j<N;j++){ if(j<N/2){        //左半分 if(j%2!=0) //jが奇数 batx[0][i][j]=imagein[i][j+N/2-1]; if(j%2==0) //jが偶数 batx[0][i][j]=imagein[i][j]; } if(N/2<=j && j<N){ //右半分 if(j%2!=0) //jが奇数 batx[0][i][j]=imagein[i][x+N/2-1];      if(j%2==0) //jが偶数 batx[0][i][j]=imagein[i][x]; x++; } } } for(i=0;i<N;i++){ for(n=1;n<M+1;n++){ k=0; for(j=0;j<N;j++){ mul=(int)pow(2.0,(double)n); if(j%mul < mul/2){ //偶数列 batx[n][i][j] = batx[n-1][i][j]+cos(2*PI*k/mul)*batx[n-1][i][j+mul/2]- sin(2*PI*k/mul)*Imbatx[n-1][i][j+mul/2]; Imbatx[n][i][j]=Imbatx[n-1][i][j]+sin(2*PI*k/mul)*batx[n-1][i][j+mul/2]+ cos(2*PI*k/mul)*Imbatx[n-1][i][j+mul/2]; k++; } else{ //奇数列 batx[n][i][j] = cos(2*PI*k/mul)*batx[n-1][i][j] + batx[n-1][i][j-mul/2]- sin(2*PI*k/mul)*Imbatx[n-1][i][j]; Imbatx[n][i][j]=Imbatx[n-1][i][j-mul/2]+sin(2*PI*k/mul)*batx[n-1][i][j]+cos(2*PI*k/mul)*Imbatx[n-1][i][j]; k++; } Re_countx[i][j] = batx[M][i][j]; Im_countx[i][j] = Imbatx[M][i][j]; } } } for(i=0;i<N;i++){ for(j=0;j<N;j++){ FFT[i][j]=pow(pow(Re_countx[i][j],2)+pow(Im_countx[i][j],2),0.5); FFT[i][j]=log10(FFT[i][j]); if(FFT[i][j]>max) max=FFT[i][j]; imageout[i][j]=(unsigned char)255*FFT[i][j]/max; } } 結果的に出力される画像は以下の画像になります。 ごらんのように縞模様が出てしまいます。 分かる方どうかお願いいたします。

  • 構造体内のポインタのポインタについて

    ポインタを理解するために以下のようなテストプログラムを作りました。 test.h --- typedef struct i_info{ int i_id; char i_name[64]; } I_INFO; typedef struct j_info{ int j_id; char j_name[64]; } J_INFO; typedef struct k_info{ int k_id; char k_name[64]; } K_INFO; typedef struct info{ int id; char name[64]; I_INFO iinfo; J_INFO *jinfo; K_INFO **kinfo; } INFO; --- test.c --- 1 #include <stdlib.h> 2 #include <stdio.h> 3 #include "./test.h" 4 5 int main(int argc, char **argv) 6 { 7 INFO info; 8 J_INFO j; 9 K_INFO k; 10 K_INFO *pk=NULL; 11 12 memset (&info,NULL,sizeof(info)); 13 memset (&j,NULL,sizeof(j)); 14 memset (&k,NULL,sizeof(k)); 15 16 info.id = 1; 17 memcpy(info.name,"***",3); 18 19 info.iinfo.i_id = 2; 20 memcpy(info.iinfo.i_name,"*i*",3); 21 22 info.jinfo = &j; 23 j.j_id = 3; 24 memcpy(j.j_name,"*j*",3); 25 26 info.kinfo = &pk; 27 pk= &k; 28 k.k_id = 4; 29 memcpy(k.k_name,"*k*",3); 30 31 printf( "%d\n",info.id); 32 printf( "%s\n",info.name); 33 printf( "%d\n",info.iinfo.i_id); 34 printf( "%s\n",info.iinfo.i_name); 35 printf( "%d\n",info.jinfo->j_id); 36 printf( "%s\n",info.jinfo->j_name); 37 /* 38 printf( "%d\n",info.kinfo->k_id); 39 printf( "%s\n",info.kinfo->k_name); 40 */ 41 } --- 38,39行目をコメントアウトするとコンパイルは通るのですが、 そのままだとコンパイルエラーになります。 なぜいけないのでしょうか?理由を教えてください。

  • C言語の構造体についてです。

    構造体employee 型の変数を配列で5つ宣言し、BMI 値、肥満率、理想体重を求めた後、BMI 値の昇順でソートをかけ、表示をするというプログラムを作成したいのですが、うまくいきません。 ・引数は、配列(構造体employee []型 または、構造体employee *型) ・戻り値は、なし。 ・関数名は、sort ・番号はint型 ・名前はchar型 ・身長・体重・BMI値・肥満率・理想体重はdouble型 という指定があります。 #include <stdio.h> #define N 5 struct employee{ int number; char name[20]; double height; double weight; double bmi; double fat; double ideal; }; void bmi_fat(struct employee *); void sort(struct employee []); int main(void) { int i; struct employee std[N]={ {1, "oohata", 173.0, 60.0, 0.0, 0.0, 0.0},{2, "suzuki", 168.8, 60.2, 0.0, 0.0, 0.0}, {3, "satou", 168.2, 80.5, 0.0, 0.0, 0.0},{4, "tanaka", 162.5, 45.2, 0.0, 0.0, 0.0}, {5, "yamada", 155.3, 55.7, 0.0, 0.0, 0.0} }; for(i=0; i<N; i++){ sort(std); bmi_fat(&std [i]); } for(i=0; i<N; i++){ sort(std); printf("社員番号:%d番\n", std[i].number); printf("名前:%s\n", std[i].name); printf("身長:%2.1lfcm\n", std[i].height); printf("体重:%2.1lfkg\n", std[i].weight); printf("BMI:%2.1lf\n", std[i].bmi); printf("肥満率:%2.1lf%\n", std[i].fat); printf("理想体重:%2.1lfkg\n", std[i].ideal); } return 0; } void sort(struct employee a[]) { int i, j; struct employee x; a->bmi=a->weight/((a->height/100.0)*(a->height/100.0)); a->ideal=(a->height-100)*0.9; a->fat=a->weight/a->ideal*100.0; for(i=0; i<N-1; i++){ for(j=0; j<N-i-1; j++){ if(a[j].bmi>a[j+1].bmi){ x=a[j]; a[j]=a[j+1]; a[j+1]=x; } } } } 以上が作成済みのプログラムなのですが、「外部シンボル'_bmi_fat'が未解決」と出てしまいます。 どこを直してよいのかが全く分かりません。 ご教授お願い致します。

  • 構造体へのポインタについて

    初心者です。 C入門書の著者のサポートページには正誤表とダウンロードしかないためこちらで質問させていただきます。 下記のコードの下から二行目の構造体へのポインタ (Car *) について、中学生に説明するように基本的な考え方、目的、書式、参考URLなどを教えて下さい。 ポインタについては、該当の章を読み直し基本事項については理解しておりますが、突然あるページから(Void *)や(Char *)など括弧で閉じるものが説明なしに出てきてちょっと混乱してます。(汗 どうぞ宜しくお願い致します。 #include<stdio.h> /* 構造体型struct Carの宣言 */ typedef struct Car{ int num; double gas; }Car; int main(void) { printf("int型のサイズは%dバイトです。¥n", sizeof(int)); printf("double型サイズは%dバイトです。¥n", sizeof(double)); printf("構造体structCar型のサイズは%dバイトです。¥n", sizeof(Car)); printf("構造体struct Car型へのポインタのサイズは%dバイトです。¥n", sizeof(Car *)); return 0; }

  • 構造体のリンク?

    こんにちは。 超初心者です。 どうぞよろしくお願いしますm(__)m 下記の三つのファイル、コンパイルすると「パブリックシンボル_high、_lowがi.obj、c.objの両方に定義されている」旨のエラーが出てしまいます。 ヘッダファイルに#ifndef~を書くくらいしか見当がつけられない初心者です(T_T) どこをどう直せばいいのか教えてください。 やりたいことは、high->i+high->j、low->i+low->jを関数一つに纏めて、mainから別ファイルに独立させることです。 *********c.h********* #ifndef __c__ #define __c__ struct type{ int i; int j; }*high,*low; extern int f(struct type *temp); #endif *********c.cpp********* #include"c.h" int f(struct type *temp); int f(struct type *temp){ return temp->i+temp->j; } *********i.cpp********* #include<iostream.h> #include"c.h" void main(void){ high->i=10; high->j=30; low->i=100; low->j=300; cout<<f(high)<<","<<f(low)<<endl; }

  • c言語の、voidの使い方で困っています

    C言語の問題を教えて下さい。 この問題で困っています。 複素数z1,z2の引き算、掛け算を計算する構造体complexを引数、 戻り値とする関数 complex hikizan(complex z1,complex z2) complex kakezan(complex z1,complex z2) を作成し、 複素数を画面に表示する関数 void show(complex x) で結果を表示するプログラムを作りなさいという問題です。 z1=1+3i z2=2+2i です。 作ってみたのですが、void show(complex x)を使う方法が分かりません。 教えて下さい、お願いします。 以下、作ったプログラムです #include<stdio.h> typedef struct complex{ double re; double im; } complex; complex hikizan(complex z1,complex z2) { complex z; z.re=z1.re-z2.re; z.im=z1.im-z2.im; return z; } complex kakezan(complex z1,complex z2) { complex zz; zz.re=z1.re*z2.re-z1.im*z2.im; zz.im=z1.re*z2.im+z1.im*z2.re; return zz; } int main(void) { complex z1,z2,z,zz; z1.re=1; z1.im=3; z2.re=2; z2.im=2; z=hikizan(z1,z2); zz=kakezan(z1,z2); printf("z1-z2=%f+%fi \n",z.re,z.im); printf("z1*z2=%f+%fi \n",zz.re,zz.im); }

  • C言語のプログラミングで質問です

    C言語のプログラミングで質問です. 時間を測ろうと下記のようなプログラムをしてみましたが計測時間がoTime, nTime共に0.000になってしまいます.(winmm.libはリンクさせてます) おかしいところはどこでしょうか? #include<stdio.h> #include<time.h> #include<windows.h> #include<mmsystem.h> #include<stdlib.h> #define N 2048 #define M 32 int main(int argc, char* argv[]) {   int i, j, k, l;   float target = 0;   float* a;   float* b;   float c;   DWORD nTime, oTime;     a = (float*)malloc(sizeof(float)*N);   b = (float*)malloc(sizeof(float)*N);   c = 0;   for(i = 0; i < N; i++)   {     a[i] = 1000;     b[i] = 0;   }  oTime = timeGetTime();   for(i = 0; i < M; i++)   {    for(j = 1; j < N/M; j += j)    {      for(k = 0; k < N/M; k++)      {        if(k % 2 == 0)        {          a[k+i*N/M] += a[k+j+i*N/M];        }      }    }    b[i] = a[i*N/M];    printf("%f\n", a[i*N/M]);   }   for(i = 0; i < M; i++)   {     target += b[i];   }   c = target;   nTime = timeGetTime();   printf("%f\n%f\n%f", c, oTime, nTime);   getch();   return 0; }

  • C言語プログラムエラーについて

    構造体とポインタを使って関数電卓のプログラムを作ってコンパイルしたのですがひとつだけエラーがでて困っています。親切な方回答よろしくお願いします。 ソースコード↓ #include<stdio.h> #include<string.h> #include<math.h> int main(void) { int i; double result; char inp_buf[30]; double input_d; typedef struct{ char*f_name; double(*func)(double); }FUNC_TBL; FUNC_TBL f_tbl[] = { { "sin",sin }, { "cos",cos }, { "tan",tan }, { "exp",exp }, }; printf( ">" ); scanf( "%s %lf", inp_buf, &input_d); for( i=0;i< sizeof(f_tbl)/sizeof(FUNC_TBL);i++) { if(!strcmp(f_tbl[i],f_name,inp_buf)) { 29行目→ result = f_tbl[i],func(input_d); } } printf("%lf\n",result); return 0; } エラーメッセージ↓ (29):error C2440:`=`:`FUNC_TBL`から`double`に変換できません。

  • C言語構造体についてです。

    C言語、π=PI 3.14159265で構造体を用いてmensekiを呼び出して 半径と面積を計算して出力するプログラムです。下の空白を埋めてもらえますか? /* 構造体のプログラム */ #include <stdio.h> #include <math.h> #define PI 3.14159265 struct Data { /* 半径rと面積areaをdoubleで宣言 */ }; void menseki(struct ... 構造体のポインタを引数とする ){ /* 面積を計算する際に構造体のアドレスから計算する */ circle->area=PI* .....; } main(){ struct Data example[2]; //構造体配列 int i; /* 半径rを構造体配列を用いて2例入力する */ /* 2例の各々について mensekiを呼び出して 半径と面積を計算して出力する */ } よろしくお願いします。

専門家に質問してみよう