如何在字符串数组中查找重复的字符串

时间:2011-10-14 06:50:01

标签: c string

我有一个字符串数组,我必须找到重复的字符串,然后删除那个重复的字符串,就像我有字符串

 char aa[50]="Amit Hanish Mahesh Amit"

现在Amit是重复的,必须从字符串中删除它。

#include "string.h"
main()
{
  char x[100] = "Amit Hanish Mahesh Amit";
  char y[3][100];
  int i = 0, k = 0, j = 0, c = 0, end, t;
  int current = 1;
  while (x[i] != '\0') {
    if (x[i] != ' ') {
      y[k][j] = x[i];
      j++;
      i++;
    } else {
      // c = c + 1;
      i++;
      k++;
      j = 0;
    }
    y[k][j] = '\0';
  }

  for (end = 1; end <= 3; end++) {
    for (t = 0; t < end; t++) {
      if (strcmp(y[end], y[t]) == 0) break;
    }
    if (end == t) {
      strcpy(y[current],y[t]);
       current++;
    }
  }
  y[current] = 0;
  printf("%s",y);
}

我为它编写了一个小例程。似乎没有工作。任何人都有任何建议我哪里出错?

6 个答案:

答案 0 :(得分:3)

你得到的其他答案对于少数字符串工作正常(你的示例代码只有4个)。但是,如果你比较一个大数字,这将是非常缓慢的,因为你正在进行n ^ 2比较。我建议首先将字符串拆分为字符串数组,然后使用qsort()对数组进行排序。在排序的数组中,所有重复项都保证是相邻的。这减少了从n ^ 2到n log n的时间 - 排序所需的时间。

答案 1 :(得分:2)

我会使用strtok拆分字符串数组(参见手册页)。

所以我会有类似的东西

char x[100]="Amit Hanish Mahesh Amit";

/* Preparing the result string */
size_t sz_result = sizeof(char) * (strlen(x) + 1);
char* result = (char*) malloc( sz_result );
result[0] = '\0';

/* Parsing the string from one element to the other */
char* elm = strtok(x, " ");
while( (elm = strtok(NULL, " ")) != NULL )
{
  ...

您将拥有字符串的每个元素以验证它们是否唯一。

然后我会使用类似hashmap的东西(你可以使用glib中的那个)或者只有当它不在时才将读取字符串元素放在一个新字符串中。

以下是第二个解决方案的示例:

  ...
  /* Is the element already in the result string? */
  if ( strstr(result, elm) == NULL )
  {
    /* Then we should add it */
    snprintf( result, sz_result - 1, "%s %s", result, elm );
  }
}

最后,如果要修改x,只需将结果复制到x:

即可
strncpy( x, result, 99 );

这是一个示例代码(未优化,不使用strn *原语等)

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


int main()
{
  char x[100]="Amit Hanish Mahesh Amit";

  /* Preparing the result string */
  size_t sz_result = sizeof(char) * (strlen(x) + 1);
  char* result = (char*) malloc( sz_result );
  result[0] = '\0';

  /* Parsing the string from one element to the other */
  char* elm = strtok(x, " ");
  if (elm != NULL) strcpy(result, elm);
  while( (elm = strtok(NULL, " ")) != NULL )
  {
    /* Is the element already in the result string? */
    if ( strstr(result, elm) == NULL )
    {
      /* Then we should add it */
      strcat( result, " " );
      strcat( result, elm );
    }
  }

  strcpy( x, result );

  fprintf( stdout, "Result: %s\n", x );
}

答案 2 :(得分:1)

