#define EQ(s,t) (strcmp(s,t) == 0)
spdist(s, t)
char *s, *t;
{
while (*s++ == *t)
if (*t++ == '\0')
return 0; /* exact match */
if (*--s) {
if (*t) {
if (s[1] && t[1] && *s == t[1] && *t == s[1] && EQ(s+2, t+2))
return 1; /* transposition */
if (EQ(s+1, t+1))
return 2; /* 1 char mismatch */
}
if (EQ(s+1, t))
return 2; /* extra character */
}
if (*t && EQ(s, t+1))
return 2; /* missing character */
return 3;
}
Поскольку у нас есть spname, несложно вставить функции по коррекции написания в p:
/* p: print input in chunks (version 4) */
#include
#define PAGESIZE 22
char *progname; /* program name for error message */
main(argc, argv)
int argc;
char *argv[];
{
FILE *fp, *efopen();
int i, pagesize = PAGESIZE;
char *p, *getenv(), buf[BUFSIZ];
progname = argv[0];
if ((p=getenv("PAGESIZE")) != NULL)
pagesize = atoi(p);
if (argc > 1 && argv[1][0] == '-') {
pagesize = atoi(&argv[1][1]);
argc--;
argv++;
}
if (argc == 1)
print(stdin, pagesize);
else
for (i = 1; i < argc; i++)
switch (spname(argv[i], buf)) {
case -1: /* no match possible */
fp = efopen(argv[i], "r");
break;
case 1: /* corrected */
fprintf(stderr, "\"%s\"? ", buf);
if (ttyin() == 'n')
break;
argv[i] = buf; /* fall through... */
case 0: /* exact match */
fp = efopen(argv[i], "r");
print(fp, pagesize);
fclose(fp);
}
exit(0);
}
Функции по коррекции написания не следует слепо применять к каждой программе, которая использует имена файлов. Они хорошо сочетаются с p, так как p — диалоговая программа, но подходят и для недиалоговых программ.
Насколько вы можете улучшить эвристику для выявления наилучшего совпадения в spname? Например, неразумно рассматривать регулярный файл так, как если бы он был каталогом; текущая версия это допускает.
Имя tx совпадает с каким-либо именем tc, которое оказывается последним в каталоге для любого одиночного символа с. Можете ли вы придумать лучшую меру расстояния? Реализуйте ее и посмотрите, насколько хорошо эта конструкция работает с реальными пользователями.
Работает ли p ощутимо быстрее, если чтение каталога выполняется большими порциями?
Модифицируйте spname, чтобы возвращать имя, которое является префиксом желаемого имени, если нельзя найти более точного совпадения. Как следует разрешить ситуацию, если несколько имен совпадают с префиксом?
Какую пользу могли бы извлечь другие программы из spname? Сконструируйте отдельную программу, которая корректировала бы другие аргументы прежде, чем передать их другой программе, как в
$ fix prog filenames...
Можете написать версию cd, которая использует spname? Как бы вы ее встроили?
7.3 Файловая система: индексные дескрипторы