人力検索はてな
モバイル版を表示しています。PC版はこちら
i-mobile

2次元配列の定数ファイルをExcelで自動生成したい。

例えば、10×10の配列データとして、以下を定義するとします。
table99[10][10] = {
{0,0,0,0,0,0,0,0,0,0}
{0,1,2,3,4,5,6,7,8,9}
{0,2,4,6,8,10,12,14,16,18}
:
:
:
{0,9,18,27,36,45,54,63.72.81}
}

これを定数ファイルとして、Excelから自動で出力したいと考えています。
10×10くらいなら、無理やりExcelで表作って、CSV保存して切った貼ったでもなんとかなるのですが
256×256のテーブルを10個作らないといけないことが分かり、しかも数値が一部見直しになる可能性もありってことで、ちょっと省力化できないかな、と考えています。

●質問者: GM91
●カテゴリ:コンピュータ 学習・教育
○ 状態 :終了
└ 回答数 : 4/4件

▽最新の回答へ

質問者から

要求仕様をまとめると
1)要素数は256×256
2)各要素の中身は符号付浮動小数で記載。
3)できれば、10点×10点くらいをExcelに記入したら、256×256点のテーブルへ展開したい。
4)256点 という要素数は変動なし。簡易に変更できればなおよい。
5)256×256のテーブルはExcel上でみれなくてもOK。いきなりc言語用ファイルを吐いてもOK。
こんな感じです。
その他、不明点あれば追加します。

また、参考になるサイトの紹介などでもOKです。
何卒宜しくお願いします。


1 ● 犬猫ハーフ
●1ポイント

以下の手順ではどうでしょうか?

1. Excel上でテーブルを作成する。
2. テーブルをCSVで保存する。
3. CSVファイルを読み込み、C言語用のファイルを吐くプログラムを実行する。

3.用のプログラムだけ作成する必要がありますが、これは簡単に出来ると思います。


GM91さんのコメント
ありがとうございます その方法でやろうとしていて、それを力づくでなく楽に処理できないか、という質問です。

2 ● セガビ
●3ポイント

ちょっと手元にExcelがないので確実にできるかは自信がないのですが、Excelで256*256の表を作って"data.csv"というファイル名でCSV出力し、

float table[256][256] = {
#include "data.csv"
};

みたいな感じで書けば初期化できそうな気がします。

Cなら2次元配列でも256*256個の1次元配列として初期化できますので、256ごとの{}は不要です。ただし、csvファイルの各行の最後に","が必要なので、Excelで最後のセルに空白を入れるなどして、行末に","が入るようにしないとダメですね。

できなかったらゴメンなさい...


GM91さんのコメント
ありがとうございます。 質問の趣旨は c言語への取り込み方ではなく ファイルの生成方法、です。

3 ● rsc
●50ポイント

