/****************************************************************************** Snippet: Soundex parser. Author: Richard Woolcock (aka KaVir). Date: 20th December 2000. ****************************************************************************** This code is copyright (C) 2000 by Richard Woolcock. It may be used and distributed freely, as long as you don't remove this copyright notice. ******************************************************************************/ /*************************************************************************** * _/ _/ * * _/_/_/ _/_/ _/_/_/ _/ _/_/ _/ _/ _/_/_/ * * _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ * * _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ * * _/ _/ _/ _/_/_/ _/ _/_/ _/_/_/ _/_/_/ * *************************************************************************** * Mindcloud Copyright 2001-2003 by Jeff Boschee (Zarius), * * Additional credits are in the help file CODECREDITS * * All Rights Reserved. * ***************************************************************************/ /****************************************************************************** Required library files. ******************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include "merc.h" /****************************************************************************** Local literals ******************************************************************************/ #define KEY_SIZE 4 /* Size of the soundex key */ /****************************************************************************** Local operation prototypes. ******************************************************************************/ static char LetterConversion(char chLetter); /****************************************************************************** Global operations. ******************************************************************************/ /* Function: GetSoundexKey * * This function determines a soundex key from the string argument and returns * the address of the key (which is stored in a static variable). Because the * most common use of the soundex key is to compare it with _another_ soundex * key, this function uses two internal storage buffers, which are alternated * between every time the function is called. * * The function takes one parameter, as follows: * * szTxt: A pointer to the string from which the soundex key is calculated. * * The return value is a pointer to the soundex key string. */ char *GetSoundexKey(const char *szTxt) { int iOldIndex = 0; /* Loop index for the old (szTxt) string */ int iNewIndex = 0; /* Loop index for the new (s_a_chSoundex) string */ static char s_a_chSoundex[2][KEY_SIZE + 1]; /* Stores the new string */ static unsigned iSoundex; /* Determines which s_a_chSoundex is used */ iSoundex++; /* Switch to the other s_a_chSoundex array */ s_a_chSoundex[iSoundex % 2][0] = '\0'; /* Clear any previous data */ /* * Copy the first character without conversion */ if ((s_a_chSoundex[iSoundex % 2][iNewIndex++] = tolower(szTxt[iOldIndex++]))) { do /* Loop through szTxt */ { char chLetter; /* Stores the soundex value of a letter */ /* * Double/triple/etc letters are treated as single letters */ while (tolower(szTxt[iOldIndex]) == tolower(szTxt[iOldIndex + 1])) { iOldIndex++; continue; } /* * Convert the letter into its soundex value and store it */ chLetter = LetterConversion((char) tolower(szTxt[iOldIndex])); /* * Ignore NUL and 0 characters and only store KEY_SIZE characters */ if (chLetter != '\0' && chLetter != '0' && iNewIndex < KEY_SIZE) { /* * Store the soundex value */ s_a_chSoundex[iSoundex % 2][iNewIndex++] = chLetter; } } while (szTxt[iOldIndex++] != '\0'); /* * If less than KEY_SIZE characters were copied, buffer with zeros */ while (iNewIndex < KEY_SIZE) { s_a_chSoundex[iSoundex % 2][iNewIndex++] = '0'; } /* * Add the NUL terminator to the end of the soundex string */ s_a_chSoundex[iSoundex % 2][iNewIndex] = '\0'; } /* * Return the address of the soundex string */ return (s_a_chSoundex[iSoundex % 2]); } /* Function: SoundexMatch * * This function compares two soundex keys and returns a percentage match. * * The function takes two parameters, as follows: * * szFirst: A pointer to the first soundex key. * szSecond: A pointer to the second soundex key. * * The return value is an integer which contains the percentage match. */ int SoundexMatch(char *szFirst, char *szSecond) { int iMatch = 0; /* Number of matching characters found */ int iMax = 0; /* Total number of characters compared */ /* * Make sure that both strings are of the correct size */ if (strlen(szFirst) == KEY_SIZE && strlen(szSecond) == KEY_SIZE) { int i; /* Loop counter */ /* * Loop through both strings */ for (i = 0; i < KEY_SIZE; i++) { /* * If either of the values are not NUL */ if (szFirst[i] != '0' || szSecond[i] != '0') { iMax++; /* Increment the maximum */ } /* * If BOTH values are not NUL */ if (szFirst[i] != '0' && szSecond[i] != '0') { /* * Check for a match */ if (szFirst[i] == szSecond[i]) { iMatch++; /* A match was found */ } } } } /* * Return the percentage match */ return (iMatch * 100 / iMax); } /****************************************************************************** Local operations. ******************************************************************************/ /* Function: LetterConversion * * This function converts a single letter into it's appropriate soundex value. * * The function takes one parameter, as follows: * * chLetter: The letter to be converted. * * The return value is a single character which contains the converted value. */ static char LetterConversion(char chLetter) { const char *kszSoundexData = "01230120022455012623010202"; char chResult; /* Store the soundex value, or NUL */ if (islower(chLetter)) { /* * Determine the soundex value associated with the letter */ chResult = kszSoundexData[(chLetter - 'a')]; } else /* it's not a lowercase letter */ { /* * NUL means there is no associated soundex value */ chResult = '\0'; } /* * Return the soundex value, or NUL if there isn't one */ return (chResult); }