mots quotidiens. | |
Daichi Mochihashi (持橋大地) daichi <at> ism.ac.jp | by hns, version 2.10-pl1. |
|
||||||||||||||||||||||||||||||||||||||||||||||
double **matrix = dmatrix(rows, cols); for (i = 0; i < rows; i++) for (j = 0; j < cols; j++) if (matrix[i][j] > 0) ...のように使う。ただし, 単なる配列の配列なので, 行列の大きさ(rowsとcols) は別に覚えておく必要がある。
一番簡単な解決策は, ベクトルの場合は
typedef struct { double *content; int length; } dvector;のような構造体を定義しておいて
for (i = 0; i < v->length; i++) if (v->content[i]) ...のように使うことですが, これは v[i] のようにはアクセスできません (contentは構造体の先頭にあるが, lengthフィールドがあるため, 無理矢理 v[i] としてもオフセットが狂ってしまう)。
少し考えると, 後ろに length があるからいけないのであって, 前に持たせればよくね? ということで, 次のようなコードを書くと, C言語でも普通に配列に長さを持たせる ことができることに気付いた。
/* dvector2.c */ double * dvector (int size) { double *v; if ((v = (double *)calloc(size + 1, sizeof(double))) == NULL) { perror("dvector"); return NULL; } /* record size */ *((int *)v) = size; v += 1; return v; } void free_dvector (double *v) { free(v - 1); }ここで, dvector.h で
#define vsize(v) *((int *)(v-1))としておくと,
double *v = dvector(20); double **m = dmatrix(n, k); for (i = 0; i < vsize(v); i++) if (v[i] > 0) ... for (i = 0; i < mrows(m); i++) for (j = 0; j < mcols(m); j++) if (m[i][j] > 0) ...のように普通にMATLABのように使うことができ, 長さを覚えておく必要がない。 行列の場合にも同じことができ, 2つ分前に行数と列数を入れておいて, *((int *)) でアクセスすればok。下に dvector2.{c,h}, dmatrix2.{c,h} を置いておきます。
ポイントは, これは全く合法的なことをしているので, C言語なら必ず使えて,
外からは普通の double *, double ** と全く同じだということです。
これまで, 配列のサイズを変更する時は前の長さを与えないといけなかったり,
行列の場合は free() する場合もfree()するべき列の数を外から与えて
やらないといけませんでしたが, これで勝手に長さを自分で取得して
リサイズしたり, free() したりできるので, その点でも便利です。
唯一心配すべきなのは, double や double * にintが入らない場合ということですが,
sizeof(int) > sizeof(double) だったり, int がポインタのサイズより大きいような
変態的な環境は普通はないと思うので, 心配しなくてよさそうです
(thanks to 高林君)。
*2
これで, C言語の配列/行列もMATLABのように使えるようになりました。
#define matrix_val(m,i,j) m[i][j] #define vector_len(v) vsize(v) ..を用意しておいて,
#!/bin/sh # # indenter # if [ $# -lt 2 ]; then echo "usage: $0 replace.cpp source.c" exit 0 fi sed 's/^#/_CPP_DIRECTIVE_/g' $2 | cat $1 - | cpp -C -P | \ sed 's/^_CPP_DIRECTIVE_/#/g' | indent -bl -bli0 -psl -krのようなスクリプトを書くことで, 綺麗に変換することができました。
タイトル一覧 |