## Separate the list implementation from the main translation unit: Currently, the list can not be used in any other program. Move it to a separate source file and include its corresponding header in the main program. ## Define `main()` at the end of the translation unit: If we define `main()` at the end, we wouldn't require all the forward declarations of the functions. ## Extra arguments to `main()`: `fileOpener()` checks whether at least 2 arguments were provided to the program, but what when more than 2 are provided? Currently, one can pass around `INT_MAX` arguments to the program. ## Prefer standard exit status values to non-standard ones: Use `EXIT_FAILURE` and `EXIT_SUCCESS` from `stdlib.h` to signify failure and success respectively. ## Eliminate redundant function calls: ``` fseek(file, 0, SEEK_SET); ``` does nothing at the beginning of `calculate()`, as the file position indicator is already at the beginning of the file. As of the second call, it can be replaced with `rewind(file)`. ## Read the file in large chunks: Currently you're reading it byte by byte, and whilst that has the benefit of not having to allocate anything, reading it in bigger chunks (4-64 Kib) should prove to be faster. ## Use `sizeof *ptr` instead of `sizeof (type)` in calls to `malloc()` and family: ```c #if 0 Node *node = calloc(1, sizeof(Node)); #else Node *node = calloc(1, sizeof *node); #endif ``` It will reduce maintenance headaches if you ever change the type of `node`.