Search code examples
carrayslinked-listdirectoryfree

Where to set my free(); in my C program?


I have created this program which searches through a computer's directory (given an address, i.e. C:\Windows). It stores the file names into linked lists organized in a 26-long array (each slot for a letter of the alphabet).

When I run the program it prints out the file names of folders in repect to the letters I have typed in. However, when I do it for a second time, it prints out the last printouts again along with the new ones.

For example:
Enter Directory Address: C:\Windows
C:\Windows
Enter letters to search by: sy
sy
Symbols
System
System.ini
System32
Enter letters to search by: a
a
addins
appcompat
AppPatch
AppReadiness
AsCDProc.log
Symbols
System
System.ini
System32
Enter letters to search by:

I believe my free(); is in the wrong place. I am wicked new to C, so I'm still learning on how to allocate memory properly. Would someone have any suggestions to help me fix this issue?

Here is my code:

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

//Prototyping
int fileNameBegin(const char *a, const char *b);
void returner(char directory[256], char string[32]);
void print();

//Array of Node Pointer
struct node* arrayOfLinkedLists[26];

//Main
int main() {
    printf("Enter Directory Address:\n");
    char str[256];
    gets(str);
    char letter[32];
    do {
        printf("Enter letters to search by:\n");
        letter[0] = '\0';
        gets(letter);
        returner(str, letter);
        print();

    } while (letter[0] != '\0');
    return 0;
}

//Constructing the Node Struct
struct node{
    char fileName[50];
    struct node *next;
};

//Narrowing Down Search
int fileNameBegin(const char *a, const char *b)
{
    if(strncasecmp(a, b, strlen(b)) == 0) return 1; //not case sensitive, string comparing var a and b with String length
    return 0;
}

#define DATA_MAX_LEN    50

//Adding the node (Files) to the LinkedList in Array
void addFileName(struct node **pNode, const char *c)
{
    while (*pNode)
        pNode = &(*pNode)->next; //It equals the address of the pointer

    *pNode = malloc( sizeof **pNode );

    strncpy((*pNode)->fileName,c,DATA_MAX_LEN-1); //Copying characters from String
    (*pNode)->fileName[ DATA_MAX_LEN-1] = 0;
    (*pNode)->next = NULL;
}

//Opening the Directory. Reading from Directory. Comparing File Name to String and Adding if there's a match
void returner(char directory[256], char string[32])
{
    DIR *pDir = opendir (directory);
    if (pDir)
    {
        struct dirent *pent;
        while ((pent = readdir(pDir)))
        {
            if (pent->d_name[0] == '.' && (pent->d_name[1] == 0 || (pent->d_name[1] == '.' && pent->d_name[2] == 0)))
                continue;

            if(fileNameBegin(pent->d_name, string))
                addFileName(arrayOfLinkedLists + ((int) strlwr(string)[0] - 97), pent->d_name);
        }
        closedir (pDir);
    }
}

//I have no idea what this does.... oh, it displays it, duh.
void print(){
    int i;
    struct node *temp;

    for(i=0 ; i < 26; i++){
        temp = arrayOfLinkedLists[i];
        while(temp != NULL){
            printf("%s\n",temp->fileName);
            temp = temp->next;
        }
    }
    free(temp);
}

Solution

  • After each node print call free() on it and set every array item to NULL

    void print(){
        int i;
        struct node *temp,*printed;
    
        for(i=0 ; i < 26; i++){
            temp = arrayOfLinkedLists[i];
            while(temp != NULL){
                printf("%s\n",temp->fileName);
                printed = temp;
                temp = temp->next;
                free(printed);
            }
            arrayOfLinkedLists[i] = NULL;
        }
    }