char - みる会図書館


検索対象: 月刊 C MAGAZINE 1990年5月号
43件見つかりました。

1. 月刊 C MAGAZINE 1990年5月号

今回は , まず , 標準ライプラリとして必 要て、あろうと思われる関数の一覧表 ( Tbl. 6 ) を発表します。 このほかにも , ランタイムルーチン用の 内部関数や , DOS とのインタフェイス関数 などが必要となります。また , 当然 , 日本 語処理用のライプラリも必要となりますし , グラフィックやマウスなどのハードウェア インタフェイス関連のライプラリも必要に なるてしよう。 PragmaC のライプラリの仕様に関して は , 読者の皆さんと協議しながら決定して いきたいと思っています。幸い , ライプラ long lseek (int fd, long offset, int base) char malloc (unsigned size) int mblen (const char * s, size t n) VOid memmove (ViOd, const VOid, Size t) void memcpy (void * sl , const viod * s2, size t n) int memcmp (const VOid *sl,char *s2,size t n) Char memchar (const VOid *S,char C,Size t n) int mbtowc (wchar t * pwc, const char * s, size t n) TbI. 7 Project P 「 agmaC の各種プログラムが対応する動作環境 対応予定 マシン 最小機器 構成 DOS NEC PC -98 シリーズ 富士通 FM - R50. R60 , R70 シリーズ 東芝 J ー 3100 シリーズ 日本旧 M PS / 55 シリーズ CPU = V30.8086 田田 86.80286 , 80386 メモリ 640K ノヾイト 2HD ( 相当 ) ドライプ X2 MS-DOS 3.1 以上 リの作成を開始するまて、には , まだ少々の 時間がありますのて、 , 本誌上において以下 の項目について討議したいと思います。 * ワイド文字関数 *ANSIßå連 *UNIX 関数 * DOS インタフェイス関数 * 日本語処理関数 * グラフィックライプラリ *CRT, キーポード , マウス関連 UNIX ANSI ANSI ANSI ANSI ANSI ANSI ANSI DOS ANSI ANSI ANSI UNIX DOS ANSI ANSI ANSI ANSI ANSI ANSI ANSI ANSI ANSI ANSI ANSI ANSI ANSI ANSI ANSI ANSI ANSI ANSI ANSI void srand (unsigned seed) ViOd memset (VOid * S, int C, Size t int mkdi 「 (cha 「 *pathname) time t mktime (struct tm) double modf (double value, double Size t offsetof (S name, m_name) onexit t onexit (onexit t func) int outp (unsigned po , int value) n) * iptr) int outpw (unsigned po 代 , unsigned value) void pe 「「 0 「 (char st 「 ing) double pow (double x,double ⅵ int p 「 intf (char * fo 「 mat , ・・・ ) int putc (char cc, FILE * stream) int putchar (char c) int puts (const char * string) VOid qsort (cha 「 * a 「「 ay, unsigned number, unsigned width, int( * cmpf)(const void * , const void * ) ) int raise (int sig) int rand (void) int read (int fd, char * buffer, unsigned count) char 「 e 訓 OC (unsigned cha 「 * 0 旧 p , unsigned size) int remove (char * pathname) int rename (cha 「 *from, cha 「 *tO) void rewind (FILE * stream) int 「 mdir (char * pathname) char sbrk (unsigned size) int scanf (char * format, VOid setbuf (FILE * stream, char * buf) int setjmp (jmp buf env) char * setlocale (int category, const char * locale) int setvbuf (FILE * stream, char * buf, int type, int size) void (signal(int sig,void(*func)(int)) )(int) double sqrt (double x) int sprintf (char * buf, char * format, double sinh (double x) double sin (double x) int sscanf (cha 「 * buffer, char * fO 「 mat , ・・・ ) cha 「 strcat (char * sl , const char * s2) unsigned char strch 「 (const cha 「 * s, int c) int strcmp (const char *sl,const char *S2) int st 「 COII (const cha 「 * sl , const cha 「 * s2) ANSI char strcpy (char *sl,const char *S2) size t strcspn (const char * string, const char * set) Char St 「 e 「「 0 「 (cinst Char * S) Size t strftime (char * S, size_t maxsize, const Char * format, const st 「 uct tm * timept 「 ) unsigned strlen (const cha 「 * s) cha 「 strncat (char *Sl,const cha 「 *S2,size t n) int strncmp (const cha 「 * Sl , const cha 「 * S2, size t n) char strncpy (char * sl , const char * s2, size t n) DOS unsigned char strpb 「 k (const char *SI, const cha 「 *S2) int vsprintf (char * buf, char * fO 「 mat, va list a 「 9 ) int vprintf (char * fO 「 mat, va list arg) int vfp 「 intf (FILE * stream, char * format, va list arg) void va start ()a list ap, param N) ANSI void va end ()a list ap) ANSI type va a 「 g ()a 」 ist ap, type) int ungetc (char c, FILE * stream) UNIX char toupper (char c) DOS char tolower (char c) char * tmpnam (char * s) FILE * tmpfile (void) time_t time (time t *timer) ANSI double tanh (double x) UNIX double tan (double x) int system(char * st 「 ing) int sysint (unsigned vec, struct regval * callreg, struct 「 egv 引 size t strxfrm (char * sl , const cha 「 * s2, size t n) unsigned long st 「 0ⅵ (cha 「 * nptr, char * * endpt 「 , int base) ANSI long strtol (char * nptr, cha 「 * * endpt 「 , int base) char strtOk (cha 「 *sl,const cha 「 *S2) double strtOd (cha 「 * nptr, char * * endptr) cha 「 strstr (const char * sl , const char * s2) size_t strspn (const char * string, const char * set) unsigned char strrchr (const char * S, int C) * ret 「 eg) size t wcstombs (char * S, const wchar t * pwcs, size t int wctomb (cha 「 * s, wchar t wchar) int write (unsigned fd, char * buffer, unsigned count) n) ANSI ANSI ANSI ANSI ANSI ANSI ANSI ANSI ANSI ANSI ANSI ANSI ANSI ANSI ANSI UNIX DOS ANSI ANSI ANSI ANSI ANSI ANSI ANSI ANSI ANSI ANSI ANSI ANSI ANSI ANSI ANSI ANSI ANSI ANSI ANSI ANSI ANSI ANSI UNIX ANSI ANSI

