如何在C语言中从字符串数组中删除重复字符串。

3

我正在尝试制作一个程序,其中有一个链表,其中包含不同的城市名称和其他无关紧要的内容。城市名称为“Seattle, Boston, New York, Seattle, Washington, Boston”之类。我的目标是创建一个仅包含唯一城市名称的数组。所以对于给定的例子,它应该是这样的:“Seattle, Boston, New York, Washington”。

我的想法是先制作一个字符串的原始数组,在其中包含所有重复的数据,然后遍历每个城市并使其所有其他出现的地方变为“NULL”。但由于某种原因,它无法正常工作,我不知道为什么。

此外,如果您们能够提供简单版本的解决方案,我将不胜感激。

这是我的代码:

void city_list(City *head)
{
    City *temp = head;

    char** names_raw;
    char** names_new;
    int num_names = 100;
    int curr_pos = 0;

    names_raw = malloc(num_names * sizeof(char*));

    for(int i = 0; i < num_names; i++)
    {
        names_raw[i] = malloc(256 * sizeof(char));
    }

    while(temp != NULL)
    {
       
        strcpy(names_raw[curr_pos++], temp->name);

        temp = temp->next;
    }

    names_new = malloc(num_names * sizeof(char*));

    for(int i = 0; i < num_names; i++)
    {
        names_new[i] = malloc(256 * sizeof(char));
    }

    for(int i = 0; i < curr_pos; i++)
    {
        if(strcmp(names_raw[i], "NULL"))
        {
            for(int j = i+1; j < curr_pos; j++)
            {
                if(!strcmp(names_raw[j], names_new[i]))
                {
                    strcpy(names_raw[j], "NULL");
                }
            } 

            strcpy(names_new[i], names_raw[i]);
        }
    }

    for(int i = 0; i < curr_pos; i++)
    {
        printf("%s\n", names_new[i]);
    }

    free(names_raw);
    free(names_new);
}

当我调试代码时,没有出现任何错误,但它打印出了所有城市,就好像数组中没有做任何处理一样。


首先,重要的事情说三遍,为了实现你想要的功能,你真的不需要复制这些字符串两次……对吧?其次,我希望你确定名称短于256个字符,否则你的代码存在多种缓冲区溢出的可能性。更安全的复制方式是使用strncpy() - Marco Bonelli
@MarcoBonelli 我知道这些名称比256个字符短,但在我得到的任务中,他们明确要求使用最多256个字符的字符串,我已经做到了。 - michael368
1
问题出在第二个strcmp中,它将raw[j]new[i]进行比较。此时代码中的new[i]为空。一旦你解决了这个问题,下一个问题就是执行strcpy的过程中将raw[i]复制到了new[i]。应该将其复制到new[k]中。 - user3386109
1个回答

0

您没有给出完整的示例(“City”是什么?您的输入数组是如何构建的?等等)。但我怀疑您正在使事情过于复杂:(

建议:

  1. Pass your array into a function named int delete_dupes(char* arr[], int n) (or similar)

  2. Sort the array:

    EXAMPLE CODE: https://www.geeksforgeeks.org/c-program-sort-array-names-strings/

  3. "Delete" the duplicates by moving them to the front of your array

    int delete_dupes(char* arr[], int n) {
      char *current_name = arr[0];
      int i=1, j=1;
      while (i < n) {
        if (strcmp(arr[i], current_name) != 0) {
          free(arr[j]);  /* Do *NOT* do this if you didn't malloc() this string!!!! */
          arr[j++] = arr[i];
          current_name = array[i];
        }
      }
      return j;
    }
    
  4. The function returns the new #/strings. That number will be <= n.

    Additionally, you may want to null out the unused array elements and/or free the duplicate string values.

  5. An "ideal" solution would be for you to implement a dynamic list.

  6. If you want to "malloc()" each string individually, please consider the standard C library function strdup() .

“而且,不,我还没有测试过 :)”

如果城市名称不在同样大小的缓冲区中,strcpy 就无法实现你想要的功能。但是你甚至不需要 strcpy;你可以直接赋值(并确保必要时释放被覆盖的元素)。 - Moonchild
好的点子 - 示例已修改。但未编译或测试 ;) - paulsm4

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接