いきなりc言語用ファイルを吐いてもOKということで、こんな感じでどうでしょうか。(^_^;

Option Explicit

Sub mkTable()
 Dim i, j, m, n As Integer
 Dim s As String
 m = 256
 n = m
 s = "float table[" + Trim(Str(m)) + "][" + Trim(Str(n)) + "] = {" + vbCrLf
 For i = 0 To m - 1
 s = s + vbTab + "{"
 For j = 0 To n - 1
 If i < 10 And j < 10 Then
 s = s + Str(i * j) + ".0"
 Else
 s = s + Str(0) + ".0"
 End If
 If j < n - 1 Then s = s + ","
 Next j
 s = s + "}"
 If i < m - 1 Then s = s + ","
 s = s + vbCrLf
 Next i
 s = s + "};" + vbCrLf
  'Debug.Print s
 Open "output.txt" For Output As #1
 Print #1, s
 Close #1
End Sub

10×10のデータから256×256のデータを予想するのをちょっとやってみました。(^_^;
FORECASTのxの範囲用に258行目を使いました。(^_^;

Sub macroAll()
 Call mkTable1
 Call mkTable2
End Sub

'種データ
Sub mkTable1()
 Cells.Clear
 Dim i, j As Integer
 
 For i = 1 To 10
 For j = 1 To 10
 Cells(i, j) = (i - 1) * (j - 1)
 Next
 Next
 
  ' Forecast用
 Dim k As Integer
 For k = 1 To 10
 Cells(258, k).Value = k
 Next k
End Sub

' Forecastで予想してみる
Sub mkTable2()
 Dim i, j, k, m, n As Integer
 m = 256
 n = m
 For k = 11 To m
 For j = 1 To k - 1
 Cells(k, j).Value = calc1(k, j)
 Next j
 For i = 1 To k
 Cells(i, k).Value = calc2(i, k)
 Next i
 Next k
End Sub

Function calc1(i, j) As Double
 calc1 = WorksheetFunction.Forecast(i, Range(Cells(1, j), Cells(10, j)), Range(Cells(258, 1), Cells(258, 10)))
End Function

Function calc2(i, j) As Double
 calc2 = WorksheetFunction.Forecast(j, Range(Cells(i, 1), Cells(i, 10)), Range(Cells(258, 1), Cells(258, 10)))
End Function

※参考URL
http://dekiru.net/article/4566/


GM91さんのコメント
ありがとうございます、ちょっと試してみます。

rscさんのコメント
もしかして、10×10は自分でセルに入力しておいて、他の256×256を補間法で計算するってことですか。(?_?;

GM91さんのコメント
そうです

4 ● a-kuma3
●300ポイント ベストアンサー

3)できれば、10点×10点くらいをExcelに記入したら、256×256点のテーブルへ展開したい。

これがよく分からなかったので、以下のようにしました。

Const max = 256

' 256 × 256 の表を作成
Sub make_data()
 For r = 1 To max
 For c = 1 To max
 Cells(r, c) = (r - 1) * (c - 1)
 Next
 Next
End Sub



' 256 × 256 の表を配列の宣言形式でファイルに保存
Sub output_data()
 Filename = "D:\table99.h"
 Open Filename For Output As #1
 Print #1, "double table99["; max; "]["; max; "] = {"
 For r = 1 To max
 Print #1, "{";
 For c = 1 To max
 Print #1, Format(Cells(r, c), "0.#########");
 If c <> max Then
 Print #1, ",";
 Else
 Print #1, "},"
 End If
 Next
 Next
 Print #1, "};"
 Close #1
End Sub

256×256 の表は、10×10 の領域をコピーする、もしくは、ある範囲を決めてランダムな数字で埋める、とか、いろいろやり方はあるでしょうが、サブルーチン make_data のループの中身を書き換えれば良いかな、と。



追記です。

簡単にいうと、10×10(16×16とかでもOK)くらいの入力点の間を内挿して、256点×256点のテーブルを作りたいのです。
内挿する点は与えた点の直線補間でOK。
...
※贅沢を言えば、入力する点数は10×10?20×20くらいで対応できると嬉しいです。(出力は256^2で固定OK)


データを作るところを以下のようにしました。

Const from_max = 10
Const max = 256

Function calc_interpolation(r, c)
 mm = CDbl(max - 1)

 x = (c - 1) * (from_max - 1) / mm + 1
 y = (r - 1) * (from_max - 1) / mm + 1

 x0 = Application.RoundDown(x, 0)
 x1 = x0 + 1
 y0 = Application.RoundDown(y, 0)
 y1 = y0 + 1

 v00 = Cells(y0, x0).Value
 v10 = Cells(y0, x1).Value
 v01 = Cells(y1, x0).Value
 v11 = Cells(y1, x1).Value

 v = (x1 - x) * ((y1 - y) * v00 + (y - y0) * v01) + (x - x0) * ((y1 - y) * v10 + (y - y0) * v11)
 calc_interpolation = v

End Function

Sub make_data()
 Set to_sheet = Worksheets("Sheet2")
 For r = 1 To max
 For c = 1 To max
 to_sheet.Cells(r, c).Value = calc_interpolation(r, c)
 Next
 Next
End Sub

選択中のシートの左上10×10 の領域を、"Sheet2" の 256×256 の領域に書き出します。
先の回答のファイルへの書き出しと共有してるので、変数名が変な感じになってますが、対象の大きさは以下の定数で変更できます(A1 から始まるところと、行と列の大きさが等しいところは固定です)。

データの補間には、画像を拡大するときに使われる「双一次補間」というのを使いました。
http://imagingsolution.blog107.fc2.com/blog-entry-142.html

ちょっと遅いです。10秒近くかかると思います。
上手くやれば、もっと速くできると思いますが、そう何度も使うマクロではないと思うので :-)


GM91さんのコメント
ありがとうございます 簡単にいうと、10×10(16×16とかでもOK)くらいの入力点の間を内挿して、256点×256点のテーブルを作りたいのです。 内挿する点は与えた点の直線補間でOK。 蛇足だと思いますがイメージ的な話をしますと、 例えば、東海道新幹線の各駅のキロ程と到着時刻を入力して、中間地点のキロ程から凡その通過時刻を割り出したい 行:各駅のキロ程(要素1:新大阪 0km、 要素2:京都 39km、・・・東京 515km) 0,56,…,515 列:各駅までの所要時間(分)(要素1:新大阪 0分、 要素2:京都 15分、・・・東京 160分) 0,15,…,160 これを与えて、行列各々256分割のCSVイメージを作りたい。 ※Excelシートに256×256の結果を出しても良いし、直接テキストファイルやCSVファイルに出力するでもOK。 「線形補間でよい」というのは、例えば、 米原と岐阜羽島間で加減速したりとかは特に気にせずに単純に2駅間を等速で走行する前提でOK、という意味です。 ※贅沢を言えば、入力する点数は10×10〜20×20くらいで対応できると嬉しいです。(出力は256^2で固定OK)

a-kuma3さんのコメント
あ、内挿 ∠(・`_´・ )

a-kuma3さんのコメント
データの補間について、回答に追記しました。

a-kuma3さんのコメント
あ、修正前のコードを貼ってしまった。少々お待ちを。

a-kuma3さんのコメント
正しいコードにしました <tt>(^^;</tt>

GM91さんのコメント
試してみました、非常に良い感じです。 感服つかまつりました。 補間の件は、リンク先の内容で頭がクラクラしたのですが、妥当かどうかはまた検証してみます。 ありがとうございました!

a-kuma3さんのコメント
>> 補間の件は、リンク先の内容で頭がクラクラしたのですが、妥当かどうかはまた検証してみます。 << 式をいただいただけです。 最初は自分でやろうかと魔が差したのですが、15分で諦めました <tt>:-)</tt>

a-kuma3さんのコメント
>> 選択中のシートの左上10×10 の領域を、"Sheet2" の 256×256 の領域に書き出します。 << とか書きながら、コードは Sheet<span style="color:red;">5</span> になっていたという <tt>orz</tt> ザルで すみません...

a-kuma3さんのコメント
度々、すみません。 X と Y のデータを取り違えてました。 >|vb| v00 = Cells(x0, y0).Value v10 = Cells(x1, y0).Value v01 = Cells(x0, y1).Value v11 = Cells(x1, y1).Value ||< の部分は、以下のようになっているのが正解です。 >|vb| v00 = Cells(y0, x0).Value v10 = Cells(y0, x1).Value v01 = Cells(y1, x0).Value v11 = Cells(y1, x1).Value ||< # 回答のコードも修正しました <tt>m(_ _)m</tt> おまけ。 元の 10×10 の領域にランダムな値を埋めるサブルーチンです。下記では -50 ? +50 の範囲の乱数を入れてます。 >|vb| Sub make_data_random() vfirst = -50 vrange = 100 Randomize For r = 1 To from_max For c = 1 To from_max Cells(r, c).Value = vfirst + Rnd * vrange Next Next End Sub ||< # うーん、テスト 大切だ

GM91さんのコメント
ありがとうございます。 シート名は自分で直したので無問題よ。 ちなみにウチのpcだと待たされ感ゼロです。

1-5件表示/6件
4.前の5件|次5件6.
関連質問

●質問をもっと探す●



0.人力検索はてなトップ
8.このページを友達に紹介
9.このページの先頭へ
対応機種一覧
お問い合わせ
ヘルプ/お知らせ
ログイン
無料ユーザー登録
はてなトップ