コマンドプロンプトで、cd 23tok のあと dir を実行するとファイルの一覧が出る。
「dir *.c」を実行してみよ。 すると、ファイルの名前が .c で終わるファイルだけの一覧が出る。 この「*」は、0 文字以上の任意の文字列を表す。 ほかに、「?」は任意の一文字を表す。 たとえば、renshu...c という名前のファイルがあるとして、 「dir renshu?.c」とすると、renshu1.c, renshu2.c などは出るが、 renshu12.c は出ない。 この「*」「?」を「ワイルドカード」と呼ぶ。
Windows についている find は、指定された文字列を複数ファイルから探しだすものである。 「find "文字列" ファイル名」として実行する。 「find "printf" *.c」「find "strcmp" *.c」など、実行してみよ。
注意:unix の find はまったく違うプログラムである。
§11.1 のプログラムでは、 コマンドライン引数が「?」「*」を含んでいると、 それらは“展開”されるのだった。 これを利用すると、find のように動くプログラムが書ける。
#include <stdio.h> #include <stdlib.h> #include <string.h> #define MAXLINE 1024 int main(int argc, char *argv[]) { int i, first; FILE *in; char line[MAXLINE]; if (argc == 1) { fprintf(stderr, "使い方が違います.\n"); exit(1); } for (i = 2; argv[i] != NULL; i++) { if ((in = fopen(argv[i], "rt")) == NULL) { fprintf(stderr, "%s が開けません.\n", argv[i]); exit(1); } first = 0; /* そのファイルでまだ見つかっていなければ 0 */ while (fgets(line, MAXLINE, in) != NULL) { if (strstr(line, argv[1]) != NULL) { /* argv[1] を line が含んでいれば */ if (first == 0) { printf("== %s ==\n", argv[i]); /* ファイル名は一度だけ表示 */ first = 1; } fputs(line, stdout); /* その行を表示 */ } } fclose(in); /* たくさんのファイルを開くので、済んだら閉じる必要あり */ } }
関数 strstr(char *string, char *key) は、 key が string に含まれていれば、 最初に含まれている位置を返す。含まれていなければ NULL を返す。
「0123456789」の「2345」を文字 8 の前に移動するプログラムを書いてみよう。 「0167234589」となれば成功である。 もう一つ同じ長さの配列をとれるなら簡単だが、それはできないものとする。
これには、昔から知られているアルゴリズムがある。 まず、2345 を反転して 5432 とする。 67 を反転して 76 とする。 これで「0154327689」となった。 最後にこれらを合わせた 543276 を反転させると「0167234589」となる。 反転は、ソートプログラムで作った関数 swap() の要領でできる。
#include <stdio.h> char str1[] = "0123456789"; char str2[] = "0123456789"; void move(char *str, int from, int to, int here); int main() { puts(str1); move(str1, 2, 5, 8); puts(str1); putchar('\n'); puts(str2); move(str2, 5, 8, 2); puts(str2); } void move(char *str, int from, int to, int here) { int i, j; char tmp; i = from; j = to; while (i < j) { tmp = str[i]; str[i] = str[j]; str[j] = tmp; i++; j--; } if (to < here) { i = to + 1; j = here - 1; while (i < j) { tmp = str[i]; str[i] = str[j]; str[j] = tmp; i++; j--; } i = from; j = here - 1; while (i < j) { tmp = str[i]; str[i] = str[j]; str[j] = tmp; i++; j--; } } else if (here < from) { i = here; j = from - 1; while (i < j) { tmp = str[i]; str[i] = str[j]; str[j] = tmp; i++; j--; } i = here; j = to; while (i < j) { tmp = str[i]; str[i] = str[j]; str[j] = tmp; i++; j--; } } }
move(2, 8, 5) などを実行した場合の動作は保証されない。
これが、私が金沢大学の授業で作る最後のプリントです。 長い間ありがとうございました。 SDG (= Soli Deo gloria)。