Hello,

I'm new to C programming, taking a course in college on System Architecture. Anyways, I'm required to submit a project, and I have to build it using gcc -ansi. When I run the following command:

gcc wordstat.c -ansi wordstat

it generates the following output:

wordstat.c: In function `main':
wordstat.c:316: parse error before `char'
wordstat.c:317: `newline' undeclared (first use in this function)
wordstat.c:317: (Each undeclared identifier is reported only once
wordstat.c:317: for each function it appears in.)
wordstat.c:329: parse error before `*'
wordstat.c:333: `dictionaryHead' undeclared (first use in this function)
wordstat.c:334: `textHead' undeclared (first use in this function)
wordstat.c:337: `pointer' undeclared (first use in this function)
wordstat.c: In function `checkArgument':
wordstat.c:382: parse error before `*'
wordstat.c:383: `fp' undeclared (first use in this function)


My code looks fine to me, I don't understand why I'm getting these errors. Thank you so much for your help! Below here I've included the contents of the files being compiled.


The files being used are wordstat.c and wordstat.h. Here are there contents:


WORDSTAT.C file:
Code:
/* wordstat.c : Defines the entry point for the console application.*/

#include "wordstat.h"

/*inserts a new node with data = nodeData to the head of the list*/
void insertBeginning(WORD **listHead, char nodeData[100])
{
	WORD *temp;
	if(*listHead == NULL) /*no head, create a new word and make listHead point to it*/
	{
		temp = (WORD *)malloc(sizeof(WORD));
		strcpy(temp->data, nodeData);
		temp->nextNode = NULL;
		*listHead = temp;
	}
	else /*make a new word, point its next to head, and then point listHead to the new word*/
	{
		temp = (WORD *)malloc(sizeof(WORD));
		strcpy(temp->data, nodeData);
		temp->nextNode = *listHead;
		*listHead = temp;
	}
}

/*This function takes two char* arrays, compares there characters one at a time until a difference is found and returns the result*/
int compareWords(char *word1, char *word2)
{
	char word1Char;
	char word2Char;
	int counter = 0;
	int returnValue; /*if < 0, wta is smaller, if > 0 wta is larger, if = 0 the words are the same*/

	word1Char = word1[counter];
	word2Char = word2[counter];

	while(word1Char != 0 || word2Char != 0)/*loop over the arrays looking for a difference, stop if we hit the end of a word*/
	{
		returnValue = word1Char - word2Char;

		if(returnValue != 0)
		{
			return returnValue; /*we've found a difference, so lets return it*/
		}

		/*no difference so increment our counter and set the next characters to examine*/
		counter++;
		word1Char = word1[counter];
		word2Char = word2[counter];
	}

	/*if we reach here, then one of the values is null, so we need to handle what to return*/
	returnValue = word1Char - word2Char;

	return returnValue;
}

/*search for the word in the dictionary.  If it is found, return 1, else return 0*/
void checkDictionary(WORD *word, WORD *dictionaryHead)
{
	int comparisonValue;
	WORD *pointer = dictionaryHead;
	
	while(pointer != NULL) /*loop over the list*/
	{
		comparisonValue = compareWords(word->data, pointer->data); /*see if the word matches a word in dictionary*/
		if(comparisonValue == 0)/* we have a match*/
		{
			word->inDictionary = 1; /*set the flag that shows the word was in the dictionary*/
			return;
		}

		pointer = pointer->nextNode;
	}

	/*if we reach this point, then the word was not found in the dictionary*/
	word->inDictionary = 0;
	return;
}




/*inserts a new word into the linked list sorting by the data value.  If word matches another word, increments the count instead of adding*/
WORD* insertSort(WORD **listHead, WORD **wordToAdd)
{
	WORD *previous;
	WORD *current = *listHead;
	WORD *word = *wordToAdd;
	int loopCounter = 0; /*needed to make sure we don't access previous if previous isn't set*/
	int difference = 0;
	
	while(current != NULL) /*we haven't reached the end of the list yet, keep looping*/
	{
		if(loopCounter == 0)
		{
			difference = compareWords(word->data, current->data);
			if(difference < 0) /*word comes before current*/
			{
				word->nextNode = current;
				return word;
			}
			else if(difference > 0) /*word comes after current, advance pointer*/
			{
				previous = current;
				current = current->nextNode;
			}
			else /*word is the same as current*/
			{
				current->count = current->count + word->count;
				free(word);
				return *listHead;
			}			
		}
		else /*using previous is fine*/
		{
			difference = compareWords(word->data, current->data);
			if(difference < 0) /*word comes before current*/
			{
				previous->nextNode = word;
				word->nextNode = current;
				return *listHead;
			}
			else if(difference > 0) /*word comes after current, advance pointer*/
			{
				previous = current;
				current = current->nextNode;
			}
			else /*word is the same as current*/
			{
				current->count = current->count + word->count;
				free(word);
				return *listHead;
			}	
		}

		loopCounter++;
	}

	/*if we reach here, then the word goes on the end of the list*/
	previous->nextNode = word;
	word->nextNode = NULL;

	return *listHead;
}

