プログラミングの書き換え Visual basic→C言語
解決済
回答 2
投稿
- 評価
- クリップ 1
- VIEW 3,542

退会済みユーザー
前提・実現したいこと
visual basicで書いてあるプログラムをC言語に書き換えています
高速フーリエ変換を行い数値を入力することで画像が表示されるプログラムを作ろうとしています
一通り書き換えてみましたが変な数値が表示され画像が表示されません
どこをどのように書き換えたらプログラムが動くのか教えていただきたいです
また,必要のない部分があれば教えていただきたいです
入力する数値はデータ数n=512,α=0.05,β=2,γ=0.1,走査範囲=20,ガウス乱数1(あり),異方性=0(なし)です.
発生している問題・エラーメッセージ
画像が表示されない
おそらくスペクトル作成の部分の書き換えができていないと思われる
該当のソースコード
visualbasicここに言語を入力
ここにご自身が実行したソースコードを書いてください
Option Explicit
Dim i As Integer, j As Integer
Dim N As Integer
Dim ParaA1 As Single, ParaB1 As Single, ParaC1 As Single
Dim A() As Single, B() As Single, Sp() As Single, Sp1() As Single
Dim AX() As Single, BY() As Single
Dim Z() As Single
Dim region As Single, QS As Single
Dim Zmax As Single, ZMin As Single
Private Sub cmdCalc_Click()
' **************************************
' 2次元フーリエ係数を算出する
' データ数を選択後,計算開始
' **************************************
Dim flag As Single, flag2 As Single
If optDataNum(0) = True Then
N = 512
ElseIf optDataNum(1) = True Then
N = 256
Else
N = 128
End If
ReDim A(N - 1, N - 1), B(N - 1, N - 1)
ReDim AX(N - 1, N - 1), BY(N - 1, N - 1)
ReDim Sp(N - 1, N - 1)
ReDim Z(N - 1, N - 1)
If optSR(0) = True Then
region = 20
ElseIf optSR(1) = True Then
region = 2
Else
region = 0.5
End If
'ガウス
If chkGauss.Value Then
flag = 1
Else
flag = 0
End If
'異方性
If Check1.Value Then
flag2 = 1
Else
flag2 = 0
End If
ParaA1 = CSng(txtpara(0).Text)
ParaB1 = CSng(txtpara(1).Text)
ParaC1 = CSng(txtpara(2).Text)
QS = -1
' スペクトル作成
frmBusy.ProgressBar1.Max = 4 * N
frmBusy.ProgressBar1.Min = 0
frmBusy.lblBusy = "計算中…"
frmBusy.Show
MakeSp N, ParaA1, ParaB1, ParaC1, A(), B(), region, flag, flag2, Sp()
For i = 0 To N - 1
For j = 0 To N - 1
Sp(i, j) = (A(i, j) ^ 2 + B(i, j) ^ 2) / 0.25
AX(i, j) = A(i, j)
BY(i, j) = B(i, j)
Next j
Next i
DrawSimage frmSImage.picSImage, N, Sp()
fft2DMain N, -1, AX(), BY()
ZMin = AX(0, 0)
For i = 0 To N - 1
For j = 0 To N - 1
If AX(i, j) < ZMin Then ZMin = AX(i, j)
Next j
Next i
Zmax = AX(0, 0)
For i = 0 To N - 1
For j = 0 To N - 1
Z(i, j) = AX(i, j) + Abs(ZMin)
If Z(i, j) > Zmax Then Zmax = Z(i, j)
Next j
Next i
DrawData frmImage.picImage, N, Z(), Zmax
frmImage.Show
End Sub
Private Sub cmdQuit_Click()
End
End Sub
Private Sub mnuSavea_Click()
**************************************
' 2次元複素フーリエ係数作成
' **************************************
Dim i As Integer, j As Integer
Dim PI As Single, phase As Single, rad As Single, phaseS As Single
Dim kx As Single, ky As Single, K As Single
Dim Spec As Single, gauss As Single, lim As Single, Spec2 As Single, Rnd1 As Single, Rnd2 As Single
'波長をカットする領域
If region = 2 Then
lim = 50
ElseIf region = 0.5 Then
lim = 50
Else
lim = 50
End If
'SP面を創成
Randomize 4
PI = 4 * Atn(1)
For i = 1 To N / 2 - 1
For j = 1 To N / 2 - 1
If i <> 0 Or j <> 0 Then
kx = i / (region)
ky = j / (region)
K = Sqr(kx ^ 2 + ky ^ 2)
Rnd1 = Rnd
Rnd2 = Rnd
gauss = Abs(Sqr(-2 * Log(Rnd1)) * Cos(2 * PI * Rnd2))
'************************
'gaussの上限,下限 (04.6.20)
If gauss < 0.001 Then
gauss = 0.001
ElseIf gauss > 10 Then
gauss = 10
End If
'************************
Spec = ParaA1 * (K ^ (-ParaB1))
Spec2 = Spec * (gauss ^ flag)
rad = Sqr(Spec2 * 0.25)
If Sqr(kx ^ 2 + ky ^ 2) >= lim Then
phase = PI / 2
Else
phase = 2 * PI * Rnd
End If
A(i, j) = rad * Cos(phase)
B(i, j) = rad * Sin(phase)
A(N - i - 1, N - j - 1) = rad * Cos(phase)
B(N - i - 1, N - j - 1) = rad * Sin(phase)
A(i, N - j - 1) = rad * Cos(phase)
B(i, N - j - 1) = rad * Sin(phase)
A(N - i - 1, j) = rad * Cos(phase)
B(N - i - 1, j) = rad * Sin(phase)
End If
Next j: DoEvents: frmBusy.ProgressBar1.Value = i
Next i
'壁の創成0°方向 0
For i = 0 To N / 2 - 1
If i <> 0 Then
kx = i / (region)
K = Sqr(kx ^ 2)
gauss = Abs(Sqr(-2 * Log(Rnd)) * Cos(2 * PI * Rnd))
'************************
'gaussの上限,下限 (04.6.20)
If gauss < 0.001 Then
gauss = 0.001
ElseIf gauss > 10 Then
gauss = 10
End If
'************************
Spec = ParaC1 * ParaA1 * (K ^ (-ParaB1))
Spec2 = Spec * (gauss ^ flag)
rad = Sqr(Spec2 * 0.25)
If Sqr(kx ^ 2) >= lim Then
phase = PI / 2
Else
phase = 2 * PI * Rnd
End If
A(i, 0) = rad * Cos(phase)
B(i, 0) = rad * Sin(phase)
A(N - i - 1, 0) = rad * Cos(phase)
B(N - i - 1, 0) = rad * Sin(phase)
End If
Next i
'壁の創成0°方向 511
For i = 0 To N / 2 - 1
If i <> 0 Then
kx = i / (region)
K = Sqr(kx ^ 2)
gauss = Abs(Sqr(-2 * Log(Rnd)) * Cos(2 * PI * Rnd))
以下はC言語に書き換えてみたプログラムです
include <stdio.h>
include <math.h>
include <process.h>
include <stdlib.h>
//qs変更
//保存部分変更
// α,β,γのに変更中
//parab1
void main(void)
{
int ka,kb,ix,i,j,r,l,m,n,il1,it1,it2,it3,mf,nf,ib,lff,ir,ic,z,aa,bb;
double qs,ig,q,pi,tr,tj,swap,swop,sp,xx,yy,*x,*y,*il,*ik,*d,*s;
double paraa1,paraa2,paraa3,parab1,parab2,parab3,flag,flag2,parac1,region;
double phase,rad,phaseS,kx,ky,k,spec,gauss,lim,spec2,a,b,rnd,zmin1,*zmin,*zmax,zz;
//double *xは1次元配列 double **spは2次元配列の要素数未定の指定の仕方
FILE *fr,*fw;
char infilename[50],outfilename[50];
printf("ファイルのデータ数を入力して下さい!(AFMなら512)\n");
scanf("%d",&n);
printf("n=%d\n", n);
printf("αを入力して下さい!(0.05くらい)\n");
scanf("%lf",¶a1);
printf("%lf\n", paraa1);
printf("βを入力して下さい!(2くらい)\n");
scanf("%lf",¶b1);
printf("parab1=%lf\n ", parab1);
printf("γを入力して下さい!(0.1くらい)\n");
scanf("%lf",¶c1);
printf("%lf\n", parac1);
printf("走査範囲を入力して下さい!(基本20)\n");
scanf("%lf",®ion);
printf("region=%lf\n", region);
printf("ガウス乱数 0:なし 1:あり(逆かも基本1?)\n");
scanf("%lf",&flag);
printf("%lf\n", flag);
printf("異方性 0:なし 1:あり(0?)\n");
scanf("%lf",&flag2);
printf("%lf\n", flag2);
//-----------------------------------------------------
d = (double *)malloc(sizeof(double) * n);
if (d==NULL) exit(1);
s = (double *)malloc(sizeof(double) * n);
if (s==NULL) exit(1);
x = (double *)malloc(sizeof(double) * n);
if (x==NULL) exit(1);
y = (double *)malloc(sizeof(double) * n);
if (y==NULL) exit(1);
sp = (double )malloc(sizeof(double *) * n);
if (sp==NULL) exit(1);
for (i=0; i<n; i++) {
sp[i] = (double *)malloc(sizeof(double) * n);
if (sp[i]==NULL) exit(1);
}
a = (double )malloc(sizeof(double *) * n);
if (a==NULL) exit(1);
for (i=0; i<n; i++) {
a[i] = (double *)malloc(sizeof(double) * n);
if (a[i]==NULL) exit(1);
}
b = (double **)malloc(sizeof(double *) * n);
if (b==NULL) exit(1);
for (i=0; i<n; i++) {
b[i] = (double *)malloc(sizeof(double) * n);
if (b[i]==NULL) exit(1);
}
pi=4*atan(1);
qs=-1;
ig=log(n)/log(2);
試したこと
C言語では配列の数がわからない時にマロック関数を使う必要があると教えていただいたのでそれを使って書き換えてみました
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
checkベストアンサー
0
ざっと流し読みしましたが、とりあえず
sp
などがdouble
として宣言されている割には
sp = (double )malloc(sizeof(double *) * n);
とdouble*
n個分の領域を確保しているので、
多分、意図するところは
double **sp;
...
sp = (double**)malloc(sizeof(double *) * n);
では?
もっと言えば多分二次元配列の動的確保をしたいのでしょうから
このあたりを参考にどうぞ。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
0
とりあえずDFTのプログラムを書いてからFFTを作ったほうがいいと思うよ。計算の確認ができるし、FFTの部品にも使えるよ。ついでに、元のプログラムのパラメタの多さが気になります。二次元にしてもなんかおかしい。そもそも、パラメタの解釈によって意味が変わるはず。
FFT(原信号)
原信号長が偶数ならば
→原信号奇数部と偶数部をそれぞれ再帰的にFFT。この結果で計算結果を組み立てる。
原信号長が奇数ならば
→原信号をそのままDFT
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.35%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
2016/05/25 23:54
回答ありがとうございます
sp = (double )malloc(sizeof(double *) * n);
if (sp==NULL) exit(1);
for (i=0; i<n; i++) {
sp[i] = (double *)malloc(sizeof(double) * n);
if (sp[i]==NULL) exit(1);
}
上記の部分のsp = (double )malloc(sizeof(double *) * n); を
sp = (double**)malloc(sizeof(double *) * n);に書き換えてみます
2016/05/26 08:18
2016/05/26 20:53
visual basicの
ReDim A(N - 1, N - 1), B(N - 1, N - 1)
ReDim AX(N - 1, N - 1), BY(N - 1, N - 1)
ReDim Sp(N - 1, N - 1)
ReDim Z(N - 1, N - 1)
をC言語にどのように書き換える方法がわからないのですが
この部分は省略しても大丈夫ですか?
省略してはいけないのなら書き換え方を教えていただきたいです
ちなみにN=512です
2016/05/27 13:52
C言語では realloc() ライブラリ関数の呼出しに相当します。
「再」割当てですから、普通、既に割当済みの(Dim してある)ものを ReDimするので、例えば
Dim DP(256) As Double
だったものを、
ReDim DP(512)
とするなら、
double *dp; /* 一次元配列を指すポインタ変数 dp を宣言しておき */
:
dp = malloc(sizeof(double) * 256); /* 1回目、要素数256個分の配列を確保する */
:
dp = realloc(dp, sizeof(double) * 512); /* 2回目、512個分に割当てなおす */
が相当するCのコードとなると思います(あくまで一般的には、ということで)。
ただし、まだ配列を割当ておらず、ReDim で初めてメモリを割当てるなら、それは即ち1回目のメモリ割当てなので malloc() で構わないし、不要なトラブルを避けることになります。即ち
dp = malloc(sizeof(double) * 512);
P.S.1.
コード中に「double **spは2次元配列の要素数未定の指定の仕方」とコメントがありましたが、それだけの認識ではトラブルになりそうです。C言語で二次元配列をmalloc()で割当てるのは単純ではありません。割り当てた後のアクセス方法ともあわせて、複数の方法が考えられるので、注意が要ります。
例えば次のページを参考にして、どのようなデータ構造にすればよいか・配列のアクセス方法をどうするのがよいか、検討されると良いと思います(なので、上の私の回答は簡単な一次元配列を例にした)。
C言語で2次元配列を動的に割り当てる4つの方法
http://tondol.hatenablog.jp/entry/20090713/1247426321
P.S.2
VBからCへの書き換えをするなら、本来、両方の言語に通じている必要があります。「私は、プログラミングを経験したことがな」いなら、両方に通じている方を探して、直接助言を受けるのが理想です(どちらかと言えば、少なくともC言語の経験者が望ましい)。
そのうえで、このサイトで助言を受けたければ、プログラム全体を質問の対象にするのではなく、ここの「ReDimを、どう書き換えればよいか?」のように、質問のポイントを絞ったほうが答えを得やすい(答える方も答えやすい)と思いました。