Книга: UNIX — универсальная среда программирования

3.8.49 spname.c

3.8.49 spname.c
/* spname: return correctly spelled filename */
/*
 * spname(oldname, newname) char *oldname, *newname;
 * returns -1 if no reasonable match to oldname,
 * 0 if exact match,
 * 1 if corrected.
 * stores corrected name in newname.
 */
#include <sys/types.h>
#include <sys/dir.h>
spname(oldname, newname)
 char *oldname, *newname;
{
 char *p, guess[DIRSIZ+1], best[DIRSIZ+1];
 char *new = newname, *old = oldname;
 for (;;) {
  while (*old == '/') /* skip slashes */
   *new++ = *old++;
  *new = '';
  if (*old == '') /* exact or corrected */
   return strcmp(oldname, newname) != 0;
  p = guess; /* copy next component into guess */
  for ( ; *old != '/' && *old != ''; old++)
   if (p < guess+DIRSIZ)
  *p++ = *old;
  *p = '';
  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] = ''; /* +1 for terminal '' */
 if (dir[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;
}
/* 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++ == '')
   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;
}

Оглавление книги


Генерация: 1.908. Запросов К БД/Cache: 3 / 1
поделиться
Вверх Вниз