[英]Deleting string from array of strings (C)
我有一个指针数组(char **),其中包含一些字符串。 数组以空字符串('\\ 0')结尾。 我应该在该字符串数组中搜索特定单词并删除整行(ofc使用realloc并缩短字符串数组)。 我很难做到这一点,我不断收到'糟糕的ptr'错误。
我的代码:
void deleteSentence(char **text){
char *word,*fptr;
int i=0;
word=(char*)calloc(BUFFER,sizeof(char));
printf("Enter word to delete sentences:\n");
gets(word);
while(text[i][0]!='\0'){
char *str=(char*)malloc((strlen(text[i])+1)*sizeof(char));
strcpy(str,text[i]);
fptr=strtok(str,DELIM);
while(fptr!=NULL){
if(strcmp(fptr,word)==0){
int j=i;
while(text[j][0]!='\0'){
text[j]=(char*)realloc(text[j],(strlen(text[j+1]))*sizeof(char));
strcpy(text[j],text[j+1]);
j++;
}
free(text[j]);
}
fptr=strtok(NULL,DELIM);
if(fptr!=NULL)
i++;
}
}
}
非常感谢:)
你的记忆就像一个筛子漏水,并且至少在两个地方超过你的阵列。 此外,输入与此代码的功能目的的集成实际上没有任何帮助。 该函数应该只做一件事,一件事:
给定指向以空字符串(或NULL)结尾的
char*
指针数组的指针,删除指针数组中包含单词的所有字符串。 生成的可能压缩的数组是函数的返回值。
考虑一下:
char ** deleteSentances(char **text, const char *word)
{
char **dst = text, **src = text, **res = text;
size_t size = 1, deleted = 0;
// loop while we have a non-null string that isn't empty
while (*src && (*src)[0])
{
char *tmp = strdup(*src);
if (tmp == NULL)
{
perror("Failed to allocate tmp");
exit(EXIT_FAILURE);
}
char *token = strtok(tmp, DELIM);
// search for matching word
while (token && strcmp(word, token))
token = strtok(NULL, DELIM);
// if not found, keep the string. otherwise delete it.
if (!token)
{
*dst++ = *src++;
size++;
}
else
{
free(*src++);
++deleted;
}
// don't need this.
free(tmp);
}
// resize the original array (which could have only gotten smaller)
if (deleted > 0)
{
res = realloc(text, size * sizeof(*res));
if (res == NULL)
{
perror("Failed to allocate res");
exit(EXIT_FAILURE);
}
res[size-1] = *src;
}
return res;
}
希望这足以解释。 代码被调用如下:
char **text, *word;
//... populate text with strings
//... populate word with prospect word
text = deleteSentances(text, word);
记忆泄漏了O'Festival
OP希望了解原始发布算法中内存泄漏的位置。 首先考虑以下几点:对于每个分配,应该有一个已知的点,即释放那个记忆。 这个例子有点难以说明这个概念,因为你正在为函数带来动态分配,而其中一些将被保留。
也就是说,请考虑以下景点。 我们假设在某种程度上我们分配了这种形式的指针数组:
char **text = malloc(N * sizeof(*text));
即我们有N
角色点。 在每一个中,我们进一步假设字符串的动态分配也已经发生:
for (int i=0; i<(N-1); ++i)
{
//... compute length of next string
text[i] = malloc(length * sizeof(**text));
//... copy in next string to text[i]
}
最后, text
数组中的最后一个字符指针是NULL或指向长度为0的动态字符串(即0长度的终止字符串)。
呼。 好。 毕竟,让我们看看你的算法:
void deleteSentence(char **text)
{
char *word,*fptr;
int i=0;
// Leak 1: allocate a single buffer of BUFFER-length.
// this is never freed anywhere in this function
word=(char*)calloc(BUFFER,sizeof(char));
printf("Enter word to delete sentences:\n");
// Problem: gets() is so evil and bad it has been deprecated from
// the C langage and will not be available in the next release.
// use fgets() instead.
gets(word);
while(text[i][0]!='\0')
{
// Leak 2: Done N times, where N is the number of strings in
// your original array. again, this is never freed.
char *str=(char*)malloc((strlen(text[i])+1)*sizeof(char));
strcpy(str,text[i]);
fptr=strtok(str,DELIM);
while(fptr!=NULL)
{
if(strcmp(fptr,word)==0)
{
int j=i;
while(text[j][0]!='\0')
{
// Leak 3: Done M-N times for ever string we find in position
// M of the original array. This can be *huge* if there are
// a decent number of number of reductions that crunch your
// original array down.
text[j]=(char*)realloc(text[j],(strlen(text[j+1]))*sizeof(char));
strcpy(text[j],text[j+1]);
j++;
}
// Problem: this just freed the termination string, which should
// never be done. We now have undefined behavior for the rest
// of this algorithm since the terminatingg string is invalid.
free(text[j]);
// Problem: You shoud break right here. See below for why
}
// Problem: you're missing an else condition here. At this point
// if the strcmp() found a match there is no reason to continue
// the loop. You found a match and deleted the string, crunching
// all the other string down one slot in a most-inefficient
// memory-leaking algorihm.
fptr=strtok(NULL,DELIM);
// Problem: the logic here is completely wrong. The i in this case
// should be incremented OUTSIDE the inner while loop. Furthermore
// the test is backwards.
if(fptr!=NULL)
i++;
}
}
}
简而言之,如果有可能泄漏更多的内存,那么我很难看到如何。 我提供的发布代码将根据我提供的描述的限制而工作,并且应该仔细查看,甚至通过调试器行y行,以更好地理解它是如何工作的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.