使用 C++ 实现 Soundex 算法
Posted
技术标签:
【中文标题】使用 C++ 实现 Soundex 算法【英文标题】:Soundex Algorithm implementation using C++ 【发布时间】:2009-04-22 10:21:13 【问题描述】:简单地说,Soundex 算法将一系列字符转换为代码。产生相同 Soundex 代码的字符被称为发音相同。
代码宽度为 4 个字符 代码的第一个字符始终是单词的第一个字符字母表中的每个字符都属于一个特定的组(至少在本例中,此后的代码是我将坚持的规则):
b, p, v, f = 1 c、g、j、k、q、s、x、z = 2 d, t = 3 l = 4 米,n = 5 r = 6 字母表中的每个其他字母都属于第 0 组。其他值得注意的规则包括:
属于第 0 组的所有字母都将被忽略,除非您提供的单词中的字母已用完,在这种情况下,其余代码将用 0 填充。 同一数字不能连续使用两次或多次,因此该字符被忽略。唯一的例外是上面有多个 0 的规则。例如,单词“Ray”将产生以下 Soundex 代码:R000(R 是所提供单词的第一个字符,a 是第 0 组的一部分,所以它被忽略,y 是第 0 组的一部分,所以它被忽略,没有更多字符,因此代码中剩余的 3 个字符为 0)。
我创建了一个已传递给它的函数 1) 一个 128 个字符的数组,用于创建 Soundex 代码和 2) 一个空的 5 个字符数组,用于在完成时存储 Soundex 代码函数(并通过引用传回,就像大多数数组在我的程序中使用一样)。
但是,我的问题是转换过程。我上面提供的逻辑在我的代码中并不完全有效。我也不知道为什么。
// CREATE A SOUNDEX CODE
// * Parameter list includes the string of characters that are to be converted to code and a variable to save the code respectively.
void SoundsAlike(const char input[], char scode[])
scode[0] = toupper(input[0]); // First character of the string is added to the code
int matchCount = 1;
int codeCount = 1;
while((matchCount < strlen(input)) && (codeCount < 4))
if(((input[matchCount] == 'b') || (input[matchCount] == 'p') || (input[matchCount] == 'v') || (input[matchCount] == 'f')) && (scode[codeCount-1] != 1))
scode[codeCount] = 1;
codeCount++;
else if(((input[matchCount] == 'c') || (input[matchCount] == 'g') || (input[matchCount] == 'j') || (input[matchCount] == 'k') || (input[matchCount] == 'q') || (input[matchCount] == 's') || (input[matchCount] == 'x') || (input[matchCount] == 'z')) && (scode[codeCount-1] != 2))
scode[codeCount] = 2;
codeCount++;
else if(((input[matchCount] == 'd') || (input[matchCount] == 't')) && (scode[codeCount-1] != 3))
scode[codeCount] = 3;
codeCount++;
else if((input[matchCount] == 'l') && (scode[codeCount-1] != 4))
scode[codeCount] = 4;
codeCount++;
else if(((input[matchCount] == 'm') || (input[matchCount] == 'n')) && (scode[codeCount-1] != 5))
scode[codeCount] = 5;
codeCount++;
else if((input[matchCount] == 'r') && (scode[codeCount-1] != 6))
scode[codeCount] = 6;
codeCount++;
matchCount++;
while(codeCount < 4)
scode[codeCount] = 0;
codeCount++;
scode[4] = '\0';
cout << scode << endl;
我不确定这是否是因为我过度使用了 strlen,但由于某种原因,当程序在第一个 while 循环中运行时,实际上没有任何字符被转换为代码(即实际上没有运行任何 if 语句)。
那我做错了什么?任何帮助将不胜感激。
【问题讨论】:
【参考方案1】:代替
scode[codeCount] = 1;
你应该写
scode[codeCount] = '1';
当你形成一个 char 数组时,前者实际上是第一个 ascii 字符,而后者是字符 '1'。
【讨论】:
【参考方案2】:C++ 不支持您似乎正在尝试使用的动态数组。您需要调查 std::string 类的使用。我本质上你的循环变成了这样:
void Soundex( const string & input, string & output )
for ( int i = 0; i < input.length(); i++ )
char c = input[i]; // get character from input
if ( c === .... ) // if some decision
output += 'X'; // add some character to output
else if ( ..... ) // more tests
【讨论】:
我的字符数组有一个确定的长度。我忘了提到这一点(我已经更新了我的问题以反映这一点)。 matchstr 字符数组有 128 个元素,scode 字符数组有 5 个元素。 你应该还在使用 std::string。 虽然我非常感谢您的支持,以及您在回答我的问题时的及时性,但我不能使用我在课堂上尚未涉及的函数或依赖项。非常感谢您的支持。有其他选择吗? 我已经更新了代码以反映大家的建议。但是,它仍然没有做它应该做的事情。 习惯上将作业问题标记为“作业”。这意味着您不会得到诸如“使用您调用 strlen() 时没有在字符串中添加任何空字符终止符。所以 strlen() 的返回值可以是任何东西。您可以通过在开始之前用“\0”填充“scode”来解决此问题,尽管最好有一个单独的计数器并在完成后添加“\0”。
【讨论】:
我听从了您的建议,并为 scode 使用了另一个计数器,而不是使用 strlen(我知道 scode 的长度应该是 4 个字符,这是有道理的)。【参考方案4】:这实际上是一个 C 实现,而不是 C++。无论如何,你确定你的字符串是空终止的吗?否则 strlen 将不起作用。
这些建议可以让您的代码更易于阅读和调试:
在开始之前将您的输入转换为小写。测试非法字符。 定义一个变量,将其设置为 input[matchCount] 并使用它。这将使代码更具可读性。 我建议将 if-else 语句替换为 switch-case 语句。 适应默认情况(不调用 if-else 或 case 语句)【讨论】:
我已经将 scode[4] 等同于 '\0'。谢谢。 matchstr 已经为空终止。现在,我只是得到输入字符串的第一个字符(此后减去乱码......我想这是我不应该阅读的记忆)。但是,仍然没有 soundex 代码。以上是关于使用 C++ 实现 Soundex 算法的主要内容,如果未能解决你的问题,请参考以下文章
比较不同语言的短字符串以获得相似的声音 - Soundex 是答案吗?