Thread: linked list search and count

  1. #1
    Registered User
    Join Date
    Nov 2010
    Posts
    5

    Exclamation linked list search and count

    Hello all, this is my first post so please for give if I make some type of posting mistake. I am in a programming in C class and have been given an assignment to make a program that opens a file "document.txt" and goes through each word in the list and counts how many of each word is in the file and then prints out the results in order. I have to use the started file that the instructor provide so it has to be done in the way and order that he as specified. It must use a link listed and functions and structs. I have gotten all the functions I am just having a problem with how to retreave the words. I get as far as the first word and that is it.

    Any help I could get would be greatly appreciated

    Here is my code:

    Code:
    // File: LinkedList.c
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <ctype.h>
    
    typedef struct Node {
    	char Word[25];
    	int Count;
    	struct Node *Next;
    };
    
    /* Function Prototypes */
    void GetWord( FILE *fileptr, char word[] );
    struct Node* MakeNewNode( char word[] );
    struct Node* InsertAtBeginning( struct Node *start, struct Node *newptr );
    void InsertInMiddle( struct Node *newptr, struct Node *current, struct Node *previous );
    void PrintList( struct Node *start );
    
    int main() 
    {
    	/* declare and initialize variables */
    	FILE *fileptr;
    	char word[25];
    	struct Node *start = NULL;
    	struct Node *newptr = NULL;
    	struct Node *current = NULL;
    	struct Node *previous = NULL;
    
    	printf("Openning file...\n");
    	if( ( fileptr = fopen( "document.txt", "r" ) ) == NULL )
    	{
    		printf("Unable to open file...\n");
    		return;
    	}
    
    
    	newptr = MakeNewNode(word); // function call for MakeNewNode
    
    	/* read a word from the file */
    	GetWord( fileptr, word);
    	
    	
    	/* read words and process until end of file */
    
    
    	/* Set current pointer to the beginning of the list */
    
    	start = InsertAtBeginning( start, newptr); // fuction call InsertAtBeginning
    				
    	/* Search to see if the word already exists in the list */
    	while(current != NULL && strcmp( current->Word, word) < 0)
    	{
    		current = current->Next;
    		previous=previous->Next;
    	}
    	//if(current == NULL)
    	//else
    
    	if (strcmp (current-> Word, word == 0))
    	{
    		current->Count ++;
    	}
    	else
    	newptr = MakeNewNode;
    	InsertInMiddle( newptr, current, previous );
    
    	
    
    	/* First check to see if it goes before the first word */
    
    	/* check if it matches the first word */
    
    	/* if not at the beginning, it goes in the middle or end */
    
    	/* read next word from the file */
    	GetWord( fileptr, word ); // Function call for GetWord
    	
    	PrintList( start ); // Function call for PrintList
    	printf("\n-------------------------------\n\n");
    	fclose( fileptr );
    	return;
    }// end Main function
    
    ////////////////////////////////// Start Functions ////////////////////////////////////////////
    
    //Fuction Definition for GetWord Function 
    void GetWord( FILE *fileptr, char word[] )// function call for GetWord
    {
    	char tempword[25] = "";
    	int i = 0;
    	fscanf( fileptr, "%s", tempword );
    	if( !feof(fileptr) )
    	{
    		strcpy( word, strtok( tempword, " ,.;:!?-()" ));
    		while( word[i] != '\0' )
    		{	
    			word[i] = tolower(word[i]);
    			i++;
    		}
    		printf( "%s\n", word );
    	}
    	return;
    }// end GetWord Function
    
    // Fuction Definition for InsertAtBeginning Function 
    struct Node* InsertAtBeginning( struct Node *start, struct Node *newptr )          
    {
    	newptr->Next = start;
    	start = newptr;
    	return start;
    }// end InsertAtBeginning Function
    
    // Fuction Definition for InsertInMiddle Function 
    void InsertInMiddle( struct Node *newptr, struct Node *current, struct Node *previous )
    {
    	previous->Next = newptr;
    	newptr->Next = current;
    	return;
    
    }// end InsertInMiddle Function 
    
    // Fuction Definition for MakeNewNode Function 
    struct Node* MakeNewNode( char word[] )
    {
    	struct Node * ptr;
    	ptr = malloc( sizeof ( struct Node ));
    	strcpy( ptr->Word, word);
    	ptr->Count = 1;
    	ptr->Next=NULL;
    	return ptr;
    }// end MakeNewNode Function 
    
    // Fuction Definition for PrintList Function void PrintList( struct Node *start )
    {
    	printf("     Word       Count\n");
    	printf("--------------- -----\n");
    	
    	while( start != NULL )
    	{
    		printf("%15s %5d\n", start->Word, start->Count);
    		start = start->Next;
    	}
    	return;
    }// end PrintList Function

  2. #2
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    You have a number of problems that should have come up if you compiled with all warnings on. Remove all your syntax and grammar errors from the code, and that will help some.

    You only get the first word because you haven't enclosed GetWord() inside a loop anywhere. You call it a second time, but don't do any processing afterward.

    You have a segfault on line 61 because current is NULL. You initialize current to NULL in the declaration, but never set it to the start of the list like your comment says. Because of this, your code never gets inside the while loop on line 53, and you never change current or previous. Thus, current->Word on tries to dereference a NULL. I suspect there may be a few more of these lying around, but we'll see about that later. Try iterating with a for loop and breaking out. This will ensure that you always initialize, increment and terminate your loop. E.g.
    Code:
    for (current = start; current; current = current->Next, previous = current) {
        if (strcmp(current->Word, word) >= 0) {  // can't seg fault because of the for loop termination condition
            // we found a word
            break;
        }
    }
    Work on that for now and come back with your modified code if you're still having trouble.

  3. #3
    Registered User
    Join Date
    Nov 2010
    Posts
    5
    I have always ignored the warnings because I thought it was due to using a c++ complier for a c program.

    This is what I have now:

    Code:
    int main() 
    {
    	/* declare and initialize variables */
    	FILE *fileptr;
    	char word[25];
    	struct Node *start = NULL;
    	struct Node *newptr = NULL;
    	struct Node *current = NULL;
    	struct Node *previous = NULL;
    
    	printf("Openning file...\n");
    	if( ( fileptr = fopen( "document.txt", "r" ) ) == NULL )
    	{
    		printf("Unable to open file...\n");
    		return;
    	}
    	newptr = MakeNewNode(word);
    
    	GetWord( fileptr, word );
    
    	start = InsertAtBeginning( start, newptr);
    
    	for (current = start; current; current = current->Next, previous = current) 
    	{
    		GetWord( fileptr, word);
    
    		if (strcmp (current-> Word, word >= 0))
    		{
    			current->Count ++;
    		}
    		else
    		{
    			newptr = MakeNewNode;
    			InsertInMiddle( newptr, current, previous );
    		}
    	}
    	while(current != NULL && strcmp( current->Word, word) < 0)
    	{
    		current = current->Next;
    		previous=previous->Next;
    	}
    
    	if (strcmp (current-> Word, word == 0))
    	{
    		current->Count ++;
    	}
    	else
    	{
    		newptr = MakeNewNode;
    		InsertInMiddle( newptr, current, previous );
    	}
    
    	GetWord( fileptr, word );
    	
    	PrintList( start );
    	printf("\n-------------------------------\n\n");
    	fclose( fileptr );
    	return;
    }

  4. #4
    Registered User
    Join Date
    Nov 2010
    Posts
    5
    I have since turned it my assignment but would still like to see what I am doing wrong if anyone care to add anything. Thanks

  5. #5
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Using a C++ compiler for C code will probably produce warnings (depends on the compiler and how smart it is), and they should definitely be heeded. It should cause you to figure out how to compile your program in C mode so that you can be properly notified of errors and bad practices instead of sloughing off warnings as not applicable. There are still some compiler warnings you haven't removed, which would have clued you in to some pretty serious errors.

    First (minor but worth understanding) is the typedef of your struct Node declaration. You can either do
    Code:
    struct Node {
    	char Word[25];
    	int Count;
    	struct Node *Next;
    };
    since you always refer to it as "struct Node" throughout the rest of your code, or
    Code:
    typedef struct Node {
    	char Word[25];
    	int Count;
    	struct Node *Next;
    } node_t;
    Then define/declare all your node variables as "node_t node". Notice that the latter method allows you to drop the "struct" from your definitions/declarations.

    Second, your return statements in main need to return an integer value. This is typically 0 for success, or 1..255 for various error codes (they are not standard, so you decide what returning 1, 2, etc means).

    Third, you have some jacked up strcmp calls in if statements. Fix the parentheses (compiler should give you line numbers). Also, I'm not sure about your strcmp >= 0 line inside the for loop. I think you only want to increment Count if strcmp == 0, since that's when you have a duplicate word. The > part will increment Count on all words in your list that are "less than" word. I'm not sure this is an issue either since there's so much broken code getting in the way, but pay attention to the order of strcmp arguments and what that means for the return value, i.e. strcmp(a, b) and strcmp(b, a) will yield different results.

    Fourth, your don't initialize current before your while loop, so it's pointing to wherever it was at the end of the for loop. Try making this loop a for loop too.

    Fifth, how does your read loop terminate? Your implementation of GetWord doesn't use strtok properly and there is no way for it to remember the rest of the line for further parsing on subsequent calls. It should return some sort of status (integer) signalling success/failure/EOF so that the main function can catch this and handle it appropriately.

    You have some null pointer issues. Any time you use the -> operator, you need to make sure the pointer is not null, like so:
    Code:
    if (pointer) {
        pointer->member = 17;
    }
    That's all I have for now. Try working on that if you still want to mess with the code. Repost when you're done and I'll help you out some more if you want.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Following CTools
    By EstateMatt in forum C Programming
    Replies: 5
    Last Post: 06-26-2008, 10:10 AM
  2. Replies: 3
    Last Post: 03-04-2005, 02:46 PM
  3. Replies: 6
    Last Post: 03-02-2005, 02:45 AM
  4. Contest Results - May 27, 2002
    By ygfperson in forum A Brief History of Cprogramming.com
    Replies: 18
    Last Post: 06-18-2002, 01:27 PM
  5. Linked list with two class types within template.
    By SilasP in forum C++ Programming
    Replies: 3
    Last Post: 02-09-2002, 06:13 AM