I am having trouble sorting a dirent struct in C. I have tried everything and cannot get the values of my struct array to appear in my comparison. My code looks like this:
void printSortedNames(){
struct dirent **file_list = (dirent**)malloc(5 * sizeof(dirent*));
int i = 0;
for (i = 0; i < directory_size; ++i){
file_list[i] = (dirent*)malloc(50 * sizeof(dirent));
}
DIR *dir;
struct dirent *sd;
dir = opendir(".");
if (dir == NULL){
printf("Error! unable to open directory.\n");
exit(1);
}
int count = 0;
while ((sd = readdir(dir)) != NULL){
file_list[count] = sd;
printf("%s\n", file_list[count]->d_name);
++count;
}
size_t file_list_size = sizeof(&file_list) / sizeof(struct dirent);
qsort(file_list, file_list_size, sizeof(struct dirent), sizeCompare);
}
I have created a simple function sizeCompare to show that my function is working but I get null values. My function looks like:
int sizeCompare(const void* a, const void* b){
printf("%s\n", ((const struct dirent*)a)->d_name);
}
Can someone explain to me why my sizeCompare is not retrieve the array values correctly?
UPDATE:
I have tried playing around with the size in the qsort and my value as a result was no longer null. the following line gives me an output:
qsort(file_list, 1000, sizeof(struct dirent), sizeCompare);
Obviously 1000 is not a good solution. Does anybody know the correct size for an array like this?
UPDATE 2:
sizeCompare function only takes the first parameter and the second one is null.
int sizeCompare(const void* a, const void* b){
const struct dirent *first_dirent = *(const struct dirent **) a;
const struct dirent *second_dirent = *(const struct dirent **) b;
.......
//first one works but second one is NULL
}
In the comparison function you need to dereference the pointers by first casting to struct dirent **, like this
const struct dirent *first_dirent = *(const struct dirent **) first_parameter;
this is because the address of each element is passed and since elements are pointers, the pointers passed to the funcion are pointers to pointers. Their void * addresses are the same, but you can't cast const struct dirent ** directly to const struct dirent *.
You have another important problem this,
file_list_size = sizeof(&file_list) / sizeof(struct dirent);
is wrong, try to print the value and see and it should be1
file_list_size = count;
because your code computes the size of a pointer divided by the size of struct dirent which is probably resulting in 0, read about the sizeof operator, it's result depends on the passed argument. When it's a variable, the size of the type is the result, when the variable is an array it's the size of the array.
Since file_list is a pointer to pointer, i.e. Not an array, then the result of
file_list_size = sizeof(&file_list) / sizeof(struct dirent);
is not what you think it is or what it should actually be.
There is no correct size, perhaps you should count the entries first and predict a value for the first malloc() in your code. Or use realloc() and dynamically count the entries and allocate the poitners simultaneously.
Also:
Your code leaks memory as pointed out by #user3629249 in this comment
You don't need to cast the return value from malloc()
Try not to mix code with declarations, it makes it hard to track variables and their scope.
You allocate space for 5 struct dirent * pointers but you never check for the count variable whether it reached or went beyond that value. That could lead to undefined behavior.
Your code also leaks memory because you never call closedir().
Here is an example of alphabetically sorting the entries
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
int
compareSize(const void *const A, const void *const B)
{
return strcmp((*(struct dirent **) A)->d_name, (*(struct dirent **) B)->d_name);
}
void printSortedNames(const char *const path)
{
int count;
DIR *dir;
struct dirent **list;
struct dirent *entry;
dir = opendir(path);
if (dir == NULL)
{
fprintf(stderr, "cannot open `%s'\n", path);
return;
}
/* First determine the number of entries */
count = 0;
while ((entry = readdir(dir)) != NULL)
++count;
/* Allocate enough space */
list = malloc(count * sizeof(*list));
if (list == NULL)
{
closedir(dir);
fprintf(stderr, "memory exhausted.\n");
return;
}
/* You don't need to allocate the list elements
* you can just store pointers to them in the
* pointer array `list'
*/
rewinddir(dir); /* reset position */
/* Save the pointers allocated by `opendir()' */
count = 0;
while ((entry = readdir(dir)) != NULL)
list[count++] = entry;
/* Call `qsort()', read about the `sizeof' operator */
qsort(list, count, sizeof(*list), compareSize);
/* Print the sorted entries now */
for (int index = 0 ; index < count ; ++index)
fprintf(stderr, "%s\n", list[index]->d_name);
closedir(dir);
}
int
main(void)
{
printSortedNames("/home/iharob");
return 0;
}
1Remember to limit the value of count to the maximum number of pointers you allocated space for.
Your sizeCompare function is not returning anything. You need to implement is such that it returns -1 when a < b, 0 when a = b and 1 when a > b.
int sizeCompare(const void* a, const void* b) {
// The implementation should return something
}
Also, you're calculating the file_list_size incorrectly. Can't you pass count as the second argument instead?
qsort(file_list, count, sizeof(struct dirent), sizeCompare);
Related
I'm working on a function that works as part of a larger program. My C pointer skills are a bit rusty and so I need some help here.
I keep getting segmentation fault errors, and I feel like there is a very trivial solution to my question, and any explanation would help!
Essentially, I have an empty array of structs that I need to pass through to a function as a double pointer. That function will open and read a file saving the contents of the file in the array of structs.
I need to pass it as a double pointer.
This is what I have so far:
struct node{
int first_value;
int second_value;
};
unsigned char readFunction(char *fileName, int *limit, struct node **arrayToFill){ //Many more variables passed, but I removed it for the sake of simplicity
FILE *input;
input = fopen(fileName, "r");
if (input == NULL) {
printf("error: could not read the input file!\n");
}
int i=0;
int temp1, temp2;
for(i=0; i<(*limit); i++){
fscanf(input, "(%d, %d)", &temp1, &temp2);
(*(arrayToFill+i))->first_value = temp1;
(*(arrayToFill+i))->second_value= temp2;
}
//More code
return 0; //Actually returns another array but that's irrelevant.
}
int main(){
//NOTE: I just created these variables for the sake of showing it on StackOverflow, I still get a Segmentation Fault error when I run the program.
char name[9] = {'t', 'e', 's', 't', '.', 't','x','t', '\0'};
struct node arrayToPass[10];
struct node *pointer = &arrayToPass;
struct node **data = &pointer;
unsigned char returnedVal;
int limit = 10;
returnedVal = readFunction(&name, &limit, data);
return 0;
}
Thanks in advance!
You have several problems. The first is you are using the arrayToPass[10] pointer incorrectly, all you need is:
int main (void) {
struct node arrayToPass[10];
int limit = 10;
printf ("return: %hhu\ncontent:\n", readFunction(NULL, &limit, &arrayToPass));
for (int i = 0; i < limit; i++)
printf ("%5d %5d\n",
arrayToPass[i].first_value, arrayToPass[i].second_value);
}
Do not attempt to cast around your struct node (*arrayToPass)[10] pointer when you pass the address by assigning to different pointers. You begin with type struct node [10] (array of struct node [10]) when you take the address you have struct node (*)[10] (pointer to array of struct node [10]). It is separate and district from struct node ** (pointer to pointer to struct node).
Your function then takes the type struct node (*arrayToFill)[10], e.g.
unsigned char readFunction (char *fileName, int *limit, struct node (*arrayToFill)[10])
{ //Many more variables passed, but I removed it for the sake of simplicity
FILE *input;
input = fileName ? fopen (fileName, "r") : stdin;
if (input == NULL) {
printf("error: could not read the input file!\n");
}
int i=0;
int temp1, temp2;
while (i < *limit && fscanf(input, " (%d, %d)", &temp1, &temp2) == 2) {
(*arrayToFill)[i].first_value = temp1;
(*arrayToFill)[i].second_value = temp2;
i++;
}
*limit = i;
return 0; //Actually returns another array but that's irrelevant.
}
(note: the use of the ternary operator allowing NULL to be passed as fileName to read from stdin -- that was just for my convenience)
(also note: that since you declare struct node arrayToPass[10]; with automatic storage duration in main(), you don't need to pass the address of the pointer, you only need to pass the address of the pointer if the address can changes in your function -- such as if you call realloc on the pointer. The other answer addresses that point.)
The difference between needing to pass struct node ** or struct node (*)[10] or simply struct node * boils down to how memory is allocated for the original collection. If as you have done, declaring struct node arrayToPass[10]; in main() with automatic storage duration, storage for the array is fixed. On access, the array is converted to a pointer (struct node *) and you can simply pass the array itself as the parameter. (but you are limited to no more than the number of elements originally declared)
If however, you have an allocated storage type for arrayToPass in main (e.g. struct node *arrayToPass = malloc (10 * sizeof *arrayToPass);, then if you need to change the amount of storage, e.g. the number of stuct node that your allocated block of memory can hold in readFunction(), then you must pass the address of the pointer, so if reallocation takes place, and the beginning address for your block of memory changes, that change will be seen back in the caller (main() here). In that case when you pass the address of struct node *, then your type becomes struct node **. (because you have taken the address of a pointer instead of the address of an array)
Since your arrayToPass can't be reallocated, and the storage is fixed before it is passed to readFunction(), you don't need to pass the address and you can eliminate one level of pointer indirection and just pass the array as type struct node *. That simplifies access in your function to simply arrayToFill[i].first_value = temp1;, the [..] acting as a dereference of the pointer, just as -> does.
You also may want to change the return type from unsigned char to size_t and return the number of elements filled in your struct (a meaningful return) -- or you can update the limit pointer as I did -- your choice.
The complete example is:
#include <stdio.h>
struct node {
int first_value;
int second_value;
};
unsigned char readFunction (char *fileName, int *limit, struct node (*arrayToFill)[10])
{ //Many more variables passed, but I removed it for the sake of simplicity
FILE *input;
input = fileName ? fopen (fileName, "r") : stdin;
if (input == NULL) {
printf("error: could not read the input file!\n");
}
int i=0;
int temp1, temp2;
while (i < *limit && fscanf(input, " (%d, %d)", &temp1, &temp2) == 2) {
(*arrayToFill)[i].first_value = temp1;
(*arrayToFill)[i].second_value = temp2;
i++;
}
*limit = i;
return 0; //Actually returns another array but that's irrelevant.
}
int main (void) {
struct node arrayToPass[10];
int limit = 10;
printf ("return: %hhu\ncontent:\n", readFunction(NULL, &limit, &arrayToPass));
for (int i = 0; i < limit; i++)
printf ("%5d %5d\n",
arrayToPass[i].first_value, arrayToPass[i].second_value);
}
Example Input File
$ cat dat/2x8rand.txt
(17987, 1576)
(12911, 4488)
(30688, 5875)
(25617, 16643)
(8999, 26249)
(29270, 31857)
(8954, 2094)
(21390, 27676)
Note the change in the fscanf format-string including an additional ' ' (space) before the opening parenthesis '(' to consume the '\n' (and any leading whitespace). You cannot use any input function correctly unless you check the return (e.g. fscanf(input, " (%d, %d)", &temp1, &temp2) == 2)
Example Use/Output
$ ./bin/ptrtoarraystruct < dat/2x8rand.txt
return: 0
content:
17987 1576
12911 4488
30688 5875
25617 16643
8999 26249
29270 31857
8954 2094
21390 27676
Look things over and let me know if you have further questions.
I believe you may want something like the following.
#include <stdio.h>
struct node{
int first_value;
int second_value;
};
unsigned char readFunction(char *fileName, int limit, struct node *arrayToFill){ //Many more variables passed, but I removed it for the sake of simplicity
FILE *input;
input = fopen(fileName, "r");
if (input == NULL) {
printf("error: could not read the input file!\n");
}
int i=0;
int temp1, temp2;
for(i=0; i<limit; i++){
fscanf(input, "(%d, %d)", &temp1, &temp2);
arrayToFill[i].first_value = temp1;
arrayToFill[i].second_value = temp2;
}
//More code
return 0; //Actually returns another array but that's irrelevant.
}
int main(){
//NOTE: I just created these variables for the sake of showing it on StackOverflow, I still get a Segmentation Fault error when I run the program.
char name[9] = "test.txt";
struct node arrayToPass[10];
unsigned char returnedVal;
int limit = 10;
returnedVal = readFunction(name, limit, arrayToPass);
return 0;
}
As the title says i want to pass structure to function and allocate memory, maybe it's a stupid question but i can't find the answer..
structName *allocate_memory( int *numPlayers,structName )
{
structName *retVal = malloc( sizeof(struct structName) * (*numPlayers) );
return retVal;
}
The problem is in parameters structName what should go there?
if you need the full code i can post it but i think there is no need..
You can't pass in a type as a parameter. But you can pass in its size:
void *allocate_memory( int *numPlayers, size_t struct_size)
{
void *retVal = malloc( struct_size * (*numPlayers) );
if (!retVal) {
perror("malloc failed!");
exit(1);
}
return retVal;
}
Then call it like this:
struct mystruct *s = allocate_memory(&numPlayers, sizeof(struct mystruct));
Or you just do this instead, assuming you want the memory initialized to all 0:
struct mystruct *s = calloc(numPlayers, sizeof(struct mystruct));
You can use a void pointer there, void can take anything...hope it helps....
You have two options, the first returning a new pointer (see allocate_memory) and the second is to fill in an existing pointer (see allocate_memory2. In both cases I converted numPlayers to int because it isn't necessary to provide by reference
struct structName *allocate_memory(int numPlayers)
{
struct structName *retVal = malloc(sizeof(struct structName) * numPlayers);
return retVal;
}
void allocate_memory2(struct structName **target, int numPlayers)
{
*target = malloc(sizeof(struct structName) * numPlayers);
}
int main(int argc, char** argv)
{
struct structName *str;
struct structName *str2;
//After this line str is a valid pointer of size 20*sizeof(struct structName)
str = allocate_memory(20);
//After this line str2 is a valid pointer of size 20*sizeof(struct structName)
allocate_memory2(&str2, 20);
}
You cannot pass a type as a parameter to a function.
You basically have two options realizing your allocate_memory function:
Instead of passing the name of the type simply pass the size of the type:
void *allocate_memory( int *numPlayers, size_t size). But this is only a trivial wrapper for malloc.
You could write a macro #define allocate_memory(num, type) (malloc(num * sizeof(type))) to do the job.
Maybe you're looking for a combination of both if you want to track some statistics of the memory allocated or do additional checks:
#define allocate_memory(num, type) (my_malloc((num), sizeof((type))))
void *my_malloc(int num, size_t size)
{
void *pMem = malloc(num * size);
if (pMem == NULL)
{
/* do error handling */
}
return (pMem);
}
You can use the above macro as follows:
pInt = allocate_memory(5, int); // allocates 5 integers
pStruct = allocate_memory(10, some_struct); // allocates 10 some_structs
I've looked enough about this problem on this site and still haven't found a solution.
I have an array of struct, and I want to read from a file some records and store them in the structs. The problem is the allocation of the memory.
This is the struct I use:
struct Rec{
int mat;
char *nome;
char *cognome;
};
typedef struct Rec* Record;
This is the readFromFile function:
void readFromFile(char* fileName, Record** data, int* pn)
{
char line[LINE_LENGTH];
int n, i;
char* token;
printf("\n\nReading file %s\n", fileName);
FILE* fin = fopen(fileName, "r");
if (fin == NULL)
{ printf("Error readinf file\n");getch();
goto end;
}
n = 0; // first read to know the number of lines
while (fgets(line, LINE_LENGTH, fin) != NULL) n++;
n = (n < MAX_LENGTH ? n : MAX_LENGTH);
printf("N: %d\n", n);
*pn = n;
//Then I allocate the memory for the n lines I previously read
*data = (Record*)malloc(n * sizeof(Record));
if(*data == NULL){
printf("Problem allocating memory\n");
exit(0);
}
i = 0;
for(i = 0; i < n; i++){
(*data)[i].nome = malloc(sizeof(char) * MAX_LENGTH + 1);
if((*data)[i]->nome == NULL){
printf("Problem allocating memory\n");
exit(1);
}
//Here comes the problem, the allocation of the second string fails and the program exit
(*data)[i]->cognome = malloc((sizeof(char) * MAX_LENGTH + 1));
if((*data)[i]->cognome == NULL){
printf("Problem allocating memory\n");
exit(2);
}
}
rewind(fin);
n = 0;
while (fgets(line, LINE_LENGTH, fin) != NULL && n < MAX_LENGTH)
{
token = strtok(line, ";");
strcpy((*data)[n]->nome, token);
token = strtok(line, ";");
strcpy((*data)[n]->cognome, token);
token = strtok(line, ";");
(*data)[n]->mat = atoi(token);
n++;
}
fclose(fin);
end:return;
}
I've tried to modify the structure and the code in many ways but have not found a solution, I think that probably is a pointer problem but I can't figure it out. The readFromFile function was provided from the professor and was built to read int from file and I had to modify it to read records.
There's a big difference between:
(*data)[i].nome = malloc(sizeof(char) * MAX_LENGTH + 1);
and:
(*data)[i]->cognome = malloc((sizeof(char) * MAX_LENGTH + 1));
The first line with the dot notation used, is implying, access to a member of a struct, whereas the -> implies accessing a member of a struct using pointer notation, i.e. pointer to a structure.
The confusion is showing there, as (*data) is a pointer to a struct of type Record which is a type definition of Rec.
typedef struct Rec* Record;
Since data when stripped down, is type definition of Record, aliased to a pointer to struct of Rec. The double pointer as part of parameter, which will be modified through pass by reference, is declared, after determining the number of lines in input dataset, as an array of pointers:
*data = (Record*)malloc(n * sizeof(Record));
Accessing the member data, for each entry in the array would be:
(*data)[i] dot name_of_member
The rule would have changed, had the type definition be like this:
typedef struct Rec Record;
i.e. a normal struct, no pointer usage.
Then access to the member data would have been, if allocation was achieved,
(*data)[i]->name_of_member
However, do not try hide pointers behind a typedef as that will give grief, come back to the code again in the future, and wondering why it failed, the hidden pointer has bitten you!
Record is defined as
typedef struct Rec* Record;
therefore it is pointer to struct Rec. malloc returns pointer to allocated memory (or NULL) but you cast this to pointer to pointer
*data = (Record*)malloc(n * sizeof(Record));
// = Rec**
I have narrowed a segmentation fault down to the specific line of code causing it. Here is a straightforward example showing the issue I am having.
int main()
{
char** files;
int sum;
int i;
DIR *d;
struct dirent *dir;
d = opendir(".");
if (d)
{
sum = file_sum();
char* files[sum];
i = 0;
while ((dir = readdir(d)) != NULL)
{
files[i] = dir->d_name;
i++;
}
closedir(d);
}
else
{
return -1;
}
int len = strlen(files[0]); /*segmentation fault here*/
return 0;
}
Essentially what the program is doing is taking the names of all of the files from the current directory and putting them into an array. I am then going to try to get the sizes of all of the file names, but I have been getting a segmentation fault. My theory is that perhaps the file names are not null-terminated? If this is true, I am unsure of a workaround for that, but any assistance is appreciated.
Thanks
EDIT: Sorry I had an error here. The segmentation fault only occurs when I try to store the strlen return value, as I have now changed the code to above
Inside of your if block, you're defining a variable named files. This masks the variable of the same name at the top of the function. It is not specifying the size of the array at the higher scope, which seems to be your intent. So when you exit the if block, the inner files goes out of scope, and the outer files is left uninitialized. You then dereference the uninitialized pointer, causing the core dump.
What you want to do is dynamically allocate the necessary memory inside of the if block for the memory you need.
Also, the directory name retrieved into dir->d_name probably gets overwritten on each call to readdir, so you need to allocate space for that as well.
EDIT:
You also don't need a separate function to get the file count. You can allocate the array with a default size and realloc to expand as needed:
int main()
{
char** files;
int sum;
int i;
DIR *d;
struct dirent *dir;
d = opendir(".");
if (d)
{
int size = 10;
sum = 0;
files = malloc(size * sizeof(char *)); // allocate the array
if (files == NULL) {
perror("malloc failed");
exit(1);
}
while ((dir = readdir(d)) != NULL)
{
if (sum >= size) {
// if the array is full, realloc twice the size
char **tmp;
size *= 2;
tmp = realloc(size * sizeof(char *));
if (tmp == NULL) {
perror("realloc failed");
exit(1);
}
files = tmp;
}
files[sum] = strdup(dir->d_name); // allocate and copy each string
sum++;
}
closedir(d);
}
else
{
return -1;
}
strlen(files[0]);
// free the individual strings
for (i=0; i<sum; i++) {
free(files[i]);
}
// free the array
free(files);
return 0;
}
Using "char* files[sum]" is only safe under 2 conditons:
you not trying to access the array after the end of it's declaration range: you shouln't try to access the "files" array after the end of the "if" where it's declared
that char* target need to be safely reserved. It's reasonnable to assume that the target is valid right after dir->d_name but after having closed the d DIR it's pretty risky
Here's a simple fix if you know how many files there can be in your directory : copying the dirent struct to dirList is the simplest but it's quite a big struct. You can also copy only a pointer to the dirent using "dirListPtr" but you need to be sure that your dirent struct is still valid. That's why i have put "closedir" a bit farther down.
If you're not sure about the number of files, dynamic allocation is the way to go (see dbush answer). If you want to use the data in another function, allocation is required too.
#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
#include <string.h>
int main()
{
int sum;
int i;
DIR *d;
struct dirent* dir;
// you must be sure to have less than 255 files
struct dirent dirList[255];
struct dirent* dirListPtr[255];
d = opendir(".");
if (d)
{
i = 0;
while ((dir = readdir(d)) != NULL)
{
// copy the dirent information to our local variable which will live until the end of the main
dirList[i] = *dir;
// or keep only a pointer to the dirent struct: the system will surely not discard the dirent at least as long as d is open
dirListPtr[i] = dir;
i++;
}
}
else
{
return -1;
}
printf("size of filename: %lu size of dirent %lu\n", strlen(dirList[0].d_name), sizeof(dirList[0]));
printf("size of filename: %lu\n", strlen(dirListPtr[0]->d_name));
closedir(d);
return 0;
}
size of filename: 2 size of dirent 280
size of filename: 2
I made an array of Node structs and I am trying to sort nodes in alphabetical order based on their char* variable called "word".
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "memwatch.h"
#include "concord.h"
#define BUFFSIZE 1000
int main(int argc, char** argv)
{
Node** list;
printf("%s%s\n","The file name is ", argv[1]);
readInputFile(argv[1], list);
return 0;
}
int compareWords(const void* nodeA, const void* nodeB)
{
Node* nodeAA = (Node *) nodeA;
Node* nodeBB = (Node *) nodeB;
puts("now here\n");
printf("%s\n", nodeAA->word);
printf("%s\n", nodeBB->word);
return strcmp(nodeAA->word, nodeBB->word);
}
void readInputFile(char* filename, Node** wordList)
{
FILE* file;
file = fopen(filename, "r");
wordList = calloc(BUFFSIZE, sizeof(Node*));
char* currentWord;
currentWord = (char*) malloc(sizeof(char) *BUFFSIZE);
int i;
i = 0;
while(fscanf(file, "%s", currentWord) == 1)
{
wordList[i] = (Node*) malloc(sizeof(Node));
wordList[i]->word = strdup(currentWord);
puts(wordList[i]->word);
}
fclose(file);
qsort(wordList, i, sizeof(Node), compareWords);
}
Before I was printing out garbage when I tried to print out the word in the compare function, now it looks like the function is not even being called.
now it looks like the function is not even being called.
That is because to sort a list of 0 elements you never need to compare two elements:
// ...
int i;
i = 0; // --- set to 0
while(fscanf(file, "%s", currentWord) == 1)
{
// i not changed ... causes other problems, too
// (contents omited)
}
fclose(file);
// i is still 0
qsort(wordList, i, sizeof(Node), compareWords);
// ...
Apart from that your usage of an "out parameters" is wrong, as pointed out in the comment by David C. Rankin. In this case, i'd also advise to just use the return value.
Moreover, I'd split that function into multiple functions:
// Does the file opening and closing, calls readInput
Node * readInputFile(char const *);
// The actual reading
Node * readInput(FILE *)
// Probably do the sorting outside of these functions
[First of all you question is incomplete as it misses to show us the definition of Node.]
However, three issues here:
I made an array of Node structs
You don't.
Here
wordList = calloc(BUFFSIZE, sizeof(Node*));
you allocate memory for an array of pointers to Node.
And then here
wordList[i] = (Node*) malloc(sizeof(Node));
you allocated a separate chunk of memory to each element of the pointer array created previously.
The latter may be scattered all over the process's memory. They will not be located in a continous block of memory, as expected by qsort(), which might have been the reason for:
I was printing out garbage [before]
On returning from readInputFile() the value of wordList is lost.
The reading loop does not increment the index counter i.
To fix 1. and 2. create an array and return a reference to it back up to the caller of readInputFile() like so
*wordList = calloc(BUFFSIZE, sizeof **wordList);
and call qsort() like this:
qsort(*wordList, i, sizeof(Node), compareWords);
To fix 3. do this:
size_t i = 0; /* No need for negative indexes here .*/
while((i < BUFFSIZE) /* Male sure not to overflow the array. */
&& (fscanf(file, "%s", currentWord) == 1))
{
(*wordList)[i].word = strdup(currentWord); /* This is POSIX not Standard C. */
puts((*wordList)[i].word);
++i;
}