『Cプログラミング診断室』目次次(第8章 Pascalが好き オプション文字列処理)

第8章 Pascalが好き

Pascal?


リスト8−1を見てください。C言語のようであって、そうでなさそうな、とにかく奇妙なコー ディングです。関数本体の開始の{もなければ、終了の }もありません。どうも、その代わりに、 BEGINと ENDがあるみたいです。その他にも、THEN, ELSE, ENDIF などの、本来C言語では使うは ずのないものがいっぱいあるからです。これを書いたプログラマは正気なのでしょうか。

 
リスト8−1 Pascal みたいな C

     1	chkarg( argc , argv )         /* Parameters check             */
     2	
     3	    int            argc     ;
     4	    char           *argv[]  ;
     5	
     6	    BEGIN
     7	
     8	       int         argn                            /* Number of arguments    */
     9	       ,           opt                           ; /* option character       */
    10	
    11	         for ( argn = 1, paramnum = 0 ; argn < argc ; argn++ )
    12	           BEGIN
    13	              if ( *argv[argn] == OPTION )         /* Option?                */
    14	                THEN
    15	                   if ( opt = *++argv[argn] & ASCII )
    16	                     THEN
    17	                        switch ( isalpha ( opt ) ? toupper ( opt ) : opt )
    18	                          BEGIN
    19	                             case 'E' : if (*++argv[argn] == '=')
    20	                                          THEN
    21	                                             dspsttid  = atoi (++argv[argn]);
    22	                                             argv[argn] = index (argv[argn], NULL);
    23	                                          ELSE
    24	                                             xexit (E_IFORKP);
    25	                                          ENDIF
    26	                                        break;
    27	                             case 'W' : if (*++argv[argn] == '=')
    28	                                          THEN
    29	                                             dirname = ++argv[argn];
    30	                                             argv[argn] = index(argv[argn], NULL);
    31	                                          ELSE
    32	                                             xexit (E_IFORKP);
    33	                                          ENDIF
    34	                                        break;
    35	                             case 'F' : switch (*++argv[argn])
    36	                                          BEGIN
    37	                                             case '0': if (*++argv[argn] == '=')
    38	                                                         THEN
    39	                                                            f0pathlist = ++argv[argn];
    40	                                                            argv[argn] = index (argv[argn], NULL);
    41	                                                         ELSE
    42	                                                            if (*argv[argn] == '0' && *++argv[argn] == '=')
    43	                                                              THEN
    44	                                                                 f00pathlist = ++argv[argn];
    45	                                                            argv[argn] = index (argv[argn], NULL);
    46	                                                              ELSE
    47	                                                                 xexit (E_IFORKP);
    48	                                                              ENDIF
    49	                                                         ENDIF
    50	                                                       break;
    51	                                             case '1': if (*++argv[argn] == '6' && *++argv[argn] == '=')
    52	                                                         THEN
    53	                                                            f16pathlist= ++argv[argn];
    54	                                                            argv[argn] = index (argv[argn], NULL);
    55	                                                         ELSE
    56	                                                            xexit (E_IFORKP);
    57	                                                         ENDIF
    58	                                                       break;
    59	                                             case '2': if (*++argv[argn] == '=')
    60	                                                         THEN
    61	                                                            f2pathlist = ++argv[argn];
    62	                                                            argv[argn] = index (argv[argn], NULL);
    63	                                                         ELSE
    64	                                                            xexit (E_IFORKP);
    65	                                                         ENDIF
    66	                                                       break;
    67	                                             case '3': if (*++argv[argn] == '=')
    68	                                                         THEN
    69	                                                            f3pathlist = ++argv[argn];
    70	                                                            argv[argn] = index (argv[argn], NULL);
    71	                                                         ELSE
    72	                                                            xexit (E_IFORKP);
    73	                                                         ENDIF
    74	                                                       break;
    75	                                             case '4': if (*++argv[argn] == '=')
    76	                                                         THEN
    77	                                                            f4pathlist = ++argv[argn];
    78	                                                            argv[argn] = index (argv[argn], NULL);
    79	                                                         ELSE
    80	                                                            xexit (E_IFORKP);
    81	                                                         ENDIF
    82	                                                       break;
    83	                                             default:  break;
    84	                                          ENDSWITCH
    85	                                        break   ;
    86	                             case '?' : syntax (); exit ( NO_ERROR ) ;
    87	                             default  : syntax (); exit ( E_IFORKP ) ;
    88	                          ENDSWITCH
    89	                     ENDIF
    90	                ELSE
    91	                   if ( paramnum < PARAM_MAX )
    92	                     THEN                          /* Set parameter pointer  */
    93	                        param[paramnum++] = argv[argn]
    94	                     ELSE
    95	                     ENDIF
    96	                ENDIF
    97	           ENDFOR
    98	
    99	         if ( paramnum < PARAM_MIN )               /* No parameter ?         */
   100	           THEN                                    /* Display syntax         */
   101	              syntax ()                          ;
   102	              exit ( NO_ERROR )
   103	           ELSE
   104	           ENDIF
   105	         jobid = atoi (param[JOB_ID]);          /* Set Job-ID (task-ID) */
   106	    END