2. 月刊 C MAGAZINE 1990年5月号

について定義します (PragmaC VersionI . 0 コンパイラ / 言語仕様・規約書参照 ) 。 このコンパイラ / 言語仕様・規約は , C コ ンパイラというより , むしろ C 言語のソース ファイルを処理しなければならないプログ ラムにとって , 最低限必要となる規約て、す。 今回発表する CSP もこれらの規則をもとに 作成されていますまた , この規約さえ確 定していれば , プリプロセッサを作成する ことも可能になります。 今回の構文規約は非常に標準的なものて、 すのて、 , あまり問題はないと思いますが , もし , 異論が生じるとしたら次の 2 点につい TbI. 6 標準ライプラリ関数一覧 てて、はないて、しようか。 * 予約語における ANSI 規格からの逸脱 * ワイド文字定数 , ワイド文字列につ 本規約て、定義されている予約語のうち , near, far, huge, fortran, pascal につ いては , ANSI 規格て、は予約語として扱われ ていません。しかし , PragmaC がパーソナ ルコンピュータ上 ( MS ー DOS 上 ) て、稼動する 以上 , ほかの MS-DOS 用 C コンパイラとの互 換性を完全に捨てさるわけにはいきません のて予約語としてあります。 ワイド文字定数およびワイド文字列につ いては , その実態 ( 拡張文字セットの内容 ) が定義されていないため , 現状て、の利用価 値はほとんどないかもしれません。実際 , ANSI 準拠をうたう現行の MS-DOS 用 C コン パイラにおいても , ほとんどサポートされ ていない状況て、す。しかし , 将来的な面を 考えた場合 , 漢字を扱うもっともスムーズ な方法となることも考えられるため , 現段 階から規約として定義しました。次回はデ ータタイプおよび宣言について定義します。 ライプラリ編ロ ] void abort (void) int abs (int x) double acos (double x) void alloc (int size) char asctime (struct tm double asin (double x) VOid assert (expression) double atan (double x) * St 「 eam ) * stream) * St 「 eam) num, int width, ANSI ANSI ANSI UNIX ANSI ANSI ANSI ANSI ANSI ANSI ANSI ANSI ANSI DOS ANSI ANSI ANSI ANSI ANSI UNIX ANSI ANSI UNIX ANSI ANSI ANSI ANSI ANSI ANSI ANSI ANSI ANSI ANSI ANSI ANSI ANSI ANSI ANSI ANSI ANSI int fputc (cha 「 byte, FILE * stream) int fputs (char * string, FILE * stream) int fread (char * where, size t elsize, int nelem, FILE void free (unsigned char * pointe 「 ) FILE freopen (char * filename, cha 「 * fomode, FILE * timeptr) double atan2 (double y, double x) int atexit (void ( * func)) double atof (char * nptr) int atOi (char * npt 「 ) long atOl (char * nptr) int bdOS (int fcode. unsigned long dx ds) VOid bsearch (const void * key, const void * base, int int ( * comp)(const void * , const void VOid callOC (unsigned nelem, size t elsize) double ceil (double x) void clea 「 er 「 (FILE * stream) clock t clock (void) int close (int fd) double cos (double x) double cosh (double x) int creat (cha 「 * filename, unsigned pe 「 mit) char ctime (time t * time 「 ) double difftime (time t timel, time t time2) st 「 uct div t 、 div (int x, int ⅵ void exit (int status) double exp (double x) double fabs (double x) int fclose (FILE * stream) int feof (FILE * stream) int fe 「「 0 「 (FILE * st 「 eam) int fflush (FILE * stream) int fgetc (FILE * stream) int fgetpos (FILE * stream, fpos_t * pos) char fgets (cha 「 * buffer, int bufleng, FILE * stream) double floor (double x) double fmod (double x, double y) FILE fopen (char * filename, char *fomode) int fprintf (FILE * stream, char * format) 48 CMAGAZINE 19 5 double f 「 exp (double value, int * exp) int fscanf (FILE * stream, char * format , ・・・ ) long fseek (FILE * stream,long offset, int base) int fsetpos (FILE * stream, fpos t * pos) long 負 (FILE * stream) int fwrite (char * where, size t elsize, int nelem, int getc (FILE * stream) int getchar(void) unsigned char getenv (cha 「 * name) char gets (char * name) struct tm gmtime (time_t *time 「 ) int inp (unsigned po ) unsigned inpw (unsigned PO ) 日 LE int int86 (int vecno, union REGS * inregs, union REGS * outregs) int int86x (int vecno, union REGS *inregs, union REGS *outregs, union SREGS *segregs) int intdos (union REGS *inregs, union REGS *outregs) int intdosx* (union REGS *inregs, union REGS *out 「 egs, union SREGS * seg 「 egs) int isalnum (char c) int isalpha (char c) int iscntrl (char c) int isdigit (char c) int isgraph (cha 「 c) int 回 owe 「 (char c) int isprint (char c) int ispunct (char c) int isspace (char c) int isuppe 「 (char c) int isxdigit (char c) int longjmp (jmp buf * envp, int value) double IogIO (double x) double log (double x) struct tm localtime (time_t * time 「 ) struct lconv * localeconv (void) idiv t 旧ⅳ (long numerator, long denominato 「 ) double ldexp (double x, int exp) long labs (long x) ANSI ANSI ANSI ANSI ANSI ANSI ANSI ANSI ANSI ANSI ANSI ANSI ANSI ANSI ANSI ANSI DOS DOS ANSI ANSI ANSI ANSI ANSI ANSI ANSI ANSI ANSI ANSI ANSI ANSI ANSI ANSI ANSI ANSI ANSI ANSI ANSI DOS DOS DOS DOS

3. 月刊 C MAGAZINE 1990年5月号

const と volatile 6 ロ - 本ロ 0 五ロ 一三ロ 乗松保智 今回は const と v at ⅱ e について解説します。 const と v at ⅱ e は , ANSI 標準規格で導入されたキーワードで , volatile はと もかく , const は今後よく使われるようになると思います。 この機会に理解してしまいましよう。 頭にひとつだけ現れますが , 宣言子はカン C 言語の文法定義のうち , 宣言に関連する const と volatile マて、区切っていくつもつづけることがて、き 部分を抜き出したのが List1 て、す。このリス ます。 トは yacc の記述法に基づいていますが , 省 ところて、 , この宣言て、は P はポインタ型 , 略可能なことを表す記号として [ ] を使っ const と volatile は ANSI 標準規格によっ c は char 型のオプジェクトになることはご存 て導入されたキーワードて、す。宣言の中て、 ています。また , 簡単にするために多少省 こて、 * の位置に注目し じのとおりて、す。 略した部分や不正確な部分があります。 使い , オプジェクトの性質を決めます。 てほしいのて、すが , なぜ c は char 型なのて、し const は単語 constant の省略形て、す。 con 宣言は大きく宣言指定子と宣言子のふた ようか。 stant には「不変の」「定数」という意味があり つに分けることがて、きます。 char * p, c; ます。この意味からもわかるように , const char * p, c; と書くと , p も c も char へのポインタのよう の char が宣言指定子て、 , *P と c が宣言子て、 を使って宣言されたオプジェクトは , プロ にも見えますね。この書き方は許されてい グラムの実行中に書き換えることはて、きな す。宣言指定子はひとつの宣言について先 くなります。 言指定子と宣言子 volatile という単語には「揮発性の」「変わ りやすい」という意味があります。つまり , Char * 実行中に値がころころ変わるオプジェクト を宣言するときに使います。 これらのキーワードがもつ意味について は後ほど詳しく解説することにして , まず は const, volatile を使った宣言の文法につ いて説明しましよう。 宣言子 これが宣言指定子なら p も c も ポインタになる 言の構文 Char ↑ const, volatile は int, char のような型 指定子て、はなく , また static, extern のよ うな記憶指定子て、もありません。 const と volatile だけて、ひとつの構文要素になってい ます。 子 宣 は の一部 実際には宣言指定子は cha 「だけ 116 CMAGAZINE 1990 5

4. 月刊 C MAGAZINE 1990年5月号

五ロ 用 応 nxtype が漢字第 1 バイトのとき 第 2 バイトを格納するときに , そこが漢字 第 1 バイトの場合には , その次の文字 ( 第 2 バイト目 ) を空白て、クリアする (Fig. 5 ) 。 ③カーソル位置が漢字第 2 バイトで , 格納 する文字が漢字第 2 バイトでないとき カーソル位置が漢字第 2 バイトならば , そ の前の第 1 バイトも空白て、クリアする。 ただしすて、に格納した漢字第 1 バイトと は区別する必要があります ( Fig. 6 ) 。 ・文納と表示 現行ポインタ * curptr へ文字を格納しま す。格納文字が ANK か漢字第 2 バイトのと きだけ , 文字を表示します。 ・カーソルと現行ポインタの叫斤 カーソル X 座標 xposit と現行ポインタ cur ptr を更新します。 2 バイトコードて、も 1 バイ ト単位て、処理を行うのて , 2 バイト目を処理 するときには , 第 2 バイト目を格納すべき場 所を指しています。 カー男レ後退 —backward 関数ー カーソル位置がバッファ先頭てはない場 合には , カーソルと現行ポインタを 1 減じま す (List3)0 ただし , 減じた結果 , カーソル が漢字第 2 バイトになる場合には , もう 1 回 減じます。 List 7 21 : #define KHEAD4 22 : #define HANKJI 23 : #define HANKJ2 24 : #define HANKJ3 25 : #define HANKJ4 26 : #define CONSTI 27 : #define CONST2 28 : #define CONST3 29 : 30 : #define B し ANK 31 : #define FWD 32 : #define BACK 33 : #define INS 34 : #define DE し 35 : #def ine ESC 36 : #define CR 37 : #define bE しし 38 : #defiae HOME_CLR 39 : 40 : #def'ine ANK 4 i : #define KANJI 1 42 : #define KANJ12 43 : 44 : static Char 45 : static Char 46 : static Char 47 : static Char 48 : static int 49 : static i nt 50 : static int 51 : static int 52 : casel ( ) : 53 : VO i d case2() : 54 : VO i d case3() : 55 : V 0 ー d case4 ( ) : 56 : VO i d key-asgn(int mode) : 57 : VO i d get-key-str(int x, int y, char *buffer, 58 : i nt int mode) : int max, char-set(unsigned char *ichr) : 59 : VO i d backward() : 60 : VO i d forward ( ) : 61 : VO i d insert() ; 62 : VO d delete() : 63 : VO i d get-lchar(unsigned char *ichr) : 64 : i nt test_str(unsigned char *buf, unsigned 65 : int *testptr) : Char 66 : int get_strln(unsigned char *buf, int cnt) : 67 : cls(); V 0 i d 68 : clearl(int y); VO i d put-str(int x, int y,char *buf, int count) : 69 : VO i d 70 : V 0 i d csr-posit(int x, int y); put-chr(int x, int y, char chr) : 71 : V 0 i d 72 : buzzer() : V 0 i d 73 : csr_fwd() : V 0 i d csr-back() : 74 : VO i d color(char *attr, char *colorno) : 75 : VO i d 76 : 77 : / * main 78 : main() 79 : VO i d str[60], ichr[2]; Char 82 : int workno, X, y, cnt; 83 : key-asgn( の : 85 : 88 : 89 : 90 : 92 : / * 漢字第 1 バイト境界 ( 最終 ) * / / * 半角漢字第 2 バイト境界 ( 先頭 ) / * 半角漢字第 2 バイト境界 ( 最終 ) / * 半角漢字第 2 バイト境界 ( 先頭 ) / * 半角漢字第 2 バイト境界 ( 最終 ) / * 半角漢字定数 for HÅNKJ3 * / / * 半角漢字定数 for HANKJ4 * / / * 半角漢字定数 for その他 * / / * SPACE * / / * DE し * / / * Return * / / * BUZZER Asci i control COde / * HOME_CLR * / / * 漢字第 1 バイト * / / * 漢字第 2 バイト * / / * カーソル位置のポインタ * / / * データの最後のポインタ * / / * 入力域の最後のポインタ * / / * 入力可能文字数 ( 半角単位 ) / * 挿入モードフラグ 0 = 上書き / 1 = 挿入 * / / * 文字タイプ * / / * カーソル座標 * / 0xfe 0x3f 0xde 0x7f 0x9e 0x 1 f 0X20 0X02 0x0c 0X08 0x 12 0x7f 0x1b 0x0d 0X07 0x1e 0 1 2 *chr; *curptr; *maxptr; *endptr; maxcnt; insmode; ctype : xposit, yposit; カーソル前進 ー fo a 「 d 関数ー カーソル位置がバッファ末端てはない場 合には , カーソルと現行ポインタを 1 増やし ます (List4)0 ただし , カーソル位置が漢字 第 2 バイトにある場合には , 漢字第 1 バイト になるように調整します。 キー処理 —insert 関数ー / * キーポード定義 * / c I s ( ) : color (REV, SKY) : put-str(21,2,"*** キー入力ルーチンテスト ☆☆☆” , 38 ) : c010r(0RG, WHITE) : put-str(30.4," 1 : 1 文字入力 & 表示 " , 2 の : put-str(30,6,"2 : 文字列種別の取得 " , 2 の : put-str(30,8,"3 : パイト数の取得 ". 18 ) : put-str(30, 10 , " 4 : 文字列入力 " , 14 ) : put-str(30, 12. " 9 : 終了 " , 8 ) : c010r(0RG, SKY) : 応用 C 言語 105

5. 月刊 C MAGAZINE 1990年5月号

五ロ 用 応 TbI.2 get key st ″ヾラメータ 変数タイプおよび変数名 int 画面上の入力域の先頭 X 座標 int 画面上の入力域の Y 座標 Char *buffar 文字列テータを返すためのポインタ int 入力可能最大文字数 ( バイト単位 ) max int mode 入力 / 訂正モード入力 = 0 / 訂正 = 1 TbI.3 char set 用変数 静的変数 変数タイプおよび変数名 int type int nxtype 続くメモリ領域を破壊してしまいます。ま た , 2 バイトコードの文字を消去するときに 2 バイト目を消すような場合には , いっしょ に 1 バイト目も処理しないと , ゴミが残って しまいます。 上書きモードて、の注意は , 格納用の関数 char set に任せています。 ・デ明性を求めるために get_key str て、は , 内部バッフアの関係 上 , 最大 60 バイトまて、しか入力て、きません。 汎用的に使うには , この制約を取る必要が あります ( もっとも 1 画面の横桁数を超える と , 横スクロールまたは n 行の制御という特 殊な処理が必要になります ) 。制約を取るた めには , 作業用のバッファ work [ n ] を呼び 出し側て、もっことと , 扱える最大文字数を 完全に引数 max て、制御するようにします。呼 び出し側て、バッフアをもっ場合 , 新たに引 数を設けるか , 現在の文字列引渡し用のポ インタ * buffer を使用するかのいずれかの 方法を用いることになります。 7 文字格納処理 —char set 関数ー 入力された文字は , すべて char set て、格 納します (List2)0 char set て、は , 1 バイト 単位て、文字を格納しています。つまり , 2 バ イトコードの場合には 2 回呼び出されるよう になっています。このため , 2 バイトコード の処理は難しくなっていますが , そのかわ りにバッフアへ格納する際のバッフアの動 きをつかむことがて、きます。 char set て、は TbI. 3 のような変数を使用 します。いずれもバッフアのカーソル位置 の文字とその次の文字の種類を記憶するた めの変数て、す。静的変数なのは , 2 バイトコ ードを 2 回に分けて処理しているからてす。 挿入モードと上書きモードては処理を分 けます。 ・挿入モードでの格備 挿入モードは , バッフアの文字列を後方 応用 C 言語 101 変数の内容 変数の内容 カーソル位置の文字種 0 = ANK / 1 = 漢字第 1 バイト / 2 漢字第 2 バイト カーソル位置の次の文字種 ( 意味は , type と同じ ) 1 文字格納処理 char_set 1 : char set 3 : 4 : char_set(unsigned char *ichr) V 0 i d 6 : / * 文字種 int type; 7 : / * ANK 8 : / * 漢字第 1 バイト 9 : / * 漢字第 2 バイト / * カーソル位置の次の文字種 * / 12 : 13 : 14 : 15 : 16 : 17 : 19 : 20 : 22 : 23 : 24 : 25 : 26 : 28 : 29 : 30 : 32 : 33 : 34 : 35 : 36 : 39 : 40 : 42 : 43 : 44 : 46 : 49 : 50 : 52 : 53 : 54 : 55 : List 2 static static int if(insmode==l) 挿入モード * / if(*(endptr-l) !=B し ANK) buzzer() : goto end; i=get_str ln (curptr, maxptr-curptr 十 1) : *(curptr 十 j 十 1) =*(curptr 十 j) : / * brank c lear *curptr=BLANK; if(maxptr く endptr-l) maxptr 十十 : i 十十 : put-str(xposit, yposit, curptr, i) : csr_posit(xposit, yposit) : int nxtype; e lse { if(ctype==KANJ11) nxtype=test-str(chr, curptr 十 I) : type=test-str(chr, curptr) : if((type==KANJI 1 ) Ⅱ (ctype==KANJ12&&nxtype==KANJI 1)) * (curptr + I)=B し ANK; / * 漢字第 2 バイト消去 * / put-chr(xposit + l,yposit, BLANK) : else if((type==KANJ12)&&(ctype!=KANJ12)) *(curptr-1)=B し ANK; / * 漢字第 1 バイト消去 * / put-chr(xposit-l, yposit, B し ANK) : *curptr=* ichr; if (ctype==KANJI 2 ) put-str(xposit-l. yposit, curptr-l csr-posit(xposit 十 l,yposit) : if(ctype==ANK) put-chr(xposit, yposit, *curptr) : if(curptr>maxptr) maxptr=curptr; if(curptr く endptr-l)

6. 月刊 C MAGAZINE 1990年5月号

TbI.1 高水準ファイル入出力関係のランタイムライプラリ ( 一部 ) の比較表 MS-C Tu 「 bOC UNIXV ANSI 機能の説明 fclose fclose ファイルをクローズする fdopen fdopen x ファイルティスクリプタとしてオープンする feof feof ファイルの終端を検出する fflush fflush ファイルバッフアのはきだしを行う fg ets fg ets ファイルから 1 文字読み取る X ファイルティスクリプタの拾得 fileno fileno ファイルのオープン fopen fopen 書式つきファイルへの出力 fp ri n tf fp ri ntf fputs ファイルへ 1 文字書き込む fp u ts ファイルからの読み取り f 「 ead fread ファイルからの書式つき読み取り fscanf fscanf 現在地の移動 fseek fseek 現在地の取得 ftell fte ファイルへの書き込み fw 「 ite fw 「 ite getc/fgetc getc/fgetc ファイルから 1 文字読み取る putc/fputc ファイルへ 1 文字書き込む putc/fputc 現在の位置をファイルの先頭に戻す 「 ewind rewind ユーザバッフアを指定する setbuf setbuf しているためだ。したがって , プログラミ ングを行うとき , 一般には高水準関数を使 用したほうがプログラムの互換性もよくな る。低水準関数は , ハードウェアに依存し た処理をするプログラムを作るときだけに 限ったほうがよいだろう。 ファイルポインタ ファイルポインタは , ファイルハンドル よりもより多くの情報が付加された構造体 として提供されている。参考のために Fig. 2 に MS-C と TurboC の構造体を示す ( 同じフ ーイ ~ ポイタの構造体と 0 、ても : MS ー C と TurboC て、は多少異なっているカ , これ を使用するプログラマとしては , この違い をとくに意識する必要はないだろう ) 。 ファイルポインタを基本にしている高水 準ファイル入出力関数て、は , たんにファイ ルハンドルを扱うだけて、はなく , それ以上 の情報をつねに管理するようになっている。 これらの関数て、は , 構造体のポインタとし てファイルポインタをつねに返してくるの て、 , 以後はこのポインタがファイルの ID と なり , すべての管理情報のもとになってい さらにファイルディスクリプタをファイ ルポインタのように扱うことがて、きる関数 , fdopen() 関数がある。これは , open() 関数 て、オープンされたファイルをファイルポイ ンタて、も扱えるようにするためのものて、 , 実際にはファイルディスクリプタをオープ ンしてファイルポインタを得る処理をほど ファイル八ンドルから ファイルポインタを得る方法 Fig. 2 日 LE 構造体へッダファイル ・ MS ー C の日 LE 構造体 #define FILE struct iobuf extern FILE { char *_pt 「 , cnt . char * base Char Char file , } NEAR CDECL iob ロ : int ・ Tu 「 boC の日 LE 構造体 control structure fO 「 St 「 eams * / / * Definition Of the typedef st 「 uct short unsigned Char unsigned Char short unsigned Char unsigned Cha 「 unsigned short / * fill/empty level Of buffer FiIe status flags FiIe desc 「 iptor Ungetc char if no buffer Buffer size Data transfer buffer Current active pointer / * Temporary file indicator Used fO 「 validity checking * / / * This is the FILE object level: flags : ho 旧 : bsize . * buffer , *curp , istemp , token , List int fh,• FI し E *fp; open("sample. doc" fh fdopen(fh, 78 CMAGAZINE 19 5

7. 月刊 C MAGAZINE 1990年5月号

五ロ はじめて学ぶプロクラー ニンク 匚。司 った段階て、メモリの状態は Fig. 7 ー 1 のよ int * p ; うになっており , 領域が確保されてい 「 * 」は前節て、て、てきた , データ値を求める ます 間接演算子て、す。「ポインタ、、 p 〃の指す、、値〃 ② 12 行目 ( a = 10 ; ) て、 c れ ar 型変数 a に 10 は、、 int 型〃」を意味します。同様に「 char 型 これらのポインタの演算を行うためには , が代入されます (Fig. 7 ー 2 ) データを指すポインタ p 」の宣言は , やはりそのポインタ用の領域をメモリ上に ③ 13 行目 ( p = & a ; ) て、は変数 a のアドレス char * p ; 確保し , その値を記憶しなければなりませ 値を取ってきて ( アドレス取得演算子を となります。一般的にポインタ宣言の書式 ん。というのもポインタも変数のひとつな 使っています ) , ポインタ p に代入して は , このあたり慣れないと混 います。実行が終わった段階て、ポイン のて、すから・・ テータ型 * ポインタ名 乱するかもしれませんね。ポインタは , 記 タ p は a のアドレスを指すようになりま となります。ポインタの配列を取りたいと 憶しているデータが別の変数のアドレス ( 物 きには「ポインタ名 [ 要素数 ] 」とします。 す (Fig. 7 ー 3 ) 理的なアドレスという場合もある ) て、あると ④ 14 行目 ( x = * p ; ) て、はポインタ p の指 いうだけて、 , 変数の一種て、あることに変わ すアドレスから char 型のデータを取っ てきて ( 間接演算子を使っています。取 りないのて、す。 8 ー 2 て、は p はポインタて、あるとして説明し ってきた値は 10 て、す ) それを char 型変数 こまて、説明をして , ようやくまとまっ ましたが , 実際にはポインタを使う前に「 P x に代入しています。実行が終わった段 たプログラムを記述て、きるようになります。 する必要があ はポインタて、ある」と旦 階て、は Fig. 7 ー 4 となっています ポインタを使ったごく簡単な例を List1 に示 ります。しかし , ポインタ型などというデ 結局これらの動作により a の値が x にコピ します。動作が理解て、きるて、しようか ? ータ型も , それを表す型宣言子も存在しま ーされました。しかし直接代入するのて、は 蛇足かも知れませんが , Fig. 7 を使って説 せん。仮にあったとしてもこれまて、に述べ なく , ポインタ p を介してコビーされたとい てきた , 変数とポインタの互換性がとれな 明してみましよう。 うことが新鮮て、すね。そして , 変数 a が実際 ① 10 行目 (char * (;) まて、実行が終わ 何番地に用意されているのか , くなってしまいます。というのは変数とい という具体 っても char, int, float, double などと種 類がたくさんあり , 「おのおのデータのサイ ズが異なるからて、す」 (TbI.2)o したがって , たとえばポインタ P が同じと ころを指していても , データ型によって取 り出すデータのバイト数が異なります。 Fig. 6 この例て、は , にこの説明をしました。 → 1000 番地のデータ char 型データ を取り出す → 1000 , 1001 番地の int 型データ データを取り出す という使い分けが必要になります。ポイン タとひと口にいっても , 「 char 型データを取 り出すポインタ」や「 int 型データを取り出す ポインタ」といった使い分けが必要て、す。 「 c れ ar へのポインタ」とか「 int へのポインタ」 といういい方をする人もいます ( もちろん 「 float へのポインタ」や「 double へのポイン タ」などもちゃんと存在します ) 。 これらの事柄をふまえたうえて , 「 int 型デ ータを取り出すポインタ 0 」の宣言は次のよ うになります。 P 川 00 用囲番地 1001 番地 ha 「型データ int 型テータ ( 注 ) この例では cha 「型は 1 バイト . int 型は 2 バイトのサイズをもつ場合を示す TbI. 2 変数の基本テータ 型宣言子 バイト長 意味 1 バイト整数型 整数型 ( 注 1 ) 単精度浮動小数点型 ( 注 2 ) 倍精度浮動小数点型 float 型の 2 倍 注 1 CPU による。一般的にいってビットのコンビュータでは給ビット , つまり 2 バイト。 MS-DOS 上ではおもに 2 バイト 注 2 CPU による。パソコンクラスでは 4 バイトが一般的 Char i nt float double 1 はじめて学ぶ C プログラミング 125

8. 月刊 C MAGAZINE 1990年5月号

いときには , わざわざ「リスト」になっているのは , const これも構文を満足しています。が , const Char は宣言子て、はなく , char とくつついて宣言 と volatile を両方とも書くことを許している char const d; からてす。 指定子として解釈されます。 言子は c だけ というふうに宣言を分割しなければなりま て、す。 int * const volatile 店 せん。 のように書けるのて、す。ただし , const const Char const c, d; char C, * const p; のように同じ型修飾子を重ねたときには工 というのはどうて、しよう。これも const は char なら OK て、す。 ラーになるて、しよう oconst と volatile を併 とくつついて宣言指定子になりますから OK て、は実際のコンパイラの動作を確かめて て、す。 c も d も const 属性をもつオプジェクト 用する意味については後述します。 みましよう。 List2 のプログラムを MS-C と 宣言子の中て、 const, volatile を書いても になります。 TurboC て、コンパイルしてみると , Fig. 2 の よいのは * の後ろだけだという点に注意し c, const d; char ようになります。 これはどうてしようか。 c はよいのてす てください この結果を見て驚いたのは , なんと MS- が , d が問題て、す。カンマの後ろは宣言子の char * const p; C て、は 2 行目の 1 の宣言が通ってしまう ( / ) こ はずて、すが , 文法ては宣言子の中の const は これは「 const 属性をもつポインタ P 」の正 とて、す。さっき文法工ラーだと書いたばか * の後ろにしか現れなくてはいけません。 しい宣言てす。 c れ ar が宣言指定子 , * const ・ ,TurboC て、はしつかりとエラ りなのに・ この宣言は文法工ラーて、す。 P が宣言子て、す。 ーになってしまいます。 このように , d だけに const 属性を与えた char MS-C< は const 1 が宣言子として解釈さ れているわけて、すが , ては 1 行目の宣言ては 宣言指定子は int だけて、 , const i が宣言子と なっているのて、しようか。 MS-C のコンパイル結果からみると , 1 行 目の宣言て、 i , j はどちらも const 属性をもっ ています。 6 , 7 行目の i , j への代入文がエラ ーになっています。したがって , int const は宣言指定子として , i が宣言子として解釈 されているといえます。 おそらく MS-C< は , 「宣言子のリストの うち , カンマの後ろには const が出てきても よい」という文法の拡張を行っているのてし よう。皆さんはこういう処理系独自の拡張 を使わないようにしたほうがいいてしよう。 これは ANSI 標準規格からはずれた文法てす から , せつかく作ったプログラムの移植性 を損なうことになります。 const の意味 const 属性をもつオプジェクトの宣言のし かたについてひととおり説明しました。次 const 属性についてお話しましよう。 まず , const 属性が与えられると , そのオ プジェクトは値を変更することがて、きなく なります。 const c; コンバイラのテストプログラム / * 正しい宣言 / * Ⅱよ工ラーになるはず * / List 2 1 ー 0 乙っ 0 -4 LO 6 0 ー 8 9 0 1 11 11 k, const 1 : 工ラ 工ラ 、エラ / * OKO ただし , 1 の宣言がエラー * / Fig. 2 コンバイル結果 (a)MS-C A 〉 cl a. c Microsoft ( 日 ) C Optimizing Compile 「 Version 5.10 Microsoft CO 「 p 1984 , 1985 , 1986 , 1987 , 1988. Copyright (c) AII rights reserved. ⅳ specifies const' Object C2166 : a. c(6) e 「「 0 「 C2166 : lvals specifies const' object a. c(7) e 「「 0 「 ⅳ specifies 'const' Object C2166 : a. c(9) e 「「 0 「 (b) TurboC A 〉 tcc a . C C Version 2.0 Copyright (c)1987 , 1988 Borland lnte 「 national Tu 「 bo a. c; a . C 2 : Declaration syntax e 「「 0 「 E 「「 0 「 a. c 6 : Connot modify a const object in function f E 「「 0 「 a. c 7 : Connot modify a const object in function f E 「「 0 「 a . C 9 : Undefined symbol 'I' in function f E 「「 0 「 4 e 「「 0 「 S in Compile * * * AvaiIable memory 239974 118 CMAGAZINE 19 5

9. 月刊 C MAGAZINE 1990年5月号

ッフアへのポインタ ( 変数 curptr ) を同時に 更新しなくてはなりません。 カーソルは , 文字を入力すると自動的に 1 桁ずっ進みますが , 必ず自分て、カーソル位 置を設定するようにしましよう。 ・入力モードと訂正モード get key str て、は , 入力と訂正を行える ようにしています ( 引数 mode) 。内部に作業 用に 80 バイト分のバッファ ( 配列 work ロ ) を抱えているのて、 , まず関数の頭て、配列を プランク ( 0X20 ) て、クリアします。入力時に はそのまま入力を開始しますが , 訂正時に は訂正用の文字列を配列 work へ転送します ( 訂正用の文字列は引数 * buffer にありま なお , 一律 80 バイトを転送しているのて、 , 呼び出し側のバッフアは最低て、も 80 バイト 確保しておきます。 ・挿入モードと上書きモード 初期値は , 挿入モードになっています。 この処理は , キーを押すことて、切 り換えます。挿入モードて、注意する点は , ふたつあります。 ①文字の格納時の処理 文字をバッフアに格納する際に , カーソ ル位置のバッフア内容を後方へずらしま す。詳細は , 格納用の関数 ( 曲 ar set) て、 説明します。 ②バッフアの余白のチェック カーソル位置から後ろの文字をずらすた めの余白がバッフアにあるか否かをチェ ックします。 仕様としては , 余白がなくても無視して , 後方の文字から消去してしまう方法もあり ます。しかし , 今回は最大入力文字数を設 定しているのて、 , バッファ末端の余白をチ ェックして , 余白がない場合にはエラーを 返すようにしています。 余白がないときに後方の文字を消去する よう改造する場合には , 転送文字数の確認 と 2 バイトコードの処理が必要て、す。転送文 字数をきちんと計算しないと , バッフアに 100 CMAGAZINE 19 5 List 1 / * 全角文字 * / ニ 1 ) & & ( * (endptr-2) ! = B し ANK ) ) / * 挿入余地なし * / / * 入力不可能 * / / * 漢字第 1 バイト格納 * / / * 漢字第 2 バイト格納 * / / * A N K 文字 * / / * 右矢印 * / / * 左矢印および B S * / / * リターン * / case KANJII : if((insmode buzzer ( ) : i f ( curptr buzzer() : 引 se { char_set(&inchr[0]) : ctype=KANJI 2 : char_set(&inchr[l]); break; case ANK: char-set(&inchr[0]) : break; case FWD: forward() : break : case BACK : backward() : break : case ESC : rc=l; case CR: rc=0; for(i=0;i く max;i + + ) *(buffer + i)=work[i] : case INS: insert() : break; case DE し : delete(); break : default: buzzer() : while( ctype!=CR & & ctype!=ESC ) : return (rc) : 8 0 1 よっ 0 っ 0 •< ・ -. 0 《 0 ー 8 0 11 ワ 0 っ 0 -4 ・ -. 0 《 0 ー 8 0 11 ワっ 0 -4 ・ - -0 ^ 0 7 ー 8 0 11 ワっ 0 -4 ・ - -0 ^ 0 -4 : 4 戸 0 戸 0 口 - -0 ′ 0 ) L.n LO ′ 0 ^ 0 《 0 C-O cD C-D C-D れ 0 0 ーーーーっーーーーーー 8 8 8 8 8 8 8 ニ endptr-l ) TbI. 1 get key st 「用変数 モジュール内共通変数 変数タイプおよび変数名 char *Chr Char * curptr Char * maxptr Char * endptr int maxcnt int lnsmode int Cty P e 変数の内容 文字列バッフアへのポインタ 現在のカーソル位置を示す文字列バッフアへのポインタ バッフア最後の文字へのポインタ 最大入力位置の次を示すポインタ ( ここには , 入力不可 ) 最大入力文字数 モードフラグ挿入 = 1 / 上書き = 0 入力文字 / 設定文字タイプ ANK = 0 / 漢字第 1 バイト = 1 / 漢字第 2 バイト = 2 現在のカーソル X 座標 現在のカーソル Y 座標 xposit yposit 変数および変数名 int int 内部変数 変数の内容 char WO 「 k [ 70 ] char inchr[2] 文字列用作業バッファ 入力文字用パッファ

10. 月刊 C MAGAZINE 1990年5月号

CC msconv . C て、す。デバイスディスクリプタのアセンプ ルはソースファイルの先頭に簡単に説明し てありますのて、そちらを参照してください NEC PC-98, FM16 角 FMII はそれぞれ異 なるのて、ここて、は説明しません。 OS 9 上での操作 プログラムの使い方を説明します。 起動は実行ディレクトリにデバイスドラ イバを置いた状態からプログラムを起動す るだけて、す。デバイスドライバを load , iniz する必要はありません。 argv [ 1 ] にデバイ スドライバ名を指定すればそれを load, attach します。 argv [ 1 ] が省略された場 合は MSdO が指定されたものとして load, attach します。プログラムが起動してプロ ンプト msconv : が表示されたのち , MS- DOS ディスクを所定のドライプに挿入して コマンドを入力します。コマンドの形式は , 2 文字 [ ファイル名 ] [ ファイル名 ] て、す。区切りはスペースて、 , コマンド名を まちがえるとコマンド説明が表示されます。 読み込みファイル名にはふたつのワイルド カードキャラクタ ' * ' , ' ? ' が使用て、きます。 ファイル名の末尾に ' \ ' ' / ' が付加されたと きは , それがディレクトリ名て、あると限定 して検索します。 D, L コマンドからは出力 先を stdout 以外にすることがて、きます。パイ プは使用て、きません。バグなどの可能性も ありますのて、 , MS ー DOS への書き込みは破 壊されてもかまわないディスクを使用する ほうが無難て、しよう。 OS ー 9 への書き込みは 標準関数と標準 RBF マネージャを使用して います。 OS ー 9 て、のプログラム開発環境は , その昔 においては素人から見て MS ー DOS に勝って いたと思っていましたが , MS-DOS の隆盛 とともにその開発環境が値段 , 量ともに逆 転してしまったようて、す。 1 万円以下の C コ ンパイラを見るにつけてもうらやましい限 0 List 1 : / * し Harc 圧縮ファイルの先頭を捜しだしてそこからのデータのみを * / 4 : / * chec ksum を計算して合致するかどうかによって判断する。 3 : / * 圧縮ファイルの先頭が " ヨ ? ? ー " になっている場所を捜して 2 : / * 拡張子コ zh 付のファイルへ書き込む 5 : 6 : 9 : 10 : 20 : 22 : 23 : 24 : 25 : 26 : 27 : 28 : 29 : 30 : 32 : 33 : 34 : 35 : 37 : 38 : 39 : 40 : 42 : 43 : 44 : 45 : 46 : 48 : 49 : 50 : 52 : 53 : 54 : 58 : 59 : 60 : 62 : 63 : 66 : 67 : 68 : 69 : 70 : 73 : 74 : 76 : 78 : 80 : FILE * fp. *op; Char Izhname[13] : fname[13], i nt C : 1 1 : ma i n ( ) int archive-is-msdos_sfxl ( ) , skip_msdos sfxl code(), unsigned Char Buffer[2048] : 8 : #define SEEK_CUR 1 7 : #define SEEK_SET 0 #include く ctype. h> #include く stdio. h> calc-sum() : pr i ntf ( " * * * C MAGAZI N E 自動解凍プログラム切り離し用ユーティリティ ***Yn") : pr i ntf ( " 拡張子コ zh がついたファイルは指定しないで下さい。 yn") : ニ NU しし ) { fopen(fname, i f ( (fp fname) , scanf("Xs" printf("File Name ? " ) : fname) : if ( archive-is_msdos-sfxl(fname) ) { fseek(fp, (long)0, SEEK_SET) : ex i t ( の : printf("Y"%sY" can ・ t find. Yn" skip-msdos-sfxl=code(fp) : fname [strlen (fname) ・ \ 0 冖 sprintf(lzhname, fname) : printf("making Y"%sY"Yn" lzhname) : fopen (lzhname, OP wh Ⅱ e ( (c fread(Buffer, s izeof (char) , fclose(op) : fclose(fp) : fwrite(Buffer, c. 1 , (p) : *name : Char int archive is_msdos sfxl(name) lname (char *)malloc(len + 1); len int i, strlen(name) : * lnane : Char name lname *lname 十十 ー 0 : i for ( i 2048. (p) ) ! ニ 0 ) く len; i 十十 ) tolower(*name 十十 ) : return( (len > = 4 ) & & (!strcmp(lname + len ! strcmp(lname 十 len . CO 田” ) int skip-msdos-sfxl_code(fp) 55 : F ILE *fp : uns igned Char long int fread (Buffer, sizeof (char) , 2048 , n for ( p = Buffer + 2. q = Buffer + n ー 5 : p く q : p + + ) { 56 : { fseek(fp, (long) -n, SEEK-CUR) : return 1 : - Buffer) : pri ntf(' ・ start seek po inter = 0xX04xYn" - Buffer) ー n) . SEEK_CUR) : fseek(fp. (long) ( ( (p - = calc-sum(), p ト 2 ] ) ) { if ( p ト 2 ] 〉 20 & & p[-l] if ( p[0] = int calc_sum(p. 75 : Char i nt len : int sum; for ( sum 0 : len ) 0 : len: len sum 十ニ * p 十十 : return sum & 0xff; Conference Room 137