第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 /********************************************************************************/ |