Windows programmings (7) - フィルタ -			2001.March

1. 概要
 次なる出し物はフィルタです。あ、これもコンソールプログラムね。

 テキストな入力を加工してテキストで出力する。

 という動作をするプログラムのことです。DOSだとsortとかがこの系列です。

  C:\> dir | sort > hoge.txt

 ってなことして使う。いや、この例では全然嬉しくもなんともないけど。
 興味がおありならunix系の本をぱらぱらめくってみて。

 コマンドライン。MS系では「DOS窓」と呼ばれる代物上で使われるものです。
 Machintoshでは事実上無視され、Windows MEではデフォルトではDOSコマンドが
 起動できなくなってる。ってぐらい冷遇されてます。
 (fdiskってやってみな。Meだとそんなコマンド知らねぇ。とかしらばっくれ
  やがるから。SE辺りだと素直に起動してくれるんだが)
 MEだってWindows9x。C:\Windows\commandの下にちゃんとfdiskは居るんだが。

 …しかしMEって、98SEより更に使いにくくなってるようなんだけど、私の気のせい?
 以前のバージョンで平気でできたことが不可能になってるってのは(毎度毎度思う
 のだが)勘弁して欲しいものだ。

#一つだけ例示すると、「スタート」メニューに毎回使用するドライブやフォルダの
 ショートカットを入れる。そうするとCTRL + ESC + 登録文字列の先頭文字。で
 一発でそのフォルダが開けたのだが、MEでは不可能

 さて。実はこのフィルタ系プログラムをCで書くというのは余り、賢くない。
 というのを最初に言うべきでしょう。

 何故かと言うと、入出力の双方がテキストであるなら、それらはいわゆる
 スクリプト言語で操作する方が一般にはもの凄く楽だからです。

/* filter.c - basic filter */ #include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]) { FILE *fr, *fw; int ch; if (argc>1){ if ((fr=fopen(argv[1],"r")) == NULL){ fprintf(stderr,"Input can't open.\n"); return EXIT_FAILURE; }; } else fr=stdin; if (argc>2){ if ((fw=fopen(argv[2],"w")) == NULL){ fprintf(stderr,"Output can't open.\n"); return EXIT_FAILURE; }; } else fw=stdout; while ((ch=getc(fr)) != EOF) { // TODO: Write filter functions like this! //if (ch=='0x0A') fputc('0x0D',fw); fputc(ch,fw); }; if (fr!=stdin) fclose(fr); if (fw!=stdout) fclose(fw); return EXIT_SUCCESS; } /* EOF */
stdlibを#includeしてるのはつまりreturn EXIT_SUCCESSってのをやりたいだけでやってます。 というのは秘密です(ぉぃ)
最後のfclose()はしなくても一向に問題はないんですが、自分でopenしたら自分で closeする。というのは基本ですね。 これぐらいはOSを信用しろよ。とかいう声も聞こえる気がしますが……。
んで下は、オプション指定が可能なフィルタ。
/* filtarg.c */ #include <stdio.h> #define R 0 #define W 1 static FILE *fp[2]; typedef struct tag_err { int ecode; char *emsg; } err; static err errs[] = { {0, NULL}, {1, "Input can't open."}, {2, "Output can't open."}, {3, "Too many arguments."}, {4, "Invalid option."}, {-1, "Usage: filter_sample [{-options}...] [infile[outfile]]"} }; // -------------------------------------------------------------------- static err* args(int ac, char *av[]) { int i, j=0; fp[R] = stdin; fp[W] = stdout; for (i=1; i<ac; i++) { if (av[i][0] != '-') switch (j) { case R: if ((fp[j++]=fopen(av[i],"r"))!=NULL) continue; return &errs[1]; case W: if ((fp[j++]=fopen(av[i],"w"))!=NULL) continue; return &errs[2]; default: return &errs[3]; } // Options switch (av[i][1]) { case 'a': // option 'a' fprintf(stderr, "option 'a'\n"); break; case 'b': // option 'b' fprintf(stderr, "option 'b'\n"); break; case 'v': case '?': return &errs[sizeof(errs)/sizeof(err) -1]; default: return &errs[4]; } } return &errs[0]; } // -------------------------------------------------------------------- int main(int argc, char *argv[]) { int ch; err *er; er = args(argc, argv); if (er->ecode == 0){ while ((ch=getc(fp[R]))!=EOF) { // TODO: Write filter functions like this! //if (ch=='0x0A') fputc('0x0D',fw); fputc(ch,fp[W]); } } else fprintf(stderr, "%s\n", er->emsg); if ((fp[R]!=NULL) && (fp[R]!=stdin)) fclose(fp[R]); if ((fp[W]!=NULL) && (fp[W]!=stdout)) fclose(fp[W]); return er->ecode; } /* EOF */
……でも、なんかやたらややこい気もします。 う〜む。
#ま、所詮あたいにできるのはこの程度までだわさ。ってことで笑って許して(^^;;
2001.6 だ〜!最初のサンプルでargc>2の時、fopen()で代入すべきはfw!frぢゃねぇ     だろが。私の馬鹿アホ、間抜け!!     という訳で修正しました(;_;)。gccが警告してくれたんです (EOF)