リスト9−1を見てください。実際のファイルは長いので、1つの関数の部分だけを取り出した ものです。リスト9−2が、DATE型に関する定義部分です。
リスト9−1 オリジナルプログラム 構造体の処理 |
1 int saveall_execute( item, event ) 2 Panel_item item; /*アイテムハンドル*/ 3 Event *event; /*イベントアドレス*/ 4 { 5 BYTE job[JOBNAME_LEN+1]; 6 BYTE plane[PLANENO_LEN+1]; 7 BYTE com[COMMENT_LEN+1]; 8 BYTE term[TERMINAL_LEN+1]; 9 int i; 10 Panel panel; 11 DATE old_date; 12 int old_term; 13 14 xv_set( base_frame, FRAME_BUSY, TRUE, NULL ); 15 panel = (Panel)xv_get( item, PANEL_PARENT_PANEL ); 16 if ( tr_jobname( saveall_frame, item, 17 saveall_job_item, saveall_plane_item, 18 job, plane ) != NORMAL ) 19 { 20 xv_set( base_frame, FRAME_BUSY, FALSE, NULL ); 21 return XV_ERROR; 22 } 23 strcpy( com, (char *)xv_get( saveall_com_item, PANEL_VALUE ) ); 24 strcpy( term, (char *)xv_get( saveall_terminal_item, PANEL_LABEL_STRING ) ); 25 26 termlist_end( ); 27 xv_set( saveall_frame, XV_SHOW, FALSE, NULL ); 28 command_end( ); 29 30 strncpy( base.job_name, job, JOBNAME_LEN ); 31 strncpy( base.plane_no, plane, PLANENO_LEN ); 32 strncpy( base.comment, com, COMMENT_LEN ); 33 old_term = term_no; 34 term_no = saveall_termno; 35 36 old_date.year[0] = base.date.year[0]; 37 old_date.year[1] = base.date.year[1]; 38 old_date.month[0] = base.date.month[0]; 39 old_date.month[1] = base.date.month[1]; 40 old_date.day[0] = base.date.day[0]; 41 old_date.day[1] = base.date.day[1]; 42 old_date.hour[0] = base.date.hour[0]; 43 old_date.hour[1] = base.date.hour[1]; 44 old_date.minute[0] = base.date.minute[0]; 45 old_date.minute[1] = base.date.minute[1]; 46 old_date.second[0] = base.date.second[0]; 47 old_date.second[1] = base.date.second[1]; 48 get_date( (PDATE)&base.date ); 49 if ( save_rundata( OFF ) == NORMAL ) 50 { 51 edit = OFF; 52 if ( savequit == 1) 53 { 54 savequit = OFF; 55 xv_set( base_frame, FRAME_BUSY, FALSE, NULL ); 56 xv_set( base_frame, FRAME_NO_CONFIRM, TRUE, NULL ); 57 xv_destroy_safe( base_frame ); 58 return XV_OK; 59 } 60 else if ( savequit == 2 ) 61 { 62 savequit = OFF; 63 xv_set( base_frame, FRAME_BUSY, FALSE, NULL ); 64 mainmenu_mode = MAINID_CREATE_CREATE; 65 create_create( ); 66 } 67 else if ( savequit == 3 ) 68 { 69 savequit = OFF; 70 xv_set( base_frame, FRAME_BUSY, FALSE, NULL ); 71 mainmenu_mode = MAINID_CREATE_FILE; 72 file_read( ); 73 } 74 else if ( savequit == 5 ) 75 { 76 savequit = OFF; 77 xv_set( base_frame, FRAME_BUSY, FALSE, NULL ); 78 mainmenu_mode = MAINID_CREATE_OUTPUT; 79 file_output( ); 80 } 81 } 82 else 83 { 84 term_no = old_term; 85 base.date.year[0] = old_date.year[0]; 86 base.date.year[1] = old_date.year[1]; 87 base.date.month[0] = old_date.month[0]; 88 base.date.month[1] = old_date.month[1]; 89 base.date.day[0] = old_date.day[0]; 90 base.date.day[1] = old_date.day[1]; 91 base.date.hour[0] = old_date.hour[0]; 92 base.date.hour[1] = old_date.hour[1]; 93 base.date.minute[0] = old_date.minute[0]; 94 base.date.minute[1] = old_date.minute[1]; 95 base.date.second[0] = old_date.second[0]; 96 base.date.second[1] = old_date.second[1]; 97 } 98 xv_set( base_frame, FRAME_BUSY, FALSE, NULL ); 99 return XV_OK; 100 } |
リスト9−2 オリジナルプログラム 構造体の宣言 |
1 typedef char BYTE; /* 符号付き1バイト */ 2 typedef BYTE *PBYTE; 3 typedef unsigned char UBYTE; /* 符号無し1バイト */ 4 typedef UBYTE *PUBYTE; 5 6 7 typedef struct { 8 UBYTE year[2]; /* 年 */ 9 UBYTE month[2]; /* 月 */ 10 UBYTE day[2]; /* 日 */ 11 UBYTE hour[2]; /* 時 */ 12 UBYTE minute[2]; /* 分 */ 13 UBYTE second[2]; /* 秒 */ 14 } DATE; 15 typedef DATE *PDATE; |
まず感じるのは、関数ブロックの中が、字下げ(インデンテーション)されていないことです。 この程度なら字下げされていなくても、関数の開始、終了はすぐ分かりますが、長くなると分かり づらいので、関数の内部は1タブ下げるようにしましょう。
xv_set, xv_getはXViewの関数です。詳しく知りたい方は、Xのマニュアルの第7巻(参考文献) を見てください。
36〜47行は
36 old_date.year[0] = base.date.year[0]; 37 old_date.year[1] = base.date.year[1]; 38 old_date.month[0] = base.date.month[0]; 39 old_date.month[1] = base.date.month[1]; 40 old_date.day[0] = base.date.day[0]; 41 old_date.day[1] = base.date.day[1]; 42 old_date.hour[0] = base.date.hour[0]; 43 old_date.hour[1] = base.date.hour[1]; 44 old_date.minute[0] = base.date.minute[0]; 45 old_date.minute[1] = base.date.minute[1]; 46 old_date.second[0] = base.date.second[0]; 47 old_date.second[1] = base.date.second[1];85〜96行は
85 base.date.year[0] = old_date.year[0]; 86 base.date.year[1] = old_date.year[1]; 87 base.date.month[0] = old_date.month[0]; 88 base.date.month[1] = old_date.month[1]; 89 base.date.day[0] = old_date.day[0]; 90 base.date.day[1] = old_date.day[1]; 91 base.date.hour[0] = old_date.hour[0]; 92 base.date.hour[1] = old_date.hour[1]; 93 base.date.minute[0] = old_date.minute[0]; 94 base.date.minute[1] = old_date.minute[1]; 95 base.date.second[0] = old_date.second[0]; 96 base.date.second[1] = old_date.second[1];
となっています。構造体であるDATE型のbase.date(現データ)を、old_dateに複写しておき、処理 に失敗したとき、old_dateからbase.dateに戻すことで回復処理をしています。でも、1バイト毎 に代入しています。年、月、日、時、分、秒それぞれに2バイトを割り当てているので、結局12個 の代入文をずらーっとというか、だらだらというべきか並べています。=で構造体の代入ができる ことを知らないのでしょうね。それぞれの12行は、
old_date = base.date; と base.date = old_date;で済みます。
これは単に12行が1行に縮んだだけではありません。これによって、保守性が向上しているので す。たとえば、year[2]がyear[4]に変更になった場合、修正版では何の変更も不要です。オリジナ ルでは、2行追加になります。もし、ミリセカンドを追加したいときでも、修正版では変更不要で す。修正版では、構造体の内部がどのように変化しようとも、一切修正が要りません。
横着(世間ではエレガントとも言う)に書くと、その後も横着できる、サボれることを理解し、 実施しましょう。そのうえ、サボったプログラムは品質が良いのです。「サボリ」はプログラマの とっての最大の「美徳」です。「力」をこめてプログラムを書いたりしたら、プログラムもキーボー ドも痛んでしまうではないですか。
その他には、標準型のcharは嫌いらしく、BYTE, PBYTE,UBYTE,PUBYTEなどで置き換えていますが、 あまり意味はないでしょう。プログラム全体できちんと使っていないのだから、本当に無意味でしょ う。
修正した関数をリスト9−3、DATEの型宣言をリスト9−4に示します。
リスト9−3 修正版 構造体の処理 |
1 int saveall_execute( item, event ) 2 Panel_item item; /*アイテムハンドル*/ 3 Event *event; /*イベントアドレス*/ 4 { 5 char job[JOBNAME_LEN+1]; 6 char plane[PLANENO_LEN+1]; 7 char com[COMMENT_LEN+1]; 8 char term[TERMINAL_LEN+1]; 9 DATE old_date; 10 int old_term; 11 12 xv_set( base_frame, FRAME_BUSY, TRUE, NULL ); 13 14 if ( tr_jobname( saveall_frame, item, 15 saveall_job_item, saveall_plane_item, job, plane ) != NORMAL ) 16 { 17 xv_set( base_frame, FRAME_BUSY, FALSE, NULL ); 18 return XV_ERROR; 19 } 20 21 strcpy( com, (char *)xv_get( saveall_com_item, PANEL_VALUE ) ); 22 strcpy( term, (char *)xv_get( saveall_terminal_item, PANEL_LABEL_STRING ) ); 23 24 termlist_end( ); 25 xv_set( saveall_frame, XV_SHOW, FALSE, NULL ); 26 command_end( ); 27 28 strcpy( base.job_name, job ); 29 strcpy( base.plane_no, plane ); 30 strcpy( base.comment, com ); 31 old_term = term_no; 32 term_no = saveall_termno; 33 old_date = base.date; 34 35 get_date( (PDATE)&base.date ); 36 if ( save_rundata( OFF ) == NORMAL ) { 37 edit = OFF; 38 39 switch( savequit ) { 40 case 1: 41 savequit = OFF; 42 xv_set( base_frame, FRAME_BUSY, FALSE, NULL ); 43 xv_set( base_frame, FRAME_NO_CONFIRM, TRUE, NULL ); 44 xv_destroy_safe( base_frame ); 45 return XV_OK; 46 case 2: 47 savequit = OFF; 48 xv_set( base_frame, FRAME_BUSY, FALSE, NULL ); 49 mainmenu_mode = MAINID_CREATE_CREATE; 50 create_create( ); 51 break; 52 case 3: 53 savequit = OFF; 54 xv_set( base_frame, FRAME_BUSY, FALSE, NULL ); 55 mainmenu_mode = MAINID_CREATE_FILE; 56 file_read( ); 57 break; 58 case 5: 59 savequit = OFF; 60 xv_set( base_frame, FRAME_BUSY, FALSE, NULL ); 61 mainmenu_mode = MAINID_CREATE_OUTPUT; 62 file_output( ); 63 break; 64 } 65 } else { 66 term_no = old_term; 67 base.date = old_date; 68 } 69 70 xv_set( base_frame, FRAME_BUSY, FALSE, NULL ); 71 return XV_OK; 72 } |
リスト9−4 修正版 構造体の宣言 |
1 typedef struct { 2 char year[2]; /* 年 */ 3 char month[2]; /* 月 */ 4 char day[2]; /* 日 */ 5 char hour[2]; /* 時 */ 6 char minute[2]; /* 分 */ 7 char second[2]; /* 秒 */ 8 } DATE; |