Soundex Code

(Please note that this is not a homework assignment.) I'm trying to do a soundex code where it writes out something like this: C160, but it comes out like this: C000. How do I fix this? Please Help me.

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
// ReverseName.cpp
// By Gage Haldey
// Copyright 2018
// Licensed under the terms of the GPL 3
// To compile: g++ -o ./ReverseName.bin ./ReverseName.cpp
// To run: ./ReverseName.bin
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
# include <iostream>
# include <string.h>
using namespace std;

//Delaire Variables
int X,Y,NameLength;
char Name[40],Number[40],Soundex[4];

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void shift()
{
    for (Y=X;Y<NameLength;Y++)
        Number[Y]=Number[Y+1];
    return;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int main()
{
    //Input
    cout<<"What is your last name? ";
    cin>>Name;
    //Calculations
    NameLength=strlen(Name);
    for (X=0;X<NameLength;X++) Name[X]=toupper(Name[X]);
    for (X=0;X<NameLength;X++)
        switch(Name[X])
        {
            case 'B':
            case 'F':
            case 'P':
            case 'V':Number[X]='1'; break;
            case 'C':
            case 'G':
            case 'K':
            case 'J':
            case 'Q':
            case 'S':
            case 'X':
            case 'Z':Number[X]='2'; break;
            case 'D':
            case 'T':Number[X]='3'; break;
            case 'L':Number[X]='4'; break;
            case 'M':
            case 'N':Number[X]='5'; break;
            case 'R':Number[X]='6'; break;
            case 'H':
            case 'W':Number[X]='7'; break;
            default: Number[X]='0';
        }
    for (X=0;X<4;X++) Soundex[X]='0';
    Soundex[0]=Name[0];
    //Output
    cout<<"Your last name converted is ";
    for (X=0;X<NameLength;X++) cout<<Number[X];
    cout<<".\n";
    for (X=0;X<NameLength;X++)
        if(Number[X]==Number[X+1])
            shift();
    cout<<"Your last name shifted is ";
    for (X=0;X<NameLength;X++) cout<<Number[X];
    cout<<".\n";


    cout<<"Your Soundex code is: ";
    for (X=0;X<4;X++) cout<<Soundex[X];
    cout<<".";
    cin.get();
    cin.get();
	return 0;
}
After line 67 you need a loop like on line 57 where you set Soundex[X+1] = Number[X];.

How do you want to reduce Number from 40 to 3?
Coder777, your input has helped out substantially but for some reason the output isn't shifting over for example we're supposed to get C160 but instead we're getting C201, CNoob2 and I are working on fixing this issue but if you have any input that would be great.
Well, Number[40] -> Soundex[4]

In the worst case scenario NameLength=40, but you want to store only three of this potential 40 digits. So how is this mapping done?

Using only first three digits or something?
Ok this is what we got
// ReverseName.cpp
// By Gage Haldey
// Copyright 2018
// Licensed under the terms of the GPL 3
// To compile: g++ -o ./ReverseName.bin ./ReverseName.cpp
// To run: ./ReverseName.bin
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
# include <iostream>
# include <string.h>
using namespace std;

//Delaire Variables
int X,Y,NameLength;
char Name[40],Number[40],Soundex[4];

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void shift()
{
for (Y=X;Y<NameLength;Y++)
Number[Y]=Number[Y+1];
return;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int main()
{

//Input
cout<<"What is your last name? ";
cin>>Name;
//Calculations
NameLength=strlen(Name);
for (X=0;X<NameLength;X++) Name[X]=toupper(Name[X]);
for (X=0;X<NameLength;X++)
switch(Name[X])
{
case 'B':
case 'F':
case 'P':
case 'V':Number[X]='1'; break;
case 'C':
case 'G':
case 'K':
case 'J':
case 'Q':
case 'S':
case 'X':
case 'Z':Number[X]='2'; break;
case 'D':
case 'T':Number[X]='3'; break;
case 'L':Number[X]='4'; break;
case 'M':
case 'N':Number[X]='5'; break;
case 'R':Number[X]='6'; break;
case 'H':
case 'W':Number[X]='7'; break;
default: Number[X]='0';
}
for (X=0;X<4;X++) Soundex[X]='0';
Soundex[0]=Name[0];
//Output
cout<<"Your last name converted is ";
for (X=0;X<=NameLength-1;X++) cout<<Number[X];
cout<<".\n";
Number[0]=0;
Number[X]=Number[X-1];
for (X=0;X<NameLength;X++)
{
if (Number[X]=='0') shift();
}
cout<<"Your last name shifted is ";
for (X=0;X<NameLength;X++)
{
cout<<Number[X];
}
for (X=0;X<5;X++) Soundex[X+1]=Number[X];
cout<<".\n";
cout<<"Your Soundex code is: ";
for (X=0;X<5;X++) cout<<Soundex[X];
cout<<".";
cin.get();
cin.get();
return 0;
}
To copy the first three digits the loop should be:

for (X=0;X<3;X++) Soundex[X+1]=Number[X]; // Note: 3 otherwise it is out of bounds

So does it do what you want?

Actually the shift() function looks wrong (due to the Y+1 it is also may be out of bounds). What are you trying to do there?
Can you state your phonetic rules? H and W are supposed to be removed in Soundex, not allocated the number 7.

Here's one implementation: I don't know how correct it is.

Can you also state the input name (presumably starting with a C) that you believe gave the wrong answer.

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;
   }
}

Last edited on
Topic archived. No new replies allowed.