/*take the head of a list and print all of the words in the list, with collums for word, count and inDictionary*/
void printWordList(WORD *listHead) 
{
	WORD *pointer;
	pointer = listHead;
	printf("\nWORDS\t\t\tFREQUENCIES\t\tIN DICTIONARY?\n");

	while(pointer != NULL)
	{
		printf(pointer->data);
		printf("\t\t\t");
		printf("%i", pointer->count);
		printf("\t\t\t");
		if(pointer->inDictionary == 1)
		{
			printf("Y\n");
		}
		else
		{
			printf("N\n");
		}

		pointer = pointer->nextNode;
	}
}


/*this function takes no parameters, reads the dict.txt file, creates a linked list of all the words in the dict.txt file, 
and returns a pointer to the head of the list.  This function is better for reading the dictionary than readText() because
we can grab the whole line at once (based on the formatting of the dictionary file), so we don't have to read one character
at a time.*/
WORD* readDictionary()
{
	/*declare local variables*/
	WORD *headPtr;
	WORD *current;
	int wordCount = 0;
	char readBuffer[100];

	FILE *fp = fopen("dict.txt", "rb"); /*open the dict.txt file*/

	if(fp == NULL)/*if the file failed to open, print out warning message and return headPtr*/
	{
		printf("Failed to open dict.txt.  Please make sure the dictionary file is present.");
		return headPtr;
	}

	while(fgets(readBuffer, 99, fp) != NULL) /*while loop to read each line of the dictionary file*/
	{
		int bufferCounter = 0;
		char bufferChar = readBuffer[bufferCounter];

		/*we need to find the end of the word in the buffer, so we can set the following character to 0*/
		while(bufferChar > 64 && bufferChar < 91) /*this is a character I want to keep*/
		{
			bufferCounter++;
			bufferChar = readBuffer[bufferCounter];
		}
		readBuffer[bufferCounter] = 0; /*need to set character after last letter = 0*/

		/*if we're creating the first word in the dictionary, we'll just handle that here.  Else use insertBeginning*/
		if(wordCount == 0)
		{
			headPtr = (WORD *)malloc(sizeof(WORD));
			strcpy(headPtr->data, readBuffer);
			headPtr->nextNode = NULL;
		}
		else
		{
			insertBeginning(&headPtr, readBuffer);
		}
		wordCount++;
	}

	fclose(fp);

	return headPtr;
}

/*reads the given text file, creates a linked list of WORD, and returns pointer to head of the linked list*/
WORD* readText(char *fileName)
{
	/*declare local variables*/
	char *readBuffer = (char*)malloc(sizeof(char[100]));
	char readCharacter;
	int wordCounter = 0;
	int characterCounter = 0;
	WORD* textHead;
	WORD* newWord;
	FILE *fp = fopen(fileName, "rb");

	readCharacter = getc(fp);
	while(readCharacter != EOF)
	{
		if(readCharacter > 64 && readCharacter < 91) /*character is a capital alphabetic character, and should be added to read buffer*/
		{
			readBuffer[characterCounter] = readCharacter;
			characterCounter++;
		}
		else if(readCharacter > 96 && readCharacter < 123) /*character is a lowercase alphabetic character and should be converted to upper and added to read buffer*/
		{
			readBuffer[characterCounter] = readCharacter - 32;
			characterCounter++;
		}
		else if (characterCounter > 0) /*we have read in a non alphabetic character with alphabetic characters in the readBuffer.  We have reached the end of a word.  Add the word to the words array.*/
		{
			if(wordCounter == 0)/*this is our first word*/
			{
				readBuffer[characterCounter] = 0;
				textHead = (WORD*)malloc(sizeof(WORD));
				strcpy(textHead->data, readBuffer);
				textHead->nextNode = NULL;
				textHead->count = 1;
				textHead->inDictionary = 0;
			}
			else /*this is a new word, needs to be inserted into our linked list*/
			{
				readBuffer[characterCounter] = 0;
				newWord = (WORD*)malloc(sizeof(WORD));
				strcpy(newWord->data, readBuffer);
				newWord->nextNode = NULL;
				newWord->count = 1;
				newWord->inDictionary = 0;
				textHead = insertSort(&textHead, &newWord);
			}

			/*reset our buffer and increment our wordCounter*/
			free(readBuffer);
			readBuffer = (char*)malloc(sizeof(char[100]));
			characterCounter = 0;
			wordCounter++;
		}
		/*if we reached none of these ifs, we have read in a non alphabetic with no alphabetic characters in the readBuffer, so do nothing and move on to next character*/

		/*read the next character*/
		readCharacter = getc(fp);
	}

	/*we've reached EOF.  Close file and return.	*/
	fclose(fp);
	return textHead;
}


