Thread: Searching Linked List

  1. #1
    Registered User
    Join Date
    Mar 2011
    Location
    Windsor, Ontario
    Posts
    44

    Searching Linked List

    I am having trouble searching a Linked List for contacts, when the program goes to scan in the last name it reads it in over and over. I am wondering why it doesn't just take the name and continue after that? The problems I am having are in the:
    void Search(struct contact *ptr) function. Here is the code:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <ctype.h>
    #include <string.h>
    
    //global:
    struct contact *ptrFirst = NULL;//empty list (ptrFirst is the head of the list
    struct contact *ptrLast = NULL;//empty list (ptrLast is the tail of the list)
    
    //declare a structure called contact
    struct contact //contact struct for holding contact info
    {
    	char firstname[40]; //holds the first name of ith contact
    	char lastname[40]; //holds last name of ith contact
    	char address[100]; //holds address of ith contact
    	char postalcode[7]; //holds postalcode of ith contact
    	char phone[10]; //holds phone of ith contact
    	struct contact *ptrNext;	// self referential pointer
    };
    
    //Prototypes:
    struct contact *CreateContact();
    void PrintList(struct contact *ptr);
    void ResetList();
    struct contact *AddToEnd(struct contact *ptrNew);
    struct contact* InputRecord(struct contact *ptrNew); // used by Add to interactively get the values from the user
    int Save(const char* filename);
    int Load(const char* filename);
    char *WordCap(char *word);
    void Search(struct contact *ptr);
    
    int i=0;
    
    int main()
    {
    	int run=1;
    	int	input=1;
    	int result=0;
    	int count=0;
    	printf("*** Personal Contact Book v1.0 ***");
    	printf("\n");//newline for neatness
    	while(run==1)
    	{
    		char temp[50];
    		char again[10]={'Y'}; //if after a contact is entered if will store if user wants to enter another one
    		printf(
    		"1. Add new contact\n"
    		"2. Display current contacts\n"
    		"3. Search for a contact\n"
    		"4. Save contacts to file\n"
    		"6. Delete an existing record\n"
    		"7. Exit\n"
    		);
    		scanf("%d", &input);
    		fflush(stdin); //flush because scanf was used
    		i=0;
    		switch(input)
    		{
    			case 1:
    			{
    				while(again[0]=='Y')
    				{
    					AddToEnd(InputRecord(CreateContact()));
    					printf("Add another contact?: ");//ask if they want to enter another contact
    					gets(again);//scan in answer
    					again[0]=toupper(again[0]);//make again cap so that it will correctly compare
    					printf("\n");//newline for neatness
    				}	
    				break;
    			}	
    			case 2:
    			{
    				PrintList(ptrFirst);
    				break;
    			}
    			case 3:
    			{
    				Search(ptrFirst);
    			}
    			case 4:
    			{
    				
    			}
    			case 5:
    			{
    				
    			}
    			case 6:
    			{
    				
    			}
    			case 7:
    			{
    				ResetList(ptrFirst);
    				run = 0;
    				break;
    			}
    			default:
    			{
    				printf("Invalid entry, try again\n\n");
    				break;
    			}
    		}
    	}
    }
    
    //CreateContact creates using dynamic memory allocation a new record of type contact
    //Input: assumes enough dynamic memory is available
    //Output: returns a pointer to the enw contact, or NULL if not enough memory
    struct contact *CreateContact()
    {
    	return (struct contact *)(malloc(sizeof(struct contact)));
    }
    
    //PrintList will print out the contents of the list
    void PrintList(struct contact *ptr)
    {
    	if(ptr!=NULL)
    	{
    		printf("First name: %s\n",ptr->firstname);
    		printf("Last name : %s\n",ptr->lastname);
    		printf("Address   : %s\n",ptr->address);
    		printf("Postal Code: %s\n",ptr->postalcode);
    		printf("Phone     : %s\n",ptr->phone);//ask for phone
    		printf("\n");//newline for neatness
    		PrintList(ptr->ptrNext);
    	}
    }
    
    void Search(struct contact *ptr)
    {
    	char name[40];
    	printf("What is the contact's last name?: ");
    	gets(name);
    	strcpy(name,WordCap(name)); //copy name back into ith lastname after wordcap opperated on it
    	
    	while(ptr!=NULL)
    	{
    		if(strcmp(name,ptr->lastname)==0)
    		{
    			i++;
    		}
    		ptr->ptrNext;
    	}
    	printf("Found %d record(s):\n", i);
    }
    
    //ResetList will empty or free() the contents of the list
    void ResetList()
    {
    	struct contact *ptrDel=ptrFirst;
    	
    	if (ptrDel != NULL)	// empty list! nothing to erase... quit
    	{
    		ResetList(ptrDel->ptrNext);
    		free(ptrDel);
    	}
    }
    
    //AddToEnd will add a contact to the end of the list
    struct contact *AddToEnd(struct contact *ptrNew)
    {
    	//case 1: ptrNew is not valid(ie. NULL - nothing to add!)
    	if(ptrNew==NULL)
    		return NULL;
    	//case 2: add the record to an empty list
    	if(ptrFirst==NULL)
    	{
    		ptrFirst=ptrNew;
    		ptrLast=ptrNew;
    	}
    	//case 3: add the record to an existing list
    	else
    	{
    		ptrLast->ptrNext = ptrNew;
    		ptrLast = ptrNew;		
    	}
    }
    
    //InputRecord sets the initial values of a new record
    //Input: a pointer to an existing record
    //Output: sets the int value to a value from the keyboard, and null to all pointers
    //        and returns the same pointer to that initialized record
    struct contact* InputRecord(struct contact *ptrNew)
    {
    	if(ptrNew==NULL) //fail-safe: check for valid pointer
    		return NULL;
    	int valid=0; //used when determining if user entered a valid phone or postalcode	
    	
    	printf("First name: ");
    	gets(ptrNew->firstname);
    	strcpy(ptrNew->firstname,WordCap(ptrNew->firstname)); //copy word back into ith firstname after wordcap opperated on it
    	printf("Last name : ");
    	gets(ptrNew->lastname);
    	strcpy(ptrNew->lastname,WordCap(ptrNew->lastname)); //copy word back into ith lastname after wordcap opperated on it
    	printf("Address   : ");
    	gets(ptrNew->address);
    	printf("PostalCode: ");
    	gets(ptrNew->postalcode);
    	while(valid==0) //while not valid
    	{
    		//if all the correct positions are words and numbers respectivly it will become valid
    		if(isalpha(ptrNew->postalcode[0]) && isdigit(ptrNew->postalcode[1]) && isalpha(ptrNew->postalcode[2]) &&
    		isdigit(ptrNew->postalcode[3]) && isalpha(ptrNew->postalcode[4]) && isdigit(ptrNew->postalcode[5]))
    		{
    			valid=9; //update valid if it is valid
    		}
    		else
    		{
    			printf("Invalid please re-enter PostalCode: "); //else tell user not valid
    			gets(ptrNew->postalcode);//scan in again to get new postal code
    		}
    	}
    	printf("Phone     : ");//ask for phone
    	gets(ptrNew->phone);//scan in phone
    	valid=0;//assume not valid
    	while(valid==0)//while not valid
    	{
    		//check if it is all digits
    		if(isdigit(ptrNew->phone[0]) && isdigit(ptrNew->phone[1]) && isdigit(ptrNew->phone[2]) &&
    		isdigit(ptrNew->phone[3]) && isdigit(ptrNew->phone[4]) && isdigit(ptrNew->phone[5]) &&
    		isdigit(ptrNew->phone[6]) && isdigit(ptrNew->phone[7]) && isdigit(ptrNew->phone[8]) &&
    		isdigit(ptrNew->phone[9]))
    		{	
    			valid=9;//update validity
    		}
    		else
    		{
    			printf("Invalid please re-enter Phone: ");//else print not valid
    			gets(ptrNew->phone);//re scan in phone
    		}
    	}
    					
    	
    	ptrNew->ptrNext=NULL;
    	return ptrNew;
    }
    char *WordCap(char *word)
    {
    	int i=1; //keeps track of how far in the word it is
    	*word=toupper(*word); //capatalize the first char
    	while(*(word+i)!='\0') //while not the end of the word
    	{
    		*(word+i)=tolower(*(word+i)); //it will make the rest lower case
    		i++; //increment i
    	}
    	*(word+i)=tolower(*(word+i)); //it will make the rest lower case
    	return word; //return now capatalized
    }
    And adding this which I though was the problem just causes it to go through but segment:
    ptr=ptr->ptrNext;
    Last edited by JamesD; 03-30-2011 at 02:27 PM.

  2. #2
    Registered User
    Join Date
    May 2010
    Posts
    4,632
    When I compiled your code I got these warnings:
    ||=== c_homework, Debug ===|
    main.c||In function ‘main’:|
    main.c|44|warning: unused variable ‘temp’|
    main.c|39|warning: unused variable ‘count’|
    main.c|38|warning: unused variable ‘result’|
    main.c||In function ‘Search’:|
    main.c|143|warning: statement with no effect|
    main.c||In function ‘WordCap’:|
    main.c|240|warning: declaration of ‘i’ shadows a global declaration|
    main.c|32|warning: shadowed declaration is here|
    main.c||In function ‘AddToEnd’:|
    main.c|178|warning: control reaches end of non-void function|
    obj/Debug/main.o||In function `main':|
    main.c|65|warning: the `gets' function is dangerous and should not be used.|
    ||=== Build finished: 0 errors, 8 warnings ===|
    And as you can see one of the warnings concerns your search function.

    You probably need to change your compiler's settings to turn on warning messages and insure that the warning level is set to the highest warning level.

    Jim

  3. #3
    Registered User
    Join Date
    Mar 2011
    Location
    Windsor, Ontario
    Posts
    44
    Mine just had whitespace warnings for lines 1-4 lol(I have no idea what that means btw), The compiler I use is called SSH(Secure Shell) If anyone knows how to upgrade to maximum warnings that would be pretty cool to know.
    It must be with the code I though was wrong after seeing this warning:
    Code:
    main.c||In function ‘Search’:|
    main.c|143|warning: statement with no effect|
    But even after adding in the
    Code:
    ptr=ptr->ptrNext;
    Which I assumed I had to do it segments...

    So you can see what I am saying I will do this
    Code:
    Last login: Wed Mar 30 16:33:51 2011 from 137.207.92.57
    luna:~>cc assign4.c
    "assign4.c", line 1: warning: invalid white space character in directive
    "assign4.c", line 2: warning: invalid white space character in directive
    "assign4.c", line 3: warning: invalid white space character in directive
    "assign4.c", line 4: warning: invalid white space character in directive
    luna:~>a.out
    *** Personal Contact Book v1.0 ***
    1. Add new contact
    2. Display current contacts
    3. Search for a contact
    4. Save contacts to file
    6. Delete an existing record
    7. Exit
    1
    First name: jim
    Last name : bob
    Address   : 1
    PostalCode: U8U8U8
    Phone     : 8888888888
    Add another contact?: y
    
    First name: jo
    Last name : boB
    Address   : 1
    PostalCode: Y7Y7Y7
    Phone     : 7878787878
    Add another contact?: n
    
    1. Add new contact
    2. Display current contacts
    3. Search for a contact
    4. Save contacts to file
    6. Delete an existing record
    7. Exit
    3
    What is the contact's last name?: Bob
    Found 2 record(s):
    Segmentation fault (core dumped)
    luna:~>
    Last edited by JamesD; 03-30-2011 at 02:43 PM.

  4. #4
    Registered User
    Join Date
    May 2010
    Posts
    4,632
    It also looks like you are missing a break in your switch statement in main() (case 3. You should also go through your code and replace all of the gets() with fgets() and remove the fflush(stdin) calls. The gets function is very dangerous because it is easy to overrun the array bounds. The fflush() function is not defined for input streams, it only works for output streams.

    Jim

  5. #5
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    SSH is not a compiler, it provides you with encrypted terminal (command line) access to a remote machine. It probably means you're using some sort of Linux/UNIX type OS, which means your compiler should be able to be invoked by using 'cc'. Thus, you would type something like:
    Code:
    cc -Wall foo.c
    That '-Wall' should produce maximum warnings for gcc, and might work for your cc compiler. I'm not too familiar with C compilers other than gcc though, so you might need to check the man pages for command line options. Try 'man cc'.

  6. #6
    Registered User
    Join Date
    Mar 2011
    Location
    Windsor, Ontario
    Posts
    44
    It was the break; ahah, not sure how I missed that one, and to be more specific its UNIX, when I entered man cc I got this, its beyond me..:
    Code:
    Last login: Wed Mar 30 16:55:31 2011 from 137.207.92.56
    luna:~>cc man
    ld: fatal: file man: open failed: No such file or directory
    ld: fatal: File processing errors. No output written to a.out
    luna:~>man cc
    Reformatting page.  Please Wait... done
    
    SunOS/BSD Compatibility Package Commands                   cc(1B)
    
    NAME
         cc - C compiler
    
    SYNOPSIS
         /usr/ucb/cc [options]
    
    DESCRIPTION
         /usr/ucb/cc is the interface to the BSD Compatibility  Pack-
         age  C  compiler.  It  is  a  script that looks for the link
         /usr/ccs/bin/ucbcc to the C compiler. The /usr/ccs/bin/ucbcc
         link  is  available  only  with  the  SPROcc  package, whose
         default location is /opt/SUNWspro. The /usr/ucb/cc interface
         is  identical to /usr/ccs/bin/ucbcc, except that BSD headers
         are  used  and  BSD   libraries  are  linked   before   base
         libraries.  The  /opt/SUNWspro/man/man1/acc.1  man  page  is
         available only with the SPROcc package.
    
    OPTIONS
         The  /usr/ucb/cc  interface  accepts  the  same  options  as
         /usr/ccs/bin/ucbcc, with the following exceptions:
    
    --More--(22%)
    cc -Wall foo.c was "illegal"

  7. #7
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    I found what I think was the complete man page of what you posted on line somewhere, and didn't see an option for controlling warnings. Unfortunately, I haven't used a Sun system in over 9 years, so I don't remember how to enable warnings. The only things I can suggest are 'man ucbcc' and 'man acc'. Maybe one of those commands can compile with warnings. Otherwise, ask your professor, TA or class mate.

  8. #8
    Registered User
    Join Date
    Mar 2011
    Location
    Windsor, Ontario
    Posts
    44
    Thanks anduril462 I will find out what I can, as that would be really useful to have.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Problem using strcmp and strlen in a Linked List
    By matrixx333 in forum C Programming
    Replies: 4
    Last Post: 11-23-2009, 04:13 AM
  2. Unknown memory leak with linked lists...
    By RaDeuX in forum C Programming
    Replies: 6
    Last Post: 12-07-2008, 04:09 AM
  3. Reverse function for linked list
    By Brigs76 in forum C++ Programming
    Replies: 1
    Last Post: 10-25-2006, 10:01 AM
  4. Anyone good with linked list.....I am not....
    By chadsxe in forum C++ Programming
    Replies: 11
    Last Post: 11-10-2005, 02:48 PM
  5. Replies: 3
    Last Post: 03-04-2005, 02:46 PM