查找2个字符串是否来自相同单词的函数

时间:2013-12-02 15:37:10

标签: c arrays string words

我需要在C中创建一个函数,它可以找出2个字符串是否来自相同的单词。从当前代码中可以看出,我将每个字符串加载到单独的数组中。我发现在数组中有单词,全部是小写字母,每个单词之间只有1个空格,没有所有非字母字符。我虽然,我可以对字符串进行排序并在它们上调用strcmp,但不能这样做,因为有原因,可以有“狗狗狗猫”和“狗猫”这样的字符串,这些字符串来自相同的单词,因此函数应返回1,但如果只是排序并使用strcmp则不会。所以我虽然,我可以合并所有重复的单词1然后排序和strcmp,但仍然有一个问题,当有像“狗”和“上帝”这样的词,这些是2个不同的单词,但功能排序后仍然会将它们视为相同。 “狗狗狗猫”“狗猫” - 同样的话 “HI HeLLO !!'”“嗨,,,你好嗨” - 同样的话 我会非常感谢任何帮助。我真的不知道如何创造它,我坐了很长时间,仍然无法想象它。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

int sameWords( const char * a, const char * b)
{
char * array1=NULL;
char * array2=NULL;
int length1=0, length2=0, i=0, j=0;
while(a[i])
  {
  if(i>=length1)
    {
      length1+=250;
      array1=(char*)malloc(length1*sizeof(char));
    }
  if(isspace(a[i]) && !isspace(a[i-1]))
    {
      array1[i]=a[i];
    }
  if(isalpha(a[i]))
    {
      array1[i]=tolower(a[i]);
    }
  i++;
  }
while(b[j])
  {
  if(j>=length2)
    {
      length2+=250;
      array2=(char*)malloc(length2*sizeof(char));
    }
  if(isspace(b[j]) && !isspace(b[j-1]))
    {
      array2[j]=b[j];
    }
  if(isalpha(b[j]))
    {
      array2[j]=tolower(b[j]);
    }
  j++;
  }
}

int main()
{
sameWords("This' is   string !!! ", "THIS stRing is !!  string ");
return 0;
}

4 个答案:

答案 0 :(得分:0)

您从函数sameWords返回任何内容,其返回类型为int

答案 1 :(得分:0)

我不会假装被授予答案,但我也会为这类事情看一下正则表达式。

Does C or C++ have a standard regex library?

解决它需要几分钟,你用正则表达式分割字符串,小写它,然后迭代来查看常用单词。

答案 2 :(得分:0)

我要解决此问题的方法是创建一个像树一样的数据结构,您可以在其中插入单词。如果单词已经存在,则insert函数将不执行任何操作,否则,它会将其转换为小写并将其插入树中。然后你可以简单地将两个字符串转换为这些类型的树并比较树。

另一种方法是使用bash。虽然这可能不允许你分配,但如果你理解它的工作方式和原因,你应该能够编写模仿它的代码:

# string1 and string2 are simply strings with spaces separating words
s1="dog dog dog cat"
s2="cat dog"

# Convert to arrays
a1=( $(printf "%s\n" ${s1}  | sort | uniq ) )
a2=( $(printf "%s\n" ${s2}  | sort | uniq ) )

# Compare the result
if [ "${a1[*]}" == "${a2[*]}" ] ; then
  echo "Same"
fi

答案 3 :(得分:0)

您已经了解了两种解决问题的方法。复杂的是将每个字符串拆分成单词,对它们进行排序,然后清除重复数据,这在排序数组中很容易。更容易的是将第一个字符串拆分为单词,在第二个字符串中搜索每个单词。然后以相反的方式做同样的事情:拆分第二个并检查第一个中的单词。

这两种方法都要求您拆分字符串。这也是你似乎在代码中遇到问题的地方。 (你有基本的想法来查看单词边界,但你似乎不知道如何存储单词。)

基本问题是:你如何表示单词,即C字符串的子串?有各种方式。您可以将指针与字符串长度一起使用到字符串中,也可以将它们复制到另一个缓冲区中。

这是一个将字符串a拆分为单词然后检查是否可以在b中找到每个单词的单词:

/*
 *      Return 1 if all words in a can be found in b, 
 *      return 0 otherwise.
 */
int split_and_check(const char *a, const char *b)
{
    int begin = -1;    /* marker for beginning of word */
    char word[80];     /* temporary buffer for current word */
    int prev = 0;      /* previously read char to detect word bounaries */
    int len;           /* current length of word */
    int i;

    i = 0;
    while (1) {
        if (isalpha(a[i])) {
            if (!isalpha(prev)) {
                begin = i;
                len = 0;
            }
            if (len < 80) word[len++] = a[i];
        } else {
            if (len > 0) {
                word[len] = '\0';       /* manually null-terminate word */

                if (strstr(b, word) == NULL) {
                    /* fail on string mismatch */
                    return 0;
                }
                len = 0;                /* reset word-length counter */
            }
        }
        if (a[i] == '\0') break;        /* check end here to catch last word */
        prev = a[i++];
    }

    return 1;
}

当前单词存储在本地字符缓冲区word中,长度为len。请注意在'\0'搜索word之前,如何手动将零结束标记b添加到word:库函数strstr在另一个中查找字符串。两个字符串都必须以零结尾。

这只是解决方案的一半。你必须反过来检查字符串:

int same_words(const char *a, const char *b)
{    
    if (split_and_check(a, b) == 0) return 0;
    if (split_and_check(b, a) == 0) return 0;

    return 1;
}

这还不是您问题的确切解决方案,因为字符串匹配是区分大小写的。我已经跳过了这一部分,因为它更容易:strstr区分大小写,我不知道任何忽略这种情况的变体。