int main(int argc, char *argv[])
{
	char inputBuffer[100]; /*for reading input from user if original arguments are invalid*/
	int sentry = 1; /*used to make sure we don't advance until the arguments are valid*/
	if(argc < 2) /*we have too few arguments*/
	{
		sentry = 1; /*sentry != 0 means we have a problem with the arguments*/
	}
	else if(argc == 2) /*lets check and see if our arguments are valid*/
	{
		sentry = checkArgument(argv[1]);
	}
	else /*we have too many arguments*/
	{
		sentry = 1;
	}

	if(sentry == 0) /*our arguments are good, lets copy them to inputBuffer for use*/
	{
		strcpy(inputBuffer, argv[1]);
	}

	while(sentry != 0) /*our arguments were bad, so lets get the user to give proper input*/
	{
		printf("Please enter the filename for the text file to process, or enter -h for help.  Press Enter to exit: ");
		fgets( inputBuffer, sizeof(inputBuffer), stdin);
		char *newline = strchr(inputBuffer, '\n');
		if(newline != NULL)
		{
			*newline = '\0';
		}
		sentry = checkArgument(inputBuffer);
		if(sentry == -1)/*user entered '0', so they wish to exit.*/
		{
			return 0;
		}
	}

	/*ok, we're done checking for valid arguments, we have one, lets process!*/
	WORD *dictionaryHead;
	WORD *textHead;
	WORD *pointer;

	dictionaryHead = readDictionary(); /*read the dictionary into a linked list of words*/
	textHead = readText(inputBuffer); /*read the text file into a linked list of words*/

	/*check if each word from the text is in the dictionary, and set its inDictionary value accordingly*/
	pointer = textHead;
	while(pointer != NULL)
	{
		checkDictionary(pointer, dictionaryHead);
		pointer = pointer->nextNode;
	}

	printWordList(textHead); /*print our output*/

	/*time to free all the stuff we dynamically allocated*/
	while(dictionaryHead != NULL)
	{
		WORD *freePointer = dictionaryHead;
		dictionaryHead = dictionaryHead->nextNode;
		free(freePointer);
	}
	
	while(textHead != NULL)
	{
		WORD *freePointer = textHead;
		textHead = textHead->nextNode;
		free(freePointer);
	}

	return 0;
}

/*this function will check if our arguments were valid.  If so, returns 0.  If user wants to exit returns -1.  Else returns 1.*/
int checkArgument(char *arg)
{
	if(arg[0] == 0) /*the user wants to exit.*/
	{
		return -1;
	}

	if(arg[0] == 45 && arg[1] == 104) /*we have a -h, lets check to make sure that is -h by itself, and if it is, print out the help string.*/
	{
		if(arg[2] == 0)
		{
			printf("\nwordstat.exe is an executable that will take in a single argument, which is a file name to a text document.  When given a valid filename, wordstat will read the text file, compare it against the dictionary in dict.txt, and print out the words in alphabetical order, with frequency and whether the word is in the dictionary.\n\n");
		}
		return 1; /*we're not done getting input from user*/
	}

	/*if we got here then input wasn't 0 and wasn't -h, so we check to see if we can open the file*/
	FILE *fp = fopen(arg, "rb");
	if(fp == NULL) /*we couldn't open the file*/
	{
		printf("\nError opening the indicated file.\n\n");
		return 1;
	}
	fclose(fp); /*we could open the file.  So close it for now, and return 0 to prepare for processing*/

	return 0;
}
WORDSTAT.H file:
Code:
/* wordstat.h : include file for standard system include files,
 or project specific include files that are used frequently, but
 are changed infrequently*/


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

typedef struct word
{
	int count; /*how many times was this word in the document*/
	int inDictionary; /*0 for NO, 1 for YES*/
	char data[100]; /*string holding the word*/
	struct word *nextNode; /*pointer to next word in the linked list*/
}
WORD;

int checkArgument(char *arg);