/* Title: Assignment 9-1
*  Author: Ben Miller
*
*  This program is  practise for using malloc() and free(). A list is created by using words from
*  an external file.  Then the list is sent to a few functions.  Some data is found and the
*  output is printed out.
*/

#include <stdio.h>

#define MAX 25

typedef struct NodeTag {
	char list_word[MAX];
	struct NodeTag *next;
} Structure;

Structure *add_node (Structure *);
Structure *find_longest (Structure *);
Structure *find_shortest (Structure *, Structure *);
float find_average_length (Structure *);
void delete_list(Structure **);

void main(int argc, char *argv[])
{
	FILE *infile;
	char infilename[MAX];
	char file_word[MAX];
	Structure *Head = NULL, *temp, *new_node, *current;
	Structure *longest, *shortest;
	int first_time = 1;
	char ans[3];
	float average_length;

	/* check command line arguments */
	if (argc < 2) {
                printf("usage: fopen <infilename>\n");
                printf("command line needs two arguements\n");
                printf("Enter your file name: ");
                scanf("%s", infilename);
        }
        else
                strcpy(infilename, argv[1]);

	/* check if file is empty */
	if ((infile = fopen(infilename, "r")) == NULL) {
                fprintf(stderr, "error opening input file %s\n", infilename);
                exit (1);
                }

	/* malloc the first node */
	temp = (Structure *)malloc(sizeof(Structure));
        temp->next = NULL;
        Head = temp;

	/* store words in a linked list */
	while (fscanf(infile, "%s", file_word) != EOF) {
                if (first_time == 1)
                        first_time = 0;
                else {
                        new_node = add_node(Head);
                        temp = new_node;
                }
                strcpy(temp->list_word, file_word);
	}

	/* print the list */
	printf("Here the list of words from %s.\n", infilename);
	current = Head;
	do {
		printf("%s\n", current->list_word);
		current = current->next;
	} while (current != NULL);

	printf("Would you like to know the longest word (Y/N or y/n)? ");
	scanf("%s", ans);
	if (ans[0] == 'Y' || ans[0] == 'y') {
		longest = find_longest(Head);
		printf("%s is the longest word in the list.\n", longest->list_word);
	}

	printf("Would you like to know the shortest word (Y/N or y/n)? ");
	scanf("%s", ans);
	if (ans[0] == 'Y' || ans[0] == 'y') {
		shortest = find_shortest(Head, longest);
		printf("%s is the shortest word in the list.\n", shortest->list_word);
	}

	printf("Would you like to know the average length of the words (Y/N or y/n)? ");
	scanf("%s", ans);
	if (ans[0] == 'Y' || ans[0] == 'y') {
		average_length = find_average_length(Head);
		printf("The average length of the words is %.2f\n", average_length);
	}

	/* free all exsisting nodes */
        delete_list(&Head);
        printf("The list has been cleared succesfully \n");

	exit(1);

} /* end of main */

/* adds a new node to the linked list */
Structure *add_node(Structure *first)
{
        Structure *temp, *L;

        temp = (Structure *)malloc(sizeof(Structure));
        if (first->next == NULL) {
                temp->next = NULL;
                first->next = temp;
                L = temp;
        } else {
                L = first;
                while (L->next != NULL)
                        L = L->next;
                temp->next = NULL;
                L->next = temp;
                L = temp;
        }

	 return(L); /* returning a pointer to the last node */

} /* end add_node */

/* finds the longest word in the list */
Structure *find_longest(Structure *first)
{
	Structure *current, *longest;

	current = first;
	do {
		if (strlen(current->list_word) > strlen(longest->list_word))
			longest = current;
		current = current->next;
	} while (current != NULL);

	return(longest);
}

/* finds the shortest word in the list */
Structure *find_shortest(Structure *first, Structure *longest)
{
	Structure *current, *shortest;

	shortest = longest;
	current = first;
	do {
		if (strlen(current->list_word) < strlen(shortest->list_word))
			shortest = current;
		current = current->next;
	} while (current != NULL);

	return(shortest);
}

/* finds the average length of the words in the file */
float find_average_length (Structure *first)
{
	Structure *current;
	float individual_length, total_length = 0.0;
	float how_many = 0.0, average;

	current = first;
	do {
		individual_length = strlen(current->list_word);
		total_length = total_length + individual_length;
		how_many = how_many + 1.0;
		current = current->next;
	} while (current != NULL);

	return(total_length / how_many);
}

/* delete any nodes left in the list */
void delete_list(Structure **first)
{
        Structure *next_node;

        if ((*first)->next == NULL)
                return;
        else {
                while ((*first)->next != NULL) {
                        next_node = (*first)->next;
                        free(*first);
                        (*first) = next_node;
                }
        }
        free(*first);

        return;
}

