プログラマのための ~ 新 MS ー DOS プロクラミンク入門 TabIe 7 #define _A_VO い D #define _A_SUBDI R attr & _A_ARCH 1 : h . 26 : * / —dos—setfileattr 関数 (MS-C 5.1 ) ファイル属性の設定 unsigned—dos—setfileattr(path, attr) ; # include <dos. h> Table 8 getfileattr 関数 char *path; unsigned *attr; 属性を取得するファイル名 設定する属性 ファイル属性の取得 属性定数 MS-C 5.1 unsigned *attr; char *path; int getfileattr(path, attr) ; #include<dos. h> 属性定数 Turbo C 2.0 戻り値 TabIe 9 = 0 : 正常終了 = 0 : 工ラー ( MS ー DOS のエラーコード ) ファイル属性の設定 setfileattr 関数 # include <dos. h> int setfileattr (path, unsigned attr, char *path; attr) ; 属性を取得するファイル名 属性へのポインタ 通常のファイル 意味 アーカイプ属性 サプティレクトリ ボリューム旧 システム属性 隠し属性 書き込み不可属性 戻り値 —A—NORMAL —A—RDONLY —A—HIIDDEN —A—SYSTEM —A—VOLI D —A—SUBD 旧 —A—ARCH List 6 FA—RDONLY FA—HIDDEN FA—SYSTEM FA—LABEL FA—D 旧 EC FA—ARCH 属性を設定するファイル名 設定する属性 戻り値 List 0 : 正常終了 ー 1 : 工ラー 属性表示 (dspatr. c) ファイル名 : dspatr. c 属性表示サンフ・ル・フ・ロク・ラム 0 : 正常終了 ー 1 : 工ラー #define _A_ARCH 36 : 37 : 38 : 39 : 40 : 42 : 43 : 44 : 45 : 46 : 47 : 49 : 50 : 52 : 53 : 54 : 55 : 56 : 58 : 59 : 60 : 62 : 63 : 64 : 65 : 66 : 68 : 69 : 70 : FA_ し ABE し FA_DIREC PA_ARCH 3 : 5 : 6 : 8 : 16 : 22 : 23 : 24 : 25 : 30 : 35 : int getfi leattr(char *,unsigned * ) : 7 : 使用法 : dspatr くファイル 1 〉 [.. 9 : [ 表示属性 ] 13 : コンハ・イル・スイッチ 1 5 : MS-C 5. 1 20 : Turbo C 2. 0 くファイル n > ] . テ・イレクトリ属性 隠し属性 書込不可属性 ホ・リューム・ラへ・ル Sma Ⅱ Model S a . システム属性 . 保存属性 41 : #endif int main(int,char * * ) : int main( argc,veargv ) int argc; char *argv ロ : uns igned attr; if ( argc く = fprintf ( stderr, return( 1 ) : while ( * + 十 argv ) { usage ・ dspatr くファイル 1 > [. くファイル n > ] \ n " ) : 17 : 引 /J /W3 /ZdI dspatr. c XMSCXYI ibYsetargv. 0bj / link s libcr + libh/st : 0X2800 / cp : 0X1000 / noe Sma Ⅱ Model getfi leattr が必要 tcc -w dspatr. c XTC%YlibYwildargs. obJ / * ファイル属性の取得 * / if ( _dos_getfi leattr( *argv, return( 1 ) : &attr ) ) { fprintf( stderr, " ファイル Xs の属性が取得できません。 yn", 28 : #include く stdio. h 〉 29 : #include く dos. h> 31 : #ifdef 32 : #define 33 : #define _A_RDON し Y 34 : #define _A_HIDDEN #define 0 printf ( " % ー 20S XcXcXcXcXcXcYn" attr & _A_SUBDIR ? attr & _A_VO い D attr & _A_SYSTEM attr & _A_RDON し Y attr & A_HIDDEN ? _TURBOC_ dos-getfil eattr A_SYSTEM getfileattr FA_RDON し Y FA_HIDDEN FA_SYSTEM return ( *argv ) : 新 MS—DOS プログラミング入門 *argv, 93
プログラマのための List 7 属性変更 (chgatr. c) List attr & ー ( -A-VO い D ー -A-SUBDIR ) ) ) { / * ファイル属性の設定 * / fprintf ( stderr, ”ファイル Xs の属性が変更できません。 Yn ” , *argv ) : return( 1 ) : 79 : 82 : 85 : 86 : 88 : 89 : VOid getargs ( argc, argv ) 90 : int argc; 91 : char *argv[]; while ( --argc ) { 93 : 94 : register char *p; 95 : if ( ( p = * + + argv ) [ 0 ] 96 : while ( * + + p ! = swi tch( tolower ( *p ) 98 : 99 : if ( p[l] = 100 : 101 : _A_ARCH,• set_atr 102 : p 十十 : } else if ( p[l] = 103 : 104 : res_atr 105 : p 十十 : 106 : 107 : break : 108 : if ( 矼 1 ] ー 109 : 1 10 : set_atr p 十十 : } else if ( p[l] = 1 12 : 113 : res_atr 114 : p 十十 : 115 : 116 : break : 117 : 118 : if ( p[l] ー 119 : set_atr 120 : p 十十 : } 引 se i f ( 121 : 122 : res_atr 123 : p 十十 : 124 : break : 125 : case 'r' 126 : if ( p[l] = 127 : 128 : set_atr 129 : p 十十 : } else if ( p[l] = 130 : 131 : res_atr 132 : p 十十 : 133 : 134 : break : 135 : default ・ usage ( ) : 136 : 137 : 138 : 139 : 140 : 141 : } 142 : 143 : void usage() 144. 145 : static char *msg[] " 使用法 : chgatr トく属性士 > ] くファイル 1 〉 [.. 146 : 書込不可属性 h ... 隠し属性 147 : S r " a ... 保存属性 + ... 属性ヒ・ツト 0N 148 : 149 : 150 : 151 : reg ister char **pmsg 152 : while ( **pmsg ) 153 : printf( *pmsg + 十 ) : 154 : exit( 1 ) : 155 : 156 : } 1 : 属性変更サンフ・ル・フ・ロク・ラム 3 : ファイル名 : chgatr. c 5 : 6 : 7 : 使用法 : chgatr トく属性土〉 ] くファイル 1 > [.. くファイル n > ] 8 : ( d, v は無効 ) 9 : [ 属性指定子の詳細 ] 10 : . システム属性 h . . 隠し属性 r . 書込不可属性 S . テ・イレクトリ属性 a . 保存属性 ホ・リューム・ラへ・ル 12 : V 属性ヒ・ツト OFP 属性ヒ・ツト 0N 14 : 15 : 使用例 : chgatr -s 十 h 十 r 十 a- file. ext システム属性 . 隠し属性 , 書込不可属性をセットし、 保存属性をリセットします。 19 : コンハ・イル・スイッチ 20 : Sma Ⅱ Model 21 : MS-C 5. 1 22 : 23 : /J /W3 /Zdl chgatr. c XMSCXYIibYsetargv. 0bj /link slibcr + ⅱbh/St:0X2800/CP:0X1000/n0e 24 : 25 : 26 : Turbo C 2.0 Sma Ⅱ Model 27 : が必要 * * * * * setfileattr 28 : * * * * * getfil eattr 29 : 30 : tcc -w chgatr. c XTCXYlibYwildargs. Obj 32 : * / 33 : 34 : #include く stdio. h> 35 : #include く ctype. h> 36 : #include く process. h> 37 : #include く dos. h> 38 : 39 : # ifdef _TURBOC_ 40 : #define getfileattr dos-getfil eattr 41 : #define setfileattr dos_setfileattr 42 : #define _A_RDON し Y FA_RDON し Y 43 : #define _A_HIDDEN FA_HI DDEN 44 : #define _A_SYSTEM FA_SYSTEM 45 : #define _A_VO い D FA_ し ABEL 46 : #define A_SUBDIR FA_DIREC 47 : #define A_ARCH FA_ARCH 49 : int getfileattr(char *,unsigned * ) , setfi leattr(char *,unsigned) : 50 : #endif 52 : int main(int,char * * ) : VOid getargs(int,char * * ) , usage(void) : 53 : 54 : 55 : unsigned set-atr = 0 , 56 : res_atr = 0 : 58 : int main( argc, argv 59 : int argc; 60 : char *argv[] : 62 : uns igned attr: if ( argc く = 1 ) usage() : 65 : getargs( argc, argv ) : 66 : while ( * + + argv ) { 67 : if ( **argv 68 : / * オフ・ション・スイッチ continue; / * ファイル属性の取得 * / if ( -dos_getfileattr( *argv, &attr ) ) { fprintf ( stderr, Xs の属性が取得できません。 Yn ” ”ファイル *argv return( 1 ) : 75 : attr ト set_atr; 76 : attr & : res atr; if ( _dos_setfileattr( *argv, return( 0 ) : / * 引数の取得 カ′ル′ 了 定定ッ 指指チ 性存 属保 / * システム・ファイル A SYSTEM : A_SYSTEM : / * 隠しファイル _A_HIDDEN : A_HIDDEN; / * 読出専用ファイル A_RDONLY : A_RDONLY : / * セット属性 / * リセット属性 / * 引数の取得 くファイル n 〉 ] \ n \ n ” . システム属性 \ n ” 属性ヒ・ツト 0FFYn", msg: / * セット属性 / * リセット属性 1991 2 94 CMAGAZINE
List 1 システム属性 ホ・リュームラ / ヾノレ ・ディレクトリ属性 a ・ ・・保存属性 List 6 て、注意する点は , C コンパイラのラ イプラリてコマンドラインのワイルドカー ドを展開すると , 隠し属性やシステム属性 などがついているファイルは展開されない ということてす。つまりワイルドカードを 使用せずにファイルを指定する必要があり ます。 これを避けるにはプログラムてワイルド カードを展開すればよいのてすが , この件 については別の機会に説明します。 CHGATR の使用法は CHGATR [ ーく属性士 > ] くファイル 1 > [ ・・・くファイル n > ] て、 , 属性指定子の詳細は以下のようになっ ています。 ・書き込み不可属性 r ・・隠し属性 ・システム属性 ・・保存属性 ・属性ビット ON ・属性ビット OFF file. ext にシステム属性 , 隠し属性 , 書き込 み不可属性をセットし , 保存属性をリセッ トするには CHGATR ー s 十 h 十「十 a ー file. ext となります。 List 7 て注意する点は , DOS ファンクショ ン 43h てはサプディレクトリとポリューム ID の属性がセットされているとエラーになる ということてす。したがってサプディレク トリの属性を変更する場合てもサプディレ クトリ属性を落とした属性を設定する必要 があります。 蛇足てすが , EXE, COM の実行ファイル や IO. SYS, MSDOS. SYS のシステムファイ ルなどをリードオンリ属性に設定しておく と簡単なウイルス対策になるかもしれませ ん。 ( stime. hour くく 11 ) ー ( stime. minute くく 5 ) ー ( stime. second / 2 ) : uti me 72 : #endif while ( * + + argv ) { 74 : # i fdef _TURBOC_ if ( setfiletime( *argv, &ftime ) ) { 76 : #else 77 : if ( setfiletime( *argv, udate, utime ) ) { 78 : #endif / * ファイルの日付と時刻の設定 fprintf ( stderr, " ファイル Xs が見つかりません。 %n" return( 1 ) : 84 : *argv ) : return( 0 ) : TOUCH コマンド (touch2. c) List 1 : TOUCH コマント・サンフ・ル・フ・ロク・ラム 3 : ファイル名 : touch2. c 5 : 6 : 使用法 : touch2 くファイル 1 > [.. 7 : くファイル n > ] 8 : 9 : コンハ・イル・スイッチ 1 1 : MS-C 5. 1 Small Model 13 : cl /J /W3 /Zdl touch2. c %MSC%YlibYsetargv ・ obj /link slibcr + ⅱbh/St:0X2800/CP:0X1000/n0e 16 : T urbo C 2.0 Small Model 18 : tcc -w touch2. c %TC%YI ibYwildargs. obj 20 : * / 22 : #include く stdio. h> 23 : 24 : int main( int, char * * ) ; 25 : 26 : int main( argc, argv ) 27 : int argc; 28 : char *argv[] : 29 : { if ( argc く = 1 ) { 30 : fprintf( stderr, 32 : return( 1 ) ; 33 : 34 : while ( * + + argv ) { 35 : FI し E *fp; 36 : i nt c h : if ( ( fp ー = NU しし ) { 38 : fopen ( *argv, 39 : / * ファイルの日付と時刻の設定 * / 40 : fprintf ( stderr, " ファイル %s が見つかりません。 Yn" *argv ) : return( 1 ) : 42 : ch = fgetc( fp ) : / * ファイルの先頭を 1 ハ・仆読み込んで * / 44 : rewind( fp ) : / * ファイルの先頭に戻して fputc ( ch, fp ) : / * 読み込んだ 1 ハ・仆を書込む 46 : fclose( fp ) : return( 0 ) : 48 : くファイル n 〉 ] \ n " ) : : touch2 くファイル 1 〉 usage 1991 2 88 CMAGAZINE
おわりに C 言語のライプラリてサポートしている DOS ファンクションを呼び出す関数に互換性が ないため掲載したリストが多少見にくくな ってしまいました 0MS-C が Ver. 3 からサポ ートしていれば TurboC もあわせたのてし ようが , Ver. 5 からのサポートて、すから互 換性のないのも仕方がないのて、しよう。 DOS ファンクションを呼び出す関数に互 換性がないことを考慮すれば新たに作成し たほうがよかったかもしれませんが , 今回 は条件コンパイルにより複数のコンパイラ に対応する方法をとりました。これらの関 数をサポートしていないコンパイラて、も intdos 関数に相当する関数はサポートしているは ずてすから , その関数を用いれば DOS ファ ンクションを直接呼び出すことがて、きます。 本文てもいくつか示している例を参考にし て作成してください。これらの例は MASM て、記述することもてきますが ,MASM< 記 述する例は別の機会に紹介します。 今回はふたつの項目について考察しまし た。いずれも MS ー DOS の機能を利用した簡 単なプログラミングをその機能の裏側をの ぞきながら ( 筆者の推測も入っていますから まちがっているかもしれませんが ) 説明しま した。どのような印象をもたれたて、しよう か ? 少々しつこい印象をもたれたかもし れません。しかし , MS ー DOS に限らず何事 も一度は , とことん追及する姿勢はたいせ ってす。別の分野て、も応用力となって現れ てくるはずてす。といっても MS-DOS を追 及しても仕方がないてすから , 仕事の背景 を考えながら仕事をすると上達が速くなる かもしれませんよ。 ( 参考文献 ) 1. 中島信行 , 「 MS-DOS のディスク管理とフ ァイル復活ユーティリティ」 , 『インタフェ イス』 1990 年 5 月号 90 CMAGAZINE 1991 2 76 : 82 : 84 : 85 : 86 : 87 : TabIe 5 引数 戻り値 機能 List 3 81 : #endif 77 : #else 73 : #ifdef name ) : fprintf ( stderr, " ファイル %s の日付変更に失敗しました。 \ 心 , / * ファイルの日付を 1980. 1. 1 にセット * / setfiletime( objname, 0X21 , 0 ) ) ) { = NU ししⅡ & & ( pobjtouch = if ( setfiletime( name, 0X21 , 0 ) setfiletime( objname, &ftime ) ) ) { & & ( pobjtouch = = NULL Ⅱ if ( setfiletime( name, &ftime ) TURBOC_ name ) : ret ファイル属性の取得 / 設定 return( ret ) : = ファイル属性 ( AL = 01h の場合 ) = 01 h : ファイル属性の設定 = 00h : ファイル属性の取得 DS : DX = ASC にノヾス名のアドレス AH = 43h DOS ファンクション 43h ファイル属性の取得 / 設定 CX AL AL キャリー キャリー INT 21h CX = ファイル属性 ( AL = 00h の場合 ) = 05h : アクセスの拒否 = 03h : 無効なパス = 02h : ファイルか存在しない AX = 01 h : 無効なファンクション 1 ションでボリュー D ピット ( 08h ) およびサプティレクトリピット ( 10h ) を変更するこ DS : DX レジスタで指定されたファイルの属性の取得または設定を行う。このファンク とはできない TabIe 6 —dos—getfileattr 関数 (MS-C 5.1 ) ファイル属性の取得 unsigned —dos—getfileattr(path, attr) ; # include く dos. h> cha 「 *path; unsigned * a 「 ; 属性定数 —A—NORMAL 属性を取得するファイル名 属性へのポインタ 意味 通常のファイル 書き込み不可属性 隠し属性 システム属性 ボリューム サプティレクトリ アーカイプ属性 = 0 : 正常終了 = 0 : 工ラー ( MS ー DOS のエラーコード ) —A—ARCH —A—SUBD 旧 —A—VOLI D —A—SYSTEM —A—HIDDEN —A—RDONLY 戻り値
Fig. 2 0 : 00 12 : 53 12 : 55 12 : 55 12 : 55 12 : 59 13 : 圓 13 : 00 13 : 00 12 : 54 12 : 55 12 : 55 12 : 55 12 : 53 wh--d- 隠しティレクトリの効果 DNTEST>dir \ ドライプ D: のディスクのポリュームラベルは M B し -DISK ディレクトリは D:y COMMAND COM 24931 89 ー 1 1 ー 27 LSIC86 CFG 111 90 ー 07 ー 15 TEST 90 ー 07 ー 15 く田 R > 3 個のファイルがあります . 6113280 バイトが使用可能です . DNTEST>chgatr -h + Ytest D:YTEST>dspatr Ytest Ytest D: YTEST>cd Y D:Y>dir \ ドライプ D: のディスクのポリュームラベルは M E L -DISK ドライプ D: のディスクのポリュームラベルは M E し -DISK D:y 〉 dir test 6113280 バイトが使用可能です . 2 個のファイルがあります . 111 90 ー 07 ー 15 LS I C86 C FG COMMAND COM 24931 89 ー 11 ー 27 ディレクトリは D:Y 0 : 00 12 : 53 ←テ・イレクトリ TEST は見えない ←隠しテ・イレクトリでも中身は見える ←通常の属性 ←隠し属性を設定 ←隠し属性が設定されている ディレクトリは DNTEST CHGATR CHGATR CHGATR CHGATR DSPATR DSPATR DSPATR DSPATR C EXE MAP OBJ C EXE MAP OBJ く田 R 〉 く田 R > 653 1946 9025 1815 1365 2606 9653 4480 。 90 ー 07 ー 15 90 ー 07 ー 15 90 ー 07 ー 15 90 ー 07 ー 15 90 ー 07 ー 15 90 ー 07 ー 15 90 ー 07 ー 15 90 ー 07 ー 15 90 ー 07 ー 15 90 ー 07 ー 15 10 個のファイルがあります . 6113280 バイトが使用可能です . DN>cd test D: YTEST>dir \ ←隠しテ・イレクトリでも移れる ドライプ D: のディスクのポリュームラベルは M E L -DISK ディレクトリは D:y COMMAND COM 24931 89 ー 1 1 ー 27 し SIC86 CFG 111 90 ー 07 ー 15 2 個のファイルがあります . 6113280 バイトが使用可能です . ファイル属性の取得 ( ge 廿ⅱ ea. c ) D:YTEST 〉 0 : 00 LiSt List ファイル属性の設定 ( setf ⅱ ea. c ) #include く dos. h> int getfileattr(char * int getfileattr( path, 6 : char path[]; uns igned *attr; union REGS iregs: 9 : 7 : 5 : 4 : 3 : 2 : 1 : , unsigned attr ) ファイル名 * / 2 : 3 : 4 : 5 : 7 : 9 : 1 : #include く dos. h> int setfileattr(char * , unsigned) : int setfileattr( path, 6 : char path[]; unsigned attr; union REGS 'iregs; attr ) / * 属性を取得する / * 属性へのホ・インタ ( unsigned )path; iregs. X. dX iregs. x. ax = 0X4300 : intdos( &iregs. &iregs ) : if ( iregs. x. cflag ) return ( iregs. X. cx; *attr return( 0 ) : / 事 ds:dx ハ・ス名の位置 / * ファイル属性の取得 / * ファイル属性 ( unsigned )path; dx = 0X4301 : cx ニ attr; intdos( &iregs. &iregs ) : iregs. x. cflag ? ー 1 return ( lregs. X. lregs. X. ax lregs. X. / * 属性を設定するファイル名 * / / * 設定する属性 / * ファイル属性 / * ファイル属性の設定 ハ・ス名の位置 / * ds:dx 92 CMAGAZINE 1991 2
C フログラマのための TOUCH コマンド (touch. c) LiSt するとカレントディレクトリに指定ファイ ルがない場合 , 指定したディレクトリを検 索します。たとえば set OBJTOUCH=A:%OBJD 旧 または set OBJTOUCH=A:%OBJD 旧 \ のように設定すると , カレントディレクト リの次にディレクトリ A:YOBJDIR を検索し ます (OBJTOUCH て、指定するディレクトリ は漢字のディレクトリ名に対応していませ TOUCH コマンドは現在の時刻に書き換え ますが ,OBJTOUCH ューティリティは 1980 年 1 月 1 日 0 時 0 分 0 秒に書き換えます。 ファイル属性の 取得 / 設定 DOS コマンドて、は ATTRIB コマンドて、リ ードオンリ属性とアーカイプ属性を変更す ることがてきますが , そのほかの属性は変 更てきません。しかし , DOS ファンクショ ン 43h(TabIe 5 ) を使えば隠し属性とシステ ム属性も変更てきるようになります。 MS-C 5.1 て、は属性の取得と設定を行う dos getfileatt 「関数 (Table 6 ) dos setfileattr 関数 (Table 7 ) の関数が用意されていますが TurboC 2.0 にはないようて、す ( 筆者の見落としかもしれ ませんが ) 。そこて getfileatt 「関数 (Table 8 , List 4 ) setfileattr 関数 (Table 9 , List 5 ) のふたつの関数を作成してみました。 これらの関数を使用してファイルの属性 を表示するサンプルプログラムを List 6 (dspatr. c) に , また , ファイルの属性を変更 するサンプルプログラムを List 7(chgatr. c) に示します。 DSPATR の使用法は DSPATR くファイル 1 > [ ... くファイル n > ] て , 表示属性は以下のようになっています。 ・書き込み不可属性 ・・隠し属性 1 : TOUCH コマント・サンフ・ル・フ・ロク・ラム 3 : ファイル名 : touch. c 5 : 6 : 使用法 : touch くファイル 1 > [.. くファイル n > ] 7 : 8 : 9 : setfiletime 関数が必要 * * * * * 11 : コンハ・イル・スイッチ 13 : MS-C 5. 1 Sma 1 1 Model 14 : 15 : cl /J /W3 /Zdl touch. c XMSCXYlibYsetargv. 0bj / 1 ink sl ibcr + libh/st: 0X2800 / cp : 0X1000 / noe 18 : Turbo C 2.0 Small Model 20 : tcc -w touch. c %TC%YI ibYwildargs. obj 22 : * / 23 : 24 : #include く stdio. h> 25 : #include く dos. h> 26 : 27 : int main( int, char 28 : #ifdef TURBOC_ 29 : #include く io. h 〉 30 : 31 : #define dosdate_t date 32 : #define dostime_t t i me 33 : #def ine _dos_getdate getdate 34 : #define _dos-gettime gettime 35 : 36 : int setfiletime(char *,struct ftime * ) : 37 : #else int setfiletime(char *,unsigned. unsigned); 38 : 39 : #endif 40 : int main( argc, argv 41 : 42 : int argc; 43 : char *argv[]; 44 : { struct dosdate_t sdate; 46 : struct dostime_t St i me : 47 : #ifdef _TURBOC_ struct ftime ftime; 49 : #e I se 50 : uns igned udate ; uns igned utime; 52 : #endif 53 : if ( argc ← 1 ) { 54 : fprintf( stderr, return( 1 ) : 56 : -dos-getdate( &sdate ) : -dos-gettime( &stime ) : 60 : #ifdef __TURBOC_ ft i me. ft_year = sdate. da_year ft i me. ft_month = sdate. da_mon : 63 : ft i me. ft_day = sdate. da_day; ft i 田 e. ft_hour stime. ti_hour; ftime. ft_min St i me. t i m ー n : ftime. ft-tsec = stime. ti-sec / 2 : 67 : #else ( ( sdate. year - 1980 ) くく 9 ( sdate. month くく 5 ) \ udate sdate. day; 0 / * 現在の日付 / * 現在の時刻 / * 更新日付 / 時刻 / * 更新日付 / * 更新時刻 . touch くファイル 1 > [.. くファイル n > ] \ n usage - 1980 : 新 MS ー DOS プログラミング入門 87
29 : } : List 5 GRAPHOBJ. HPP 抽象べースクラス 2 : 3 : 4 : 5 : 6 : 7 : 8 : 12 : 13 : 22 : 23 : 24 : 25 : 26 : 28 : 1 : / * メソッドはすべて純粋 v i rtual 関数として宣言する。 COLOR へのリファレンスを加える ことを考えたが , Po I ygon と C i r c 厄には共に f i I l_co I or とⅱ ne_co 1 or (s) があるので , それはやめた。このクラスの子孫に関する一般的な規則は : “可視の " オプジェクトの座標をセットしようとすると , 黙って無視される ・コンストラクタ " と operator= ( ) メソッドは常に定義しなければならない “コピ それらの主な目的は , 特定のオプジェクトが明示的に draw ( ) されるまでは , v i s i b le 属性を常に確実に FA し SE にセットするためである 9 : #if !defined(GRAPHOBJ_HPP) 10 : #define GRAPHOBJ_HPP 11 : #include く graphics. h> #include "point. hpp ” 14 : / / 子孫のクラスは DEF AULT を使って , 15 : #define DEFAULT 17 : class Graphics-Object デフォルトのパラメ ータを使用するようにする pub ⅱ c : virtual virtual virtual virtual virtual protected : B00 1 30 : #endif 20 : / / 最後に " = 0 : " と書かれたメソッドは純粋関数である VO i d VO i d VO i d VO i d Bool v i s i b 1 e : draw(void) erase (void) move reIative(Point &distance) { ret urn v i s i b I e : } : is-visible(void) move-absolute(Point &new location, Point &reference) DOT. HPP Dot クラス List 6 2 : #define DOT_HPP 1 : #if !defined(DOT HPP) 3 : 4 : 5 : 6 : 8 : 9 : 12 : 13 : 14 : 15 : 16 : 20 : 22 : 23 : 24 : 25 : 26 : 29 : 30 : 31 : 32 : # i nc 1 ude class Dot pub ⅱ c : Dot(const DOt *source) : { copy(source) ; Dot(const DOt &source) D0t(void) : コンストラクタとデストラクタ virtual public Graphics Object #include "point. hpp" graphobj. hpp" CO し ORS init_color = (COLORS) DEFAU し T) : Dot(const POint &init_location, { i f (v i s i b I e ) eras e ( ) D0t(void) 18 : / / 属性を取得するメソッド v i r tua 1 PO i nt V i rtua 1 i nt v i r tua 1 i nt &get-location(void) { return location; } : get-x (void) { return location. get get-y (void) { return location. get virtual CO し ORS get-color(void) { return CO 地心 } : 27 : / / 属性を設定するメソッド 28 : / / オプジェクトが可視のときにその位置を変えようとすると黙って無視される virtual void v i r tua 1 v 0 i d set_location(const POint &new-location) { if (!visible) location new_location,• } : set-x (const int new-x) { if (!visible) location. set_x(new_x); 0 車にはエンジンが 1 基あるが , しかし , だ からといって車はエンジン ( の派生クラス ) て、はない。車はむしろ , 工ンジンのサービ スて、ある Line , P01ygon, Arc や , またその 同類て、ある Point クラスのサービスを使う側 だ。 Dot と Point を見比べただけて、は区別が やや難しくても , そのほかのクラスと , そ れらの P0int クラスとの関係を見れば , P0int は座標を生成するためのエンジンだという ことがわかる。 List 6 と List 7 からわかるように , このク ラスは単純明快だ。 List 6 て、は , メソッドの ほとんどがインラインて、実装されている。 類とか幅という属性が加わっており , それ Line クラスも , とてもシンプルだ。線の種 線 (Line) について るようなものばかりだ。 いのだ。そのほかは , コードを見ればわか よる初期化時には FALSE て、なければならな しかし , D0t の visible は , コヒ。ー ( 代入 ) に 能は単純なビットコヒ。ーて、あるため ) 。 まう ( 訳注 : デフォルトの代入演算子 = の機 な D0t の visible 属性を TRUE にセットしてし ソッドは , ソースの D0t が可視だったら新た る。コンパイラが提供する ope 「 at0 「 = ( ) メ とを確実化するために明示的に定義してい れないかぎり可視にはならない 提供するが , オプジェクトは描画を指定さ C 十十は自動的に operator = ( ) メソッドを わせて複雑なアクションを構成すること ) は る。それ ( シンプルなメソッドを複数組み合 はよりシンプルなメソッドを利用して書け ら長くて複雑になるルーチンて、も , OOP< たけど , て、もそういうのは例外だ。普通な いし 15 行を超えるメソッドもいくつか作っ の特徴は , メソッドが短いことだ。 10 行な もそれがすべてだ。オプジェクト指向設計 らを操作するためのメソッドもあるが , て、 ゆとりのグラフィックス 29
List 67 : 60 : 59 : 58 : 55 : 54 : 53 : 50 : 49 : 47 : 46 : 45 : 44 : 42 : 41 : 40 : 39 : 36 : 35 : 33 : 32 : 30 : 28 : 26 : 24 : 22 : 14 : 12 : 8 : 7 : 6 : 5 : 3 : 1 : 逆 TOUCH コマンド (objtouch. c) ファイル日付を 1980. 01.01 に設定 ファイル名 : objtouch. c 使用法 : objtouch くファイル 1 〉 [.. くファイル n > ] 9 : くファイル名 > は複数指定可能で、拡張子を省略した場合 . obj とします。 10 : 環境変数 OBJTOUCH にオフ・シ・エクトを格納しているテ・イレクトリをセットしてく (OBJTOUCH で指定するテ・イレクトリは漢字のテ・イレクトリ名に対応していません ) * * * * * setfi letime 関数が必要 * * * * * 16 : コンハ・イル・スイッチ 18 : MS-C 5. 1 Sma Ⅱ Model C プログラマのための 第 韋 に ロ 20 : /J /W3 / 2d1 objtouch. c %MSCXYIibYsetargv. obj /link slibcr + ⅱbh/St:0X2800/CP:0X1000/n0e 25 : tcc -w objtouch. c %TC%YI ib%wi ldargs. Obj Sma Ⅱ MOdel 23 : Turbo C 2. 0 / * 環境変数 OBJTOUCH * / int setfi letime(char * , unsigned, unsigned) ; 27 : * / 29 : #include く stdio. h> #include く string. h> 31 : #include く stdlib. h> #include く dos. h 〉 34 : #define PATH し EN int main(int,char * * ) : register int ret char *argv ロ : int argc; int main( argc, argv 43 : #endif #else int setfiletime(char *,struct ftime * ) : 38 : #include く io. h > _TURBOC_ 37 : #ifdef ハ・ス名の長さ register char *pobjtouch 52 : #ifdef __TURBOC_ struct ftime ftime; getenv ( "OBJTOUCH ” ) : * ( long * )&ftime = 0X00210000 し : 56 : #endif if ( argc く = / * 1980. 01. 01 fprintf( stderr, : objtouch くファイル 1 〉 [.. くファイル n > ] \ n " ) : usage return( 1 ) : while ( --argc ) { char name[ PATHLEN ] , objname[ PATH し EN ] : strcpy( name, * 十十 argv ) : if ( strchr ( name, ニ NU しし ) / * テ・フォルト拡張子セット strcat ( name, if ( pobjtouch ! ニ NU しし ) { / * 環境変数 OBJTOUCH Ⅱ pobjtouch [ str len ( pobjtouch ) ( pobjtouch[ strlen( pobjtouch ) "XsXsXs", pobjtouch, sprintf( objname, 定義 新 MS ー DOS プログラミンク入門 MS-DOS の ティレクトリは ? 動もてきます。何か不思議な感じがしませ の内容を見ることがてき , CD コマンドて、移 いますが , DIR コマンドてディレクトリ TEST はディレクトリ TEST に隠し属性を設定して みましよう。 Fig. 2 を見てください。 Fig. 2 List 7(chgatr. c) を使ってちょっと遊んて 効果 隠しティレクトリの ては参考文献 1. を参照してください を大きく超えてしまいますのて詳細につい Fig. 1 の詳しい説明は今回のテーマの範囲 1 参照 ) 。 込まれているわけてす ( ' 91 年 1 月号 88 頁 TabIe トリエントリが 32 バイトを一組にして書き すなわちサプディレクトリには , ディレク ます。これがサプディレクトリの実体てす。 のふたつのディレクトリがあるのがわかり ( 親ディレクトリ ) ( 自分自身のディレクトリ ) の部分を見れば先頭に見なれた 内容をダンプしています。アスキーダンプ ことにより , 強制的にファイルとしてその サプディレクトリ TEST の属性を書き換える はディスクをアプソリュートに読み書きし , こて、ちょっと遊んて、みましよう。 Fig. 1 ます。 スクを直接読み書きすれば強引に変更て、き ァンクションて、変更て、きないだけて , ディ しかし , 変更てきないといっても DOS フ ないわけて、す。 前述のサプディレクトリの属性が変更て、き て、きません。このあたりに違いがあるため ープンてきますがディレクトリはオープン どういうことかというと , ファイルはオ は特別な扱いをされています。 て、はファイルと同じように感じますが , 実 MS-DOS のディレクトリは操作するうえ 新 MS ー DOS プログラミング入門 89
箱 語具 応の #include ” inputvar. h ” 0 List 1 120 : 121 : 122 : 123 : 124 : 125 : 126 : 127 : 128 : 129 : 130 : 131 : 132 : 133 : 134 : 135 : 136 : 137 : 138 : 139 : 140 : 141 : 142 : 143 : 144 : 145 : 146 : 147 : 148 : } tW ice usuperi2(xx, yy, var, len, CO し attr, prcol, prattr, key, outkey, stype) [ 引数 ] if( (stype & MUST) ) { strcpy(dummys, rmoji) : spctoru (dummys) : if(strlen (dummys)) { breakno else{ breakno int XX,• int yy; Char * va 「 ; intlen ・ char CO い char attr ・ char prcol• char prattr ・ int key ; int outkey[ ] int stype ・ }while( breakno ) : uoutform (hmoj i , rmoj i, stype) : strcpy(clrmoji, rmoji) ; strlen(clrmoji); memset (c I rmoj i , uprintv(clrmoji, prattrib, xx, yy, の : uprintv(hmoji, prattrib, xx, yy, の : refresh() : if( ! (stype & NEVERIN) ) { strcpy(var, rmoji) : return ( の : xx, YY は入力位置を示す x 座標および Y 座 標て、ある。 var は , 入力値を代入する変数てある。ま た , あらかじめこの変数に値を入力してお くと , それがデフォルト値になる。 col および attr はそれぞれ入力時における 表示色および表示属性て、ある。 n には表示幅を指定する。 p 「 col および pratt 「はそれぞれ入力後の表 示色および表示属性てある。これらの指定 の仕方は , 以下のように pldwn. h て定義され ている定数を用いて行う。 #define BLACK 0 * 0X20 十 1 #define BLUE 1 * 0X20 十 1 #define RED 2 * 0X20 十 1 #define PURPLE 3 * 0X20 十 1 #define GREEN 4 * 0X20 十 1 #define SKY 5 * 0X20 十 1 #define YELLOW 6 * 0X20 十 1 #define WHITE 7 * OX 十 1 #define NONSEC 1 #define BLINK 2 #define REVERSE 4 #define UNDERLN 8 TESTI . C List 2 1 : #define EXTERN 2 : 3 : #include く stdio. h> 4 : #include く string. h> 5 : #include く ctype. h> 6 : #include く curses. h> 7 : 8 : #include "pldwn. h" 9 : #include "fkey. h" 10 : #include input. h" 11 : #include inputvar. h" 12 : 14 : VOid main() 16 : char moji [ 256 ] : 17 : i nt key 18 : int outkeYC10] initscr(); 20 : keypad(stdscr, TRUE) : G i n S 24 : 28 : 32 : 33 : 34 : 35 : 36 : 38 : } / * 挿入 / 上書きトグルスウィッチ * / strcpy(moji, " 0000000001 " ) : refresh() : outkey [ 0 ] CUP outkey[l] CDOWN outkey[2] CR outkey [ 3 ] / * 最後に項として 0 を設定 * / 0 usuperi2(10, 10 , moji, 20 , SKY, REVERSE, WHITE, NONSEC, key, outkey, MUST) : printf("Yn 入力した値は % s です \ n " , moji ) : keypad(stdscr, FALSE) : endwin(); ex i t ( 0 ) : 応用 C 言語 97
List 67 : 65 : 64 : 63 : 62 : 60 : 58 : 57 : 56 : 55 : 54 : 53 : 52 : 49 : 48 : 46 : 45 : 44 : 43 : 42 : 41 : 40 : 39 : 38 : 36 : 35 : 34 : 33 : 32 : 30 : 29 : 28 : 26 : 25 : 24 : 23 : 22 : 20 : 13 : 12 : 11 : 8 : 6 : 5 : 4 : 3 : 2 : DISPLAY. HPP 画面制御用のクラス インスタンスは 1 つだけを , グローバルに定義する。 Graph ics_D i sp 1 ay のオプジェク トを使うクラスは , "theD isp lay" という名でそれにアクセスする。このクラスは , 仮 1 含めなければならない (set-mode(), get-mode() , 想世界をサポートするための属性も提供する。 get-default_fi ll-pattern() , こでは省略した幾つかのメソッドも , set-default_fi ll-pattern() , など ) 9 : #if !defined(DISP し AY_HPP) 10 : #define DISP し AY_HPP #include く graphics. h> double round (double value) : class Graphics_Display public: Graphics-DispIay(char *path,const int world 16 : / / コンストラクタとデストラクタ 21 : / / 属性を取得するためのメソッド { c losegraph() Graphics-DispIay(void) ー S ー 2 e ニ 1000. 0 ) : int float float int int get-aspect-ratio(void) { return aspect_ratio get_virtual-size(void) { return virtual_size; get-max_x (void) { return max_x; } : get-max-y (void) { return max_y; } : get-driver(void) { return driver; } ; / / 次の 2 つのメソッドは , 仮想世界と実画面座標との間の変換に使う , / / スケーリング・ファクタを返す float float get-x-scale(void) { return x_scale; } : get-y-scale(void) { return y_scale; } : / / 属性を設定するためのメソッドー最初の 2 つのメソッドは / / G raph i cs-0bj ect を一つでも作った後は使ってはいけない set-default-fg-color(const CO し ORS new_color) { setbkcolor(new-color) : set-defau lt-bk_color(const COLORS new_color) set-virtual-size(const double size) : set-aspect_ratio(const double ratio) : VO i d VO i d VO i d VO i d / / 変換用メソット double double int int { return round( ((float)x / x_scale) * aspect_ratio) ・ x_to-virtual(int x) { setcolor(new_color) ・ { return (int) (round(y * y_ y_to-real (float y) { return (int) (round(x * x_ x to-real (float x) { return round( (float)y / y_scale) y_to-virtual (int y) scale)) ・ scale)); 70 : #endif private: int float float float float int int driver; aspect_ratio; V i r tua ー _S i ze : x_scale; y-scale; max_x; max_y; / / 使用するディスプレイドライバ 〃 g raph i c s. h に定義されている / / 上記の get-aspect-ratio() を見よ / / 仮想世界のサイズ / / default : 1000.0 x 10 圓 . 0 / / 上記の get-x-scale() と / / get-y-scale() を見よ / / 横方向の表示サイズ ( ピクセル数 ) 〃縦方向の表示サイズ ( ピクセル数 ) 制御するだけじゃなく , 仮想世界も管理す るのだ。 は ( この理解は , C 十十の記事を書いている がして , 悩んだ。ぼくが理解したところて、 ト」という言葉がゴッチャに使われている気 本の中て、「クラス」という言葉と「オプジェク C 十十の勉強を始めたころは , いろいろな さあ出発 一手に管理する , という目的は達せられる 妥当だったのか , 自信はない。仮想世界を ことに決めた。率直にいって , この決定が を Graphics Object というクラスの中て、やる なのて、 , 関連パラメータの管理と変換処理 変換のためには , 画面に関する情報が必要 仮想から現実 , そして現実から仮想への べつにばくの独創じゃあないけどね ) 。 るのは , 自動的に行われるのだ ( こんなの , この仮想座標を画面の実際の位置に変換す 動小数点数て、指定て、きる機能を付け加えた。 世界を定義て、き , この世界の座標位置を浮 た。それを実現するために , 長方形の仮想 理してくれる , 完全な世界がほしいと思っ コンヒ。ュータがそういう細部を自動的に処 のはアホらしい ということに気づいた スペクトレシオや画面サイズの判断をする り , 2 本の線をつなげようとするたびに , ア この企画の進行途中て、 , 矩形を定義した る ) 。 ェクト = すなわち int のインスタンスて、あ i ; などにおける変数 i が , int 型をしたオプジ ートしているクラス = データ型 , そして int ( 訳注 : int などは言語処理系が最初からサポ タ型のインスタンスて、あるのと同じなのさ 例 ) て、 , つまり変数というものが , あるデー クトは , クラスのインスタンス ( 実例 , 実現 ーザが定義したデータ型 ) 。一方 , オプジェ int なんかと同じくデータ型なんだ ( ただしュ Scott Ladd のお墨っきだけど ) , クラスは , ゆとりのグラフィックス 23