『Cプログラミング診断室』目次

付録A 課題解答例


第1章で出題しておいた2つの課題 の解答例です。個人的なツールとして使用しているだけのプログラムなので、 自分で満足できる程度に動けばよいと言うことで作っています。だからといっ て、あまりいいかげんに書くと後で自分で分からなくなってしまうといやなの で、簡単なこのようなプログラムでも、私はそれなりにコメントを入れて書く ようにしています。

課題1の関数長を求めるのがリストA−1、 課題2のヒストグラムを作るのがリストA−2です。 いずれも短いプログラムですし、内容的には単純なので説明の必要はないでしょう。これらは、私 が短い自分専用のプログラムを書く時の典型的パターンになっています。

だいたいこの程度のコメントを入れておけば、半年、1年、あるいはもっと時間が経過してから 見ても分かります。関数名、変数名にできるだけ分かりやすい名前を使い、意味の切れ目に空行を 入れることで、見やすくしています。

この程度の短いプログラムは、わざわざC言語を使わず、Perlで書く方が妥当でしょう。Perlを 学習して、書き直してみてください。

◆リストA−1 課題1 関数長を求める

     1	/********************************************************************************/
     2	/*              関数のブロック中の行数を数える                                  */
     3	/*                                                                              */
     4	/*      usage:  funclen   < source   > length_list                              */
     5	/*                                                                              */
     6	/*      関数ブロックは、{ が行の先頭にあると「始まり」を示し、                  */
     7	/*                      } が行の先頭にあると「終わり」を示す。                  */
     8	/*                                                                              */
     9	/********************************************************************************/
    10	
    11	#include        <stdio.h>
    12	#include        <string.h>
    13	#include        <ctype.h>
    14	
    15	#define TRUE    (1)
    16	#define FALSE   (0)
    17	
    18	static  void    find_funcname();
    19	static  char    * get_line();
    20	
    21	#define BUFLENGTH       1000
    22	
    23	static  char    line[BUFLENGTH];                /* 1行分のバッファ     */
    24	static  char    funcname[BUFLENGTH];            /* 関数名               */
    25	static  int     line_no = 1;                    /* 行番号               */
    26	
    27	/********************************************************************************/
    28	/*                              メイン・プログラム                              */
    29	/********************************************************************************/
    30	main()
    31	{
    32	        int     start_n;
    33	
    34	        start_n = 0;
    35	
    36	        while( get_line() ) {
    37	                switch( line[0] ) {
    38	                case '{':
    39	                        start_n = line_no;      break;
    40	                case '}':
    41	                        if( strchr( line, ';' ) == NULL )       /*  }; を除く   */ 
    42	                                if( start_n > 0 )
    43	                                        printf( "%5d\t%s\n", 
    44	                                                line_no - start_n - 1, funcname );
    45	                        funcname[0] = 0;
    46	                        start_n = 0;
    47	                        break;
    48	                default:
    49	                        if( start_n == 0 )
    50	                                find_funcname();
    51	                }
    52	        }
    53	}
    54	
    55	/*------------------------------------------------------------------------------*/
    56	/*                              関数名の取りだし                                */
    57	/*------------------------------------------------------------------------------*/
    58	static  void    find_funcname()
    59	{
    60	        char    work[BUFLENGTH];
    61	        char    *p, *q;
    62	
    63	        if( strchr( line, '(' ) == NULL )               /*  ( のない行は無視    */
    64	                return;
    65	
    66	        work[0] = 0;
    67	        for( p = line; *p ; ++p ) {
    68	                if( *p==' ' || *p=='\t' )
    69	                        continue; 
    70	                if( *p == '(' )
    71	                        break;
    72	                if( *p == '#' )
    73	                        break;
    74	                if( isalpha(*p) || *p=='_' ) {
    75	                        q=work;
    76	                        while( isalpha(*p) || isdigit(*p) || *p=='_' )
    77	                                *q++ = *p++;
    78	                        *q = 0;
    79	                        --p;
    80	                }
    81	        }
    82	        if( work[0] )
    83	                strcpy( funcname, work );
    84	}
    85	
    86	/*------------------------------------------------------------------------------*/
    87	/*                              1行分の取りだし                                */
    88	/*------------------------------------------------------------------------------*/
    89	static  char    * get_line()
    90	{
    91	        static  comment = FALSE;
    92	        char    *p;
    93	
    94	        if( gets(line) == NULL )
    95	                return  NULL;
    96	
    97	                                        /* コメントの部分をブランクにする       */
    98	        for( p=line; *p ; ++p ) {
    99	                if( comment ) {                 /* コメントの終了判定   */
   100	                        if( *p=='*' && *(p+1)=='/' ) {
   101	                                *p++ = ' ';
   102	                                comment = FALSE;
   103	                        }
   104	                        *p   = ' ';
   105	                } else {                        /* コメントの開始判定   */
   106	                        if( *p=='/' && *(p+1)=='*' ) {
   107	                                *p++ = ' ';
   108	                                *p   = ' ';
   109	                                comment = TRUE;
   110	                        }
   111	                }
   112	        }
   113	
   114	        ++line_no;
   115	
   116	        return  line;
   117	}
   118	
   119	/********************************************************************************/
   120	/*                              EOF  "funclen.c"                             */
   121	/********************************************************************************/

