コマンドプロンプトで、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)。