p = guess; /* copy next component into guess */
for (; *old != '/' && *old != '\0'; old++)
if (p < guess+DIRSIZ)
*p++ = *old;
*p = '\0';
if (mindist(newname, guess, best) >= 3)
return -1; /* hopeless */
for (p = best; *new = *p++; ) /* add to end */
new++; /* of newname */
}
}
mindist(dir, guess, best) /* search dir for guess */
char *dir, *guess, *best;
{
/* set best, return distance 0..3 */
int d, nd, fd;
struct {
ino_t ino;
char name[DIRSIZ+1]; /* 1 more than in dir.h */
} nbuf;
nbuf.name[DIRSIZ] = '\0'; /* +1 for terminal '\0' */
if (dir[0] == '\0') /* current directory */
dir = ".";
d = 3; /* minimum distance */
if ((fd = open(dir, 0)) == -1)
return d;
while (read(fd,(char *)&nbuf, sizeof(struct direct)) > 0)
if (nbuf.ino) {
nd = spdist(nbuf.name, guess);
if (nd <= d && nd != 3) {
strcpy(best, nbuf.name);
d = nd;
if (d == 0) /* exact match */
break;
}
}
close(fd);
return d;
Если имя каталога, данное
mindist
, пустое, отыскивается
'.'
. Функция
mindist
читает одну строку каталога за один раз. Отметим, что буфер для
read
представляет собой структуру, а не массив символов. Мы используем
sizeof
, чтобы вычислить число байтов и привести адрес к символьному указателю.
Если строка каталога в данный момент не используется (поскольку файл удален), то поле индекса в ней равно нулю и она пропускается. Проверка расстояния осуществляется как
if (nd <= d...)
а не как
if (nd < d...)
поэтому любой одиночный символ дает лучшее совпадение, чем имя
'.'
, которое всегда является первой строкой в каталоге.
/* spdist: return distance between two names */ /*
* very rough spelling metric:
* 0 if the strings are identical
* 1 if two chars are transposed
* 2 if one char wrong, added or deleted
* 3 otherwise
*/
#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 <stdio.h>
#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++)