◆リストA−2 課題2 ヒストグラムを求める

     1	/********************************************************************************/
     2	/*              ヒストグラムの作成                                              */
     3	/*                                                                              */
     4	/*      usage:  histgram  [width]   < numbers                                   */
     5	/*              width には、各階級の幅を指定する。1 はデフォルト                */
     6	/*              numbers には、1行に整数(非負整数)を1つ指定する。            */
     7	/*                                                                              */
     8	/********************************************************************************/
     9	
    10	#include        <stdio.h>
    11	
    12	#define MAX_INDEX               2000
    13	#define DEFAULT_CLASS_WIDTH     10
    14	#define DEFAULT_GRAPH_WIDTH     1000
    15	
    16	int     hist[MAX_INDEX];                        /*  ヒストグラムの度数分布配列  */
    17	int     max_index, min_index;                   /*  最大、最小のインデックス    */
    18	int     total_number;                           /*  標本の総数                  */
    19	int     class_width;                            /*   ヒストグラムの階級の幅     */
    20	int     graph_width;                            /*   ヒストグラムの表示幅       */
    21	
    22	static  void    read_arg(), initializing(), read_data(), print_histogram();
    23	
    24	/********************************************************************************/
    25	/*                              メイン・プログラム                              */
    26	/********************************************************************************/
    27	main( argc, argv )
    28	  int   argc;
    29	  char  **argv;
    30	{
    31	        read_arg( argc, argv );
    32	        initializing();
    33	
    34	        read_data();
    35	
    36	        print_histogram();
    37	}
    38	
    39	/*------------------------------------------------------------------------------*/
    40	/*                              HELP                                        */
    41	/*------------------------------------------------------------------------------*/
    42	static  void    help()
    43	{
    44	        fprintf( stderr, "usage : histgram [-c class_width]  [-g glaph_width]\n" );
    45	        exit(1);
    46	}
    47	
    48	/*------------------------------------------------------------------------------*/
    49	/*                              引数処理                                        */
    50	/*------------------------------------------------------------------------------*/
    51	static  void    read_arg( argc, argv )
    52	  int   argc;
    53	  char  **argv;
    54	{
    55	        int     n;
    56	
    57	        class_width = DEFAULT_CLASS_WIDTH;
    58	        graph_width = DEFAULT_GRAPH_WIDTH;
    59	
    60	        while( ++argv, --argc>0 ) {
    61	                if( **argv != '-' )
    62	                        help();
    63	
    64	                switch( (*argv)[1] ) {
    65	                case 'h':
    66	                        help();
    67	                        break;          
    68	                case 'c':
    69	                        ++argv, --argc;
    70	                        n = atoi(*argv);                        
    71	                        if( n > 0 )
    72	                                class_width = n;
    73	                        break;
    74	                case 'g':
    75	                        ++argv, --argc;
    76	                        n = atoi(*argv);
    77	                        if( n > 0 )
    78	                                graph_width = n;
    79	                        break;
    80	                }
    81	        }
    82	}
    83	
    84	/*------------------------------------------------------------------------------*/
    85	/*                              初期化                                          */
    86	/*------------------------------------------------------------------------------*/
    87	static  void    initializing()
    88	{
    89	        int     i;
    90	
    91	        for( i=0 ; i<MAX_INDEX ; ++i )
    92	                hist[ i ] = 0;
    93	
    94	        max_index = -1;
    95	        min_index = MAX_INDEX;
    96	}
    97	
    98	/*------------------------------------------------------------------------------*/
    99	/*                              データの読み取り                                */
   100	/*------------------------------------------------------------------------------*/
   101	static  void    read_data()
   102	{
   103	        int     n;
   104	        int     idx;
   105	        char    buf[1000];
   106	
   107	        for( total_number=0 ; gets(buf) ; ++total_number ) {
   108	                if( 1 != sscanf( buf, "%d", &n ) )
   109	                        continue;
   110	                idx = n / class_width;
   111	                if( idx >= MAX_INDEX )
   112	                        idx = MAX_INDEX - 1;
   113	                ++hist[idx];
   114	
   115	                if( max_index < idx )   max_index = idx;
   116	                if( min_index > idx )   min_index = idx;
   117	        }
   118	}
   119	
   120	/*------------------------------------------------------------------------------*/
   121	/*                              ヒストグラムの表示                              */
   122	/*------------------------------------------------------------------------------*/
   123	static  void    print_histogram()
   124	{
   125	        int     i, j, k, l;
   126	        float   cum;
   127	        char    head[50];
   128	        char    work[50];
   129	        int     head_length;
   130	
   131	        if( total_number == 0 )
   132	                exit( 0 );
   133	
   134	        cum = 0.0;
   135	        for( i = min_index; i <= max_index ; ++i ) {
   136	                if( class_width == 1 )
   137	                        sprintf( head, "%5d ", i );
   138	                else
   139	                        sprintf( head, "%4d-%4d ",
   140	                                        i*class_width, (i+1)*class_width-1 );
   141	
   142	                cum += hist[i];
   143	                sprintf( work, "%5.1f%%  %5d  ", cum/total_number*100.0 , hist[i] );
   144	                strcat( head, work );
   145	                head_length = strlen( head );
   146	                printf( "%s", head );
   147	                for( j=0 ; j<head_length ; ++j )
   148	                        head[j]=' ';
   149	
   150	                for( k=j=0 ; j<hist[i] ; ++j ) {
   151	                        if( ++k > graph_width ) {
   152	                                printf( "\n%s", head );
   153	                                k = 1;
   154	                        }
   155	                        printf( "*" );
   156	                }
   157	                printf( "\n" );
   158	        }
   159	}
   160	
   161	/********************************************************************************/
   162	/*                              EOF  "histgram.c"                            */
   163	/********************************************************************************/


Copyright1996 Hirofumi Fujiwara. No reproduction or republication without written permission
『Cプログラミング診断室』目次