要从数组中删除重复项而不保留元素的顺序:

  1. 对数组进行排序
  2. 将唯一元素复制到数组的开头
  3. 删除带有重复元素的尾部
  4. int remove_duplicates(StringArray array) {
      if (! (array and array->items)) return 0; // empty array or NULL
    
      StringArray_sort(array); // sort
    
      // unique_copy()
      String result = array->items, last = array->items + array->size;
      for (String first = array->items; first != last; ++result) {
        String_copy(result, first); // copy first to result
        for (String prev = first; ++first != last and String_cmp(prev, first) == 0;)
          { /* skip adjacent equal items */ }
      }
      // shrink
      return StringArray_remove(array, result, last);
    }
    

    实施例

    int main() {
      char text[] = "Mahesh Amit  Hanish Amit";
      StringArray array = split(text, sizeof(text));
      StringArray_dump(array, "<"); // print array before removing duplicates
      if (remove_duplicates(array) < 0)
        perror("error remove_duplicates(), OS error if any");
      StringArray_dump(array, ">"); // print it after
      StringArray_destroy(array);
      return 0;
    }
    

    split()的位置:

    StringArray split(const char* text, size_t size) {
      if (! (text and text[size-1] == '\0')) return NULL;
    
      StringArray array = StringArray_create();
      if (! array) return NULL;
    
      size_t n = -1;
      for (const char* p = text; p != text+size; p += n+1) {
        n = strcspn(p, " \t\n"); // find index of the next whitespace
        if (n == 0) continue; // skip consecutive whitespace
    
        // append characters in range [p, p+n)
        // as a string to the array
        const String string = String_create(p, n);
        if (StringArray_append(array, string) < 0) {
          String_destroy(string);
          StringArray_destroy(array);
          return NULL;
        }
        String_destroy(string);
       }  
      return array;
    }
    

    输出

    Mahesh<Amit<Hanish<Amit<
    Amit>Hanish>Mahesh>
    

    Full source code

答案 3 :(得分:0)

我很确定,以下行不是预定的(分配,而不是比较)

 if (end = t) {

看看会发生什么,如果你编码==然后回来,如果你还有问题。

提示:始终在运算符周围编码空白,因此表达式更易于阅读。

答案 4 :(得分:0)

尝试在C中解决这种简单的问题作为练习总是很有趣。这是我的看法。

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

char* strstrn(const char *haystack, const char *needle, size_t needle_len)
{
    while((haystack = strchr(haystack, *needle)))
    {
        if (strncmp(haystack, needle, needle_len) == 0)
            return (char *) haystack;
        haystack++;
    }
    return NULL;
 }

char* find_duplicate(const char* str, size_t len, size_t dup_len)
{
    for(size_t i = 0; i < (len - dup_len); i++)
    {
        char* r = strstrn(str + i + 1, str + i, dup_len);
        if(r) return r;
    }
    return NULL;
}

int main(int argc, char** argv)
{
    if(argc < 3)
    {
        fprintf(stderr, "Usage: %s haystack dup_size\n", argv[0]);
        return 1;
    }
    char* haystack = argv[1];
    size_t len = atoi(argv[2]);
    char* r;
    while((r = find_duplicate(haystack, strlen(haystack), len)))
    {
        strcpy(r, r + len);
    }
    puts(haystack);
    return 0;
}

答案 5 :(得分:0)

/* 
 * C Program to Find the Frequency of  Every Word in a 
 * given String
 */
#include <stdio.h>
#include <string.h>

void main()
{
    int count = 0, c = 0, i, j = 0, k, space = 0;
    char str[100], p[50][100], str1[20], ptr1[50][100];
    printf("Enter the string\n");
    scanf(" %[^\n]s", str);
    printf("string length is %d\n", strlen(str));
    for (i = 0;i<strlen(str);i++)
    {
        if ((str[i] == ' ')||(str[i] == ', ')||(str[i] == '.'))
        {
            space++;
        }
    }
    for (i = 0, j = 0, k = 0;j < strlen(str);j++)
    {
        if ((str[j] == ' ')||(str[j] == 44)||(str[j] == 46))  
        {    
            p[i][k] = '\0';
            i++;
            k = 0;
        }        
        else
             p[i][k++] = str[j];
    }
    k = 0;
    for (i = 0;i <= space;i++)
    {
        for (j = 0;j <= space;j++)
        {
            if (i == j)
            {
                strcpy(ptr1[k], p[i]);
                k++;
                count++;
                break;
            }
            else
            {
                if (strcmp(ptr1[j], p[i]) != 0)
                    continue;
                else
                    break;
            }
        }
    }
    for (i = 0;i < count;i++) 
    {
        for (j = 0;j <= space;j++)
        {
            if (strcmp(ptr1[i], p[j]) == 0)
                c++;
        }
        printf("%s -> %d times\n", ptr1[i], c);
        c = 0;
    }
}