i wanted to find the duplicates present in an array of pointers.the code is shown below.when i run this application it is gining segmentation fault.But when i extract this function,i am able to run it just fine.Can anyone please tell me what could `
when i detect the duplicates,i just put those strings to a file named 开发者_如何学Coutput.txt.
i discovered that when strcmp is used,its giving this segmentation fault. but when i extract this function and run it on some test code,it works really fine.
main()
{
char *a[20];
DIR *dip;
int i = 0;
dip = opendir("src/my_folder");
char *condition_var;
while ((dit = readdir(dip)) != NULL)
{
condition_var = dit->name;
a[i] = condition_var
i++;
}
findduplicates(a,i);
}
char *findduplicates(char *arr[3],int count)
{
int i = 0;
int j = 0;
int val = 0;
FILE *output = fopen("output.txt","w");
for(i = 0;i<count;i++)
{
j = i+1;
for(;j<count;j++)
{
if(strcmp(arr[i],arr[j])==0)
{
printf("The index of a duplicate elemnt is %d\n",j);
arr[j] = " ";
}
}
}
int k = 0;
while(k<3)
{
printf("the aarray is %s\n",arr[k]);
fputs(arr[k],output);
fputs("\n",output);
k++;
}
}`
advanced thanks Maddy
char *a[20]; // an array of char pointers. 20 elements in the array.
char *findduplicates(char *arr[3],int count)
// arr is an array of char pointers, with 3 elements in the array.
findduplicates(a, count); // this will just pass 3 of the 20 pointers
// thus when you try to access a[3], it will probably seg-fault.
try this instead:
char *findduplicates(char **arr,int count)
[edit]
Maybe I'm wrong about this. I just wrote a small test program, and it wouldn't crash even if declared the function parameter as char *a[0]
. But try my suggestion anyway. Memory bugs don't always make stuff crash...
I wrote something that will find the duplicates in an arbitrary string array and print out the names. I can't tell from your question if you specifically needed the indexes from the original array. This version will sort the array and the original indexes are "lost". But if you only need to know the names which are duplicates, the following should work:
#include <string.h>
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
#define TRUE 1
#define FALSE 0
/* Compare function for quicksort. Shamelessly taken directly from linux man
* page */
static int cmpstringp(const void *p1, const void *p2)
{
return strcmp(* (char * const *) p1, * (char * const *) p2);
}
void find_duplicates(char *strings[], size_t size)
{
size_t i, j, last_occurrence;
int is_unique;
for(i = 0; i < size; ++i)
{
/* This variable tells us if the current element is unique */
is_unique = TRUE;
for(j = i; j < size; ++j)
{
/* Make sure we aren't comparing the element to itself */
if((j != i) && (strcmp(strings[i], strings[j]) == 0))
{
/* Since the array is sorted, we store the index of the last
* duplicate and continue our search from there.
*/
last_occurrence = j;
is_unique = FALSE;
}
}
/* The element was not unique, print the name */
if(is_unique == FALSE)
{
printf("Duplicate: %s\n", strings[i]);
/* Set the counter to the next element we must check for
* "uniqueness" */
i = last_occurrence;
}
}
}
int main(int argc, char *argv[])
{
/* Test array */
char *test_array[] = { "test1", "test2", "test3", "test1",
"test4", "test1", "test4" };
/* Sort it using quicksort to make the process of finding duplicates
* easier
*/
qsort(test_array, 7, sizeof(char*), cmpstringp);
find_duplicates(test_array, 7);
return 0;
}
I think this part would be the root of the problem:
while ((dit = readdir(dip)) != NULL)
{
condition_var = dit->name;
a[i] = condition_var;
i++;
}
I am not sure about how readdir() works but I would guess that every time it will return a temporal structure pointer to dit. a[i] saves condition_var as the pointer to the name. It is possible that later another call to readdir() is made and uses the exact the same mem space to return the temporal structure, overwriting the mem space that a previous condition_var pointing to.
I would suggest a safer way to do this part, which may be a little more complex, though.
while ((dit = readdir(dip)) != NULL)
{
int len = strlen(dit->name);
condition_var = malloc(len+1);
memncpy(condition_var, dit->name, len+1);
//condition_var = dit->name;
a[i] = condition_var;
i++;
}
Remember to free every mem block that you malloced, at the end of the program. (Or you can just leave all these to OS to collect the mem--not recommended). The code should be like this:
int j; // use another loop indicator if you already declared j for other uses.
for(j = 0; j<i; j++) // i is the length of a[].
{
free(a[j]);
// no worry about a[j] being NULL. free() does nothing on a NULL pointer.
a[j] = NULL;
}
精彩评论