如何从 C 中的字符串数组中删除特定字符串?

How to delete a specific string from an array of strings in C?

我需要一个函数来接收指向字符串的指针数组及其大小。 然后它应该寻找那些在数组中出现不止一次的字符串——然后我必须删除它们并重新分配数组。 函数应该 return 数组的新大小。 我正在尝试解决这个问题,但不确定哪里出了问题。

我想将每个要删除的字符串移动到数组的末尾,然后删除它,但不确定 "realloc" 应该在什么时候发生。

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

int DeleteString(char** tab, int n){
    char* check=malloc(sizeof(char)*100);
    int deleted;
    int i,j,g,h;

    for(i=0;i<n;i++){
        strcpy(check, tab[i]);
        for(j=0;j<n;j++){
            if(strcmp(check, tab[j]) == 0){     
                deleted++;
                char* temp = malloc(sizeof(char)*100);
                for(h=j;h<n-1;h++){
                    strcpy(temp, tab[h+1]);
                    strcpy(tab[h+1], check);
                    strcpy(tab[h], temp);       
                }
            }

            if(deleted>0){
                realloc(tab, sizeof(char*)*(n-deleted));
            }
        }
    }
    return n-deleted;
}

目前有"Segmentation fault"错误

SEGMENTATION FAULT 的原因是 tab[0] 存储了存储实际字符串的变量的地址。 这里 tab[i] 处于 for 循环中,因此当它试图获取 tab[1] 本身时内存错误。

for(i=0;i<n;i++){
    strcpy(check, tab[i]);...}

例如:

 char *foo = "something";
 char **ptr2;
 ptr2 = &foo;
 printf("check = %s", *ptr2); 
 for(int i=0;i<9;i++){  
   printf(" check = %c",  ptr2[i]);
 }

输出

check = something check = 4check = �check = pcheck =

实际上这是一个错误。

糟糕,你的代码问题多多,因为你没有遵守C语言的一些主要规则:

  • 每个非静态变量都应初始化(deleted 呢?)
  • 任何被分配的对象都应该被释放(checktemp。)
  • 永远不要更改作为输入参数传递给函数的内容,或者不要期望更改在 return 上可见(tab 由于下一行必须在此处考虑) .
  • 始终分配 realloc 的结果,因为它可能与输入指针 (realloc(tab, sizeof(char*)*(n-deleted));) 不同。

第一个可能是分段错误的原因,因为 deleted 被单元化了,它的值只是不确定的。但所有问题都应该得到解决。

首先,不要忘记初始化像deleted这样的变量,正如其他答案中所说的那样。

接下来,您应该释放内存(因为您正在删除项目)并且您只调用 malloc(3))。这似乎有点反常识,不是吗?

第三,你在循环中进行了大量的字符串复制,而仅仅向上移动指针应该更有效,所以你不需要重新分配字符串元素并复制单元格内容(顺便说一下,您确定这些字符串将作为 malloc()d 个字符串提供给函数吗?我会像您一样假设)

第四,考虑先对数组进行排序,使得所有相似的字符串在数组中都是相邻的。这有一个成本 O(n*log(n)),如果相等(成本 O(n))附加到删除下一个字符串,则总成本 O(n*(log(n)+1))O(n*log(n)) 而不是 O(n^2)是你的实际费用)

一旦排序,只有被删除的字符串应该是 free(3)d,当空洞出现时指针移回数组的开头,最后(当所有完成时)你可以 realloc(3) 指针数组(只有一次,不是每次都通过循环)

重新制作示例超出了本答案的范围,因为它看起来实际上是一些学校练习。对不起。我相信其他提示将帮助您更成功地重试该练习。

并思考:在写作之前思考是一个人在这份工作中取得成功的方式。