1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
|
#include <iostream>
#include <cctype>
#include <algorithm>
#include <string>
#include <map>
using namespace std;
string target;
map<char,char> cmap;
//===========================================================
void setMap() // set up Soundex character-to-digit map
{
for ( char c: "BFPV" ) cmap[c] = '1';
for ( char c: "CGJKQSXZ" ) cmap[c] = '2';
for ( char c: "DT" ) cmap[c] = '3';
cmap['L'] = '4';
for ( char c: "MN" ) cmap[c] = '5';
cmap['R'] = '6';
}
//===========================================================
string removeChars( string s, int pos, bool pred( char c ) )
{
if ( pos < s.size() ) s.erase( remove_if( s.begin() + pos, s.end(), pred ), s.end() ); // erase/remove idiom
return s;
}
//===========================================================
bool contains( char c ) { return target.find( toupper( c ) ) != string::npos; } // does current target contain char c?
//===========================================================
string soundex( string word )
{
// Remove non-alphabetic characters
string result = removeChars( word, 0, []( char c ){ return !isalpha( c ); } );
// Put in upper case
for ( char &c : result ) c = toupper( c );
// Store first character
char firstLetter = result[0];
// Remove all occurrences of H and W except first letter
target = "HW"; result = removeChars( result, 1, contains );
// Map consonants to digits
for ( char &c : result ) if ( cmap.count( c ) ) c = cmap[c];
// Replace all adjacent same digits with one digit
for ( int i = 1; i < result.size(); i++ ) if ( result[i] == result[i-1] ) result[i-1] = '*'; // star previous identicals
target = "*"; result = removeChars( result, 0, contains ); // then remove them
// Remove all occurrences of AEIOUY except first letter
target = "AEIOUY"; result = removeChars( result, 1, contains );
// Put back first letter
result[0] = firstLetter;
// Get correct length and return
result += "000"; // Add any potential padding
return result.substr( 0, 4 ); // But keep length to 4 letters
}
//===========================================================
int main()
{
string word;
setMap();
while ( true )
{
cout << "Enter a word (empty to end): "; getline( cin, word );
if ( word == "" ) return 0;
cout << "Soundex representation is " << soundex( word ) << endl;
}
}
|