今回は、BASICプログラムを5年間プロとしてやってきて、1年前に世間の流れに従って(もし かして、流れに飲み込まれて)、Cプログラマに転向した人のプログラムです。いろいろな言語か らC言語に移っている人は非常に多いと思います。その中で、いつも変なプログラムを書き、問題 を起こすのは、決まってBASICから移った人達です。 今回の特徴は、C言語の「型」が全く理解できていないことです。型の理解もせずにCプログラ ムを書き続けているとは、恐ろしいことです。ポインタや配列の使い方にも問題があります。
■プログラム■元のプログラム(ソースファイル)は1000行以上あり、#includeで型宣言部分が読み込まれてい たりしたのですが、最初の1/4くらいで十分だと思い、残りは勝手に切り捨て、#includeの部分は、 説明に必要な部分だけを直接先頭部分に移しました。そのために、static関数しかないリストになっ てしまいましたが、C言語の勉強には十分でしょう。 リスト4−1に元のプログラム(に近いもの)を示します。とにかく「キャスト」が異常に多い のが目立ちますね。 プログラムは、CADで使われているもので、線分で囲まれた領域内に適当な間隔で線分を引く ハッチング処理を行ないます。CADのソフトは、速度、計算精度などでかなりシビアな要求がさ れることが多いので、中上級の人がプログラムすることが多いのですが、世の中Cプログラマ不足 ですから、なかなかそうも行かず、この程度の人が組んだりしている場合もあるようです。これで、 機械やビルの設計が行なわれているかと思うと、寒気がしてきますね。もし、こんなレベルの人が 医療機器のソフトを組んでいたら、殆んど殺人的行為でしょう。
|
リスト4−1 オリジナルプログラム |
1 /* 2 * ハッチング処理 3 * by BASIC Programmer 4 */ 5 #include <stdio.h> 6 #include <math.h> 7 8 #define MAXSIZE 100 9 10 typedef struct point3 { 11 long x ; 12 long y ; 13 long z ; 14 } POINT3 ; 15 16 typedef struct HATCHING_DATA { 17 long kx, ky, kz ; /* 基準点 */ 18 long hx, hy, hz ; /* 方向 */ 19 short n ; /* データ数 */ 20 long x[MAXSIZE], y[MAXSIZE], z[MAXSIZE] ; /* 座標 */ 21 } HATCHING; 22 23 typedef struct WK { 24 float ct, st, cts[4], sts[4]; 25 } WORK ; 26 27 /*---------- static関数プロトタイプ宣言 ----------*/ 28 29 static void f_swap (float *a, float *b); 30 static float intr(float a); 31 static double sgn(double a); 32 static double length(float x1, float y1, float x2, float y2); 33 static void convert_sub1(float x1, float y1, float x2, float y2, 34 float *cts, float *sts); 35 static void convert_sub2(long *xx, long *yy, float cts, float sts); 36 static void convert2(float *xx, float *yy, float cts, float sts); 37 static void convert1(HATCHING *hin, WORK *hw); 38 static float takasa(long gpx[], long gpy[], long gpz[], float x0, float y0); 39 40 /* 41 * f_swap 42 */ 43 static void f_swap (float *a, float *b) 44 { 45 float c; 46 47 c = *a; 48 *a = *b; 49 *b = c; 50 } 51 52 /* 53 * intr 54 */ 55 static float intr(float a) 56 { 57 double w1; 58 double aa; 59 60 w1 = (double)a; 61 aa = modf(w1, &w1); 62 return((float)w1); 63 } 64 65 /* 66 * sgn 67 */ 68 static double sgn(double a) 69 { 70 if (a != 0.0) 71 return((a < 0.0) ? -1.0 : 1.0); 72 return(0.0); 73 } 74 75 /* 76 * 長さ計算 77 */ 78 static double length(float x1, float y1, float x2, float y2) 79 { 80 double w1, w2; 81 82 w1 = ((double)x1 - (double)x2); 83 w2 = ((double)y1 - (double)y2); 84 return (sqrt(w1 * w1 + w2 * w2)); 85 } 86 87 static void convert_sub1(float x1, float y1, float x2, float y2, 88 float *cts, float *sts) 89 { 90 double d, w1, w2; 91 92 w1 = (double)x2 - (double)x1; 93 w2 = (double)y2 - (double)y1; 94 if (1.0 > (d = sqrt(w1 * w1 + w2 * w2))) { 95 *cts = (float)1.0; 96 *sts = (float)0.0; 97 } else { 98 *cts = (x2 - x1) / (float)d; 99 *sts = (y2 - y1) / (float)d; 100 } 101 } 102 103 static void convert_sub2(long *xx, long *yy, float cts, float sts) 104 { 105 float x, y, xd, yd; 106 107 x = (float)*xx; 108 y = (float)*yy; 109 110 xd = x * cts + y * sts; 111 yd = -x * sts + y * cts; 112 113 *xx = (long)xd; 114 *yy = (long)yd; 115 } 116 117 static void convert2(float *xx, float *yy, float cts, float sts) 118 { 119 float x, y, xd, yd; 120 121 x = *xx; 122 y = *yy; 123 124 xd = x * cts - y * sts; 125 yd = x * sts + y * cts; 126 127 *xx = xd; 128 *yy = yd; 129 } 130 131 /* 132 * convert1 133 */ 134 static void convert1(HATCHING *hin, WORK *hw) 135 { 136 short i, td; 137 float x1, x2, y1, y2; 138 139 td = 1; 140 x1 = (float)hin->x[0]; 141 x2 = (float)hin->x[1]; 142 y1 = (float)hin->y[0]; 143 y2 = (float)hin->y[1]; 144 145 convert_sub1(x1, y1, x2, y2, &hw->cts[td], &hw->sts[td]); 146 147 for (i = 0; i < hin->n; i++) { 148 convert_sub2(&hin->x[i], &hin->y[i], hw->cts[td], hw->sts[td]); 149 } 150 convert_sub2(&hin->kx, &hin->ky, hw->cts[td], hw->sts[td]); 151 convert_sub2(&hin->hx, &hin->hy, hw->cts[td], hw->sts[td]); 152 153 td = 2; 154 x1 = (float)hin->x[0]; 155 x2 = (float)hin->x[1]; 156 y1 = (float)hin->z[0]; 157 y2 = (float)hin->z[1]; 158 159 convert_sub1(x1, y1, x2, y2, &hw->cts[td], &hw->sts[td]); 160 161 for (i = 1; i <= hin->n; i++) { 162 convert_sub2(&hin->x[i], &hin->z[i], hw->cts[td], hw->sts[td]); 163 } 164 convert_sub2(&hin->kx, &hin->kz, hw->cts[td], hw->sts[td]); 165 convert_sub2(&hin->hx, &hin->hz, hw->cts[td], hw->sts[td]); 166 167 td = 3; 168 x1 = (float)hin->y[1]; 169 x2 = (float)hin->y[2]; 170 y1 = (float)hin->z[1]; 171 y2 = (float)hin->z[2]; 172 173 convert_sub1(x1, y1, x2, y2, &hw->cts[td], &hw->sts[td]); 174 175 for (i = 0; i < hin->n; i++) { 176 convert_sub2(&hin->y[i], &hin->z[i], hw->cts[td], hw->sts[td]); 177 } 178 convert_sub2(&hin->ky, &hin->kz, hw->cts[td], hw->sts[td]); 179 convert_sub2(&hin->hy, &hin->hz, hw->cts[td], hw->sts[td]); 180 } 181 182 /* 183 * 高さ 184 */ 185 static float takasa(long gpx[], long gpy[], long gpz[], float x0, float y0) 186 { 187 short tr, i1, i2, p, jj, i; 188 float iy1, iy2, dd, d1, sinr, z, gct, gst, 189 xd, yd, kx1, kx2, kz1, kz2, gminx; 190 float xdd[10], ydd[10], zdd[10], ixd[10], iyd[10], izd[10]; 191 double d; 192 193 iy1 = (float)10000.0; 194 iy2 = (float)-10000.0; 195 tr = 0; 196 while (1) { 197 tr++; 198 i1 = tr; 199 i2 = (tr % 3) + 1; 200 if (1.0 <= (d = length((float)gpx[i1], (float)gpy[i1], 201 (float)gpx[i2], (float)gpy[i2]))) { 202 gct = ((float)gpx[i2] - (float)gpx[i1]) / (float)d; 203 gst = ((float)gpy[i2] - (float)gpy[i1]) / (float)d; 204 gminx = (float)99999.0; 205 for (jj = 1; jj <= 3; jj++) { 206 p = ((tr + jj - 2) % 3) + 1; 207 xdd[jj] = gct * (float)gpx[p] 208 + gst * (float)gpy[p]; 209 ydd[jj] = -gst * (float)gpx[p] 210 + gct * (float)gpy[p]; 211 zdd[jj] = (float)gpz[p]; 212 if (xdd[jj] < gminx) 213 gminx = xdd[jj]; 214 } 215 } 216 xd = gct * x0 + gst * y0; 217 yd = -gst * x0 + gct * y0; 218 if (intr(gminx) == intr(xd)) 219 continue; 220 d1 = (iy1 - iy2); 221 sinr = (iy2 - iy1) / d1; 222 for (i = 1; i <= 3; i++) { 223 ixd[i] = ((zdd[i] - iy1) / d1) * sinr; 224 iyd[i] = -((xdd[i] - xd) / d1) * sinr; 225 izd[i] = ydd[i] - yd; 226 } 227 if (iyd[2]-iyd[1] == (float)0.0 || iyd[3]-iyd[1] == (float)0.0) 228 continue; 229 kx1=ixd[1]+(ixd[2]-ixd[1])*((float)0.0-iyd[1])/(iyd[2]-iyd[1]); 230 kz1=izd[1]+(izd[2]-izd[1])*((float)0.0-iyd[1])/(iyd[2]-iyd[1]); 231 kx2=ixd[1]+(ixd[3]-ixd[1])*((float)0.0-iyd[1])/(iyd[3]-iyd[1]); 232 kz2=izd[1]+(izd[3]-izd[1])*((float)0.0-iyd[1])/(iyd[3]-iyd[1]); 233 if (kz2 - kz1 == (float)0.0) 234 continue; 235 dd = kx1 + (kx2 - kx1) * ((float)0.0 - kz1) / (kz2 - kz1); 236 z = dd * d1 * sinr + iy1; 237 return(z); 238 } 239 } 240 241 /*---------------------------------------------------------------------------*/ 242 /* 途中までです。ごめんなさーい。 by fuji */ 243 /*---------------------------------------------------------------------------*/ |
ところで、BASICは、非常に小さな、画面に収まるくらいのプログラムを書くには、大変便利な 言語です。命令、関数の数は非常に増えていますが、基本的な部分は非常に小さく、コンピュータ 入門には最適かと思います。もともと入門用に考案された言語で、コンピュータの勉強を始めるに は良いのですが、古典的BASIC(例えば、N88-BASIC)は入門レベル以上のことを考慮していない言語 ですから、これで何か大きなソフトを作ろうなどと思ってしまうと、とんでもない泥沼にはまって しまいます。
BASICからCへの移行に失敗している方が多いようですが、そのようなときは、Cへ一気に行か ず、マイクロソフトのQuickBASICなどを試みてはいかがでしょうか。BASICといっても、こちらは プログラミング言語的にもしっかりしているし、BASICとの違和感も少ないので、これで、ちゃん とした言語に慣れると、Cへの道も楽になると思います。