実は、これらのマクロはプログラムの先頭でリスト8−2のマクロ定義により、

	BEGIN    は    {    
	END      は    ;}   
というように、予約語や記号に置換され、C言語として扱われるのです。

 
リスト8−2 予約語のマクロ定義

     1	#define  BEGIN     {
     2	#define  END       ;}
     3	#define  THEN      BEGIN
     4	#define  ELSE      END else BEGIN
     5	#define  ENDIF     END
     6	#define  ENDWHILE  END
     7	#define  DO        do BEGIN
     8	#define  WHILE     END while(
     9	#define  ENDDO     );
    10	#define  REPEAT    DO
    11	#define  UNTIL     WHILE!(
    12	#define  ENDREPEAT )ENDDO
    13	#define  ENDFOR    END
    14	#define  NEXT      END
    15	#define  LOOP      for(;;)BEGIN
    16	#define  ENDLOOP   END
    17	#define  ENDSWITCH END

謎はすぐに解けましたが、「なぜ」このようなマクロ定義をしたのでしょうか。なぜ、C言語ら しさがまったくなくなるような細工をしたのでしょうか。つねに、BEGINとENDで囲みたがっている ところは、C言語を、何とかPascalのように書きたいように見えます。また、英大文字の予約語が 増えると、BASICのようにも見えてきます。つまり、リスト8−2のようにマクロ定義すると、ま るで PascalとBASICの「合いの子」のようにも書けるのですね。おもしろいマクロの使い方ですね。

■破門■

でも、ここまでC言語らしさを殺して使うのであれば、Pascalなどの他の言語でプログラミング すべきではないでしょうか。それとも、Cコンパイラしかなく、Pascalのコーディングにしか慣れ ていないための窮余の一策だったのでしょうか。でも、ここまでC言語らしさがなくなってしまう と、Cのプログラムとしては扱いかねますね。

このような特殊なコーディングをしてしまうと、エディタの括弧のバランスとか、字下げを自動 的にしてくれる便利な機能が働かなくなります。だから、眼力に頼るか、コンパイルしてエラーを 出すことで括弧バランスの崩れを見つけざるを得なくなります。これでは、とても私のように「楽」 をしたいと日々思い悩んでいる者にはできないし、そのようなプログラムを見せられたら、逃げ出 してしまいます。エディタの機能を抹殺するようなコーディングだけは止めましょう。

それとも、これを書いたプログラマは、プリントアウトしたリストを見て、この書法が良いと判 断したのでしょうか。10年前の、リストはコーディング用紙に書いて、パンチャーにカードを打っ てもらう大昔ならともかく、誰もがスクリーンエディタを使っている今日、スクリーンエディタの 機能を生かせないような方法は考えられません。そういえば、昔、画面だけでエディトしているの では不安らしく、必ずカードで作業していた上司がいました。

また、当然のことですが、C言語のプログラムを書く以上、C言語の作法から極度に逸脱してし まうと、世のCプログラマから一切相手にされなくなります。「村八分」になってしまいます。自 分の作ったプログラムは永久に自分しか見ないような場合には、どんなコーディングをしようと勝 手ですが、仕事で作るプログラムでは、そんな身勝手は許されません。

このような方法を紹介して喜んでいる本も巷にはあるようですが、けっしてこのような書き方は まねないようにしましょう。無人島でただ一人でプログラミングしていて、外界と隔絶されている ような場合は本人の勝手でしょう。しかし、Cプログラマの世界から破門されたくなかったら、今 すぐ改宗しましょう。

ということで、リスト8−1は、ばっさり書き換えてしまいましょう。


Copyright1996 Hirofumi Fujiwara. No reproduction or republication without written permission
『Cプログラミング診断室』目次次(第8章 Pascalが好き オプション文字列処理)