『Cプログラミング診断室』目次次(第4章 キャストが好き 自動的型変換)

第4章 キャストが好き

プログラムの紹介


今回は、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は、非常に小さな、画面に収まるくらいのプログラムを書くには、大変便利な 言語です。命令、関数の数は非常に増えていますが、基本的な部分は非常に小さく、コンピュータ 入門には最適かと思います。もともと入門用に考案された言語で、コンピュータの勉強を始めるに は良いのですが、古典的BASIC(例えば、N88-BASIC)は入門レベル以上のことを考慮していない言語 ですから、これで何か大きなソフトを作ろうなどと思ってしまうと、とんでもない泥沼にはまって しまいます。

BASICからCへの移行に失敗している方が多いようですが、そのようなときは、Cへ一気に行か ず、マイクロソフトのQuickBASICなどを試みてはいかがでしょうか。BASICといっても、こちらは プログラミング言語的にもしっかりしているし、BASICとの違和感も少ないので、これで、ちゃん とした言語に慣れると、Cへの道も楽になると思います。


Copyright1996 Hirofumi Fujiwara. No reproduction or republication without written permission
『Cプログラミング診断室』
目次次(第4章 キャストが好き 自動的型変換)