Link to home
Start Free TrialLog in
Avatar of subira
subira

asked on

write a program that will maintain a phone directory using linked list

Write a  program that will maintain a phone directory. Your program should be able to process several commands as explained later in this assignment.

This program will emphasize the use of linked lists. Following are the various steps involved in completing this assignment:
1.      All phone entries will be maintained in a sorted order by the last name. Further, the entries for a given last name will have to be maintained in a sorted order by the first name.
2.      Your program has to process various commands from a file named phone.in. A command will be specified on a line by itself. Further, there will be a blank line between two commands. The various commands and the file format is as specified below:
      Add an entry to the phone directory (NOTE: The phone numbers in the directory have to be unique)
ADD
lName fName
address
city
state
zip
phoneNumber
      Print  entries by last name
             PBLN
             lName
      Delete an entry by a given phone number
             DBPN
             phoneNumber
      Delete all entries with the given last name
             DBLN
             lName
      Print entire directory (output should be sorted as mentioned above)
             PDIR
A sample input file with each of the above commands might look like this (it is recommended you make one up yourself to test your program exhaustively – with all possible cases)
ADD
Brown Heather
8712 Birch Ln
Wichita
KS
67208-1111
316-658-4690

PBLN
Black

DBPN
111-111-1111

DBLN
Brown

PDIR

ADD
White Brandon
1055 Conell St
Kansas City
MO
57218
222-610-0350
3.      The output of your program has to be written to an output file, phone.out
4.      The executable of your program has to be called phone.
5.      Your program has to be split into several appropriate functions. Further, you need to use descriptive variable names. The style and readability of your program will also determine your grade, in addition to the correctness of the program.
6.      Files needed for this program:                                                                                                   defs.h, llist.h, llist.c, phone.h, phone.c, phoneFns.c Makefile
 
Avatar of zulti
zulti

Is this homework ???
Avatar of subira

ASKER

yes it is
>> yes it is
Do something and post the code.
Avatar of F. Dominicus
1) with a linked list is a bit tedious, and unfortunatly you have to write it out to disk also, so you need some way of flattening a list and reconstruct it the assignment suggest that it may be part of llist.c. But as others write, try it yourself first and then ask.

Regards
Friedrich
Dear subira,
I advise you to start working on it and ask for help if you get some problem in between. You can not expect anybody to write the complete code for you.

Regards
Prashant Sabnekar
Avatar of subira

ASKER

the following is my phone.c file

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


int main ( void )
{
     FILE *fin;
     FILE  *fout;
     DIRECTORY *directory;
     int cmd;
     DIRECTORY *temp = (DIRECTORY *) NULL ;
     DIRECTORY *dir = (DIRECTORY *) NULL;
     DIRECTORY *head = (DIRECTORY *) NULL;
     char cmdStr [5];
     DIRECTORY *ptrDirectory [BUFLEN];


    initphoneDirectory( ptrDirectory);

   if ( ( fin = fopen ( "phone.in", "r" ) ) == NULL ) {
     fprintf ( stderr, "Could not open input file: %s\n", "phone.in" );
     exit ( -1 );
   }

   if ( ( fout = fopen ( "phone.out", "w" ) ) == NULL ) {
     fprintf ( stderr, "Could not open output file: %s\n", "phone.out" );
     fclose ( fin );
  exit ( -1 );
   }

   // Loop until there are no more commands in input file
   while ( fgets ( cmdStr, BUFLEN, fin ) != NULL ) {
     if ( lineWithBlanks ( cmdStr ) )
       continue;
     else { // process the cmdStr
       cmd = fun1 ( cmdStr );


   switch ( cmd )

     {
         case ADD:   // add an entry to the phone directory

                 temp = createDirectory ( head) ;
                 dir = readEntry(fout, fin, directory );
                 break;

         case PBLN: //print entries by last name

                 printBylName(fout,fin,ptrDirectory);
                 break;


         case DBPN: // delete an entry by a given phone number

                 delByPhone(fout,fin,ptrDirectory);
                 break;


         case DBLN:  // Delete all entries with the given last name

                delBylName(fout,fin, ptrDirectory);

                break;

       }

     }

   }




   fclose ( fin );
   fclose ( fout );

   return EXIT_SUCCESS;
}


I have othe code for other files to
questions
1.I have hard time to write is the function for commands
2. How do we call a link list function to the main function?


post complete code.
Avatar of subira

ASKER


the following is phoneFns.c file

#include "phone.h"

#include <string.h>

#include <stdio.h>

#include <stdlib.h>



/*
 * Function to remove new line character
 */
void rmNl ( char str[] )
{
   char *ptr;

   if ( ( ptr = strchr ( str, '\n' ) ) )
      *ptr = '\0';
}

/*
 * Check to see if line is an empty one with only spaces
 * Returns 1 if line consists of blank spaces, 0 otherwise
 */
int lineWithBlanks ( char *s )
{
   int result = 1, i;

   for ( i = 0; i < strlen (s); i++ ) {
      if ( s[i] != ' ' ) {
         result = 0;
         break;
      }
   }
   return result;
}

int  fun1 ( char cmdStr[] )
{

int ans;

 switch( ans)
   {
      case  ADD:

         ans =  1;
         break;

      case PBLN:        ans =  2;
         break;

      case DBLN:
         ans =  3;
         break;

      case DBPN:
         ans = 4;
         break;



      case PDIR:
          ans =  5;
          break;


   }
 return ans;
    case DBLN:
         ans =  3;
         break;

      case DBPN:
         ans = 4;
         break;



      case PDIR:
          ans =  5;
          break;


   }
}

DIRECTORY *readEntry(FILE *fout, FILE  *fin, DIRECTORY *directory)



 {



         char fName[10];
         char lName[10];
         char address[25];
         char city[25];
         char state[10];
         char zip[10];
         char phoneNumber[12];

         fscanf(fin , "%s %s\n", fName, lName);
         fgets(address,25,fin);
         fscanf(fin, " %s \n", city);
         fscanf(fin, "%s \n", state);
         fscanf(fin, "%s \n", zip);
         fscanf(fin, "%s \n", phoneNumber);

         strcpy(directory->fName,fName);
         strcpy(directory->lName,lName);
         strcpy(directory->address,address);
         strcpy(directory->city,city);
         strcpy(directory->state,state);
         strcpy(directory->zip,zip);
         strcpy(directory->phoneNumber,phoneNumber);


         fprintf(fout," %s %s \n", directory->fName,directory->lName);
         fprintf(fout,"%s \n", directory->address);
         fprintf(fout,"%s\n", directory->city);
         fprintf(fout, " %s\n", directory-> state);
         fprintf(fout, " %s \n", directory->zip);
         fprintf(fout, " %s \n", directory-> phoneNumber);







         return directory;


   }


 DIRECTORY *createDirectory (DIRECTORY * head)

 {


         DIRECTORY *direc = (DIRECTORY *) malloc(sizeof(DIRECTORY));

         if (direc)

             {

                 strcpy(direc->fName, " ");
                 strcpy(direc->lName, " ");
                 strcpy(direc->address, " ");
                 strcpy(direc->city, " ");
                 strcpy(direc->state, " ");
                 strcpy(direc->zip, " ");
                 strcpy(direc->phoneNumber, " ");



            }

        return direc;


 }


void initphoneDirectory( DIRECTORY *pDirectory[])

{

     int n;
     for(n=0; n < BUFLEN ; n++)
     pDirectory[n] = NULL;
     return;

}
int phonedir(char *phoneNumber)

{

    int i=0;
    int phoneNum = 0;
    for (i = 0; i< strlen(phoneNumber); i++)
      {
         phoneNum += phoneNumber[i];
         phoneNum %= BUFLEN;
         return phoneNum;
      }



}

void printBylName(FILE *fout,  FILE *fin,  DIRECTORY *ptrDirectory[])

{


   char lName[10];

   int n = 0;

   DIRECTORY *ptr;

   fscanf(fin," %s\n", lName);
   for (n = 0; n < BUFLEN; n++)
    for (ptr = ptrDirectory[n]; ptr!=NULL; ptr = ptr->next)
     {

      if (strcmp(ptr->lName,lName)==0)

         {
           fprintf(fout, " %s\n", ptr->lName);


         }

     }



}

void delByPhone (FILE *fout, FILE *fin, DIRECTORY *ptrDirectory[])


{

     int n = 0;

     DIRECTORY *prevPtr = (DIRECTORY *)NULL;
     DIRECTORY *ptr =( DIRECTORY*) NULL;
     char phoneNumber [12];

     fscanf(fin," %s \n", phoneNumber);

     n = phonedir(phoneNumber);

     for (ptr = ptrDirectory[n]; ptr !=NULL; ptr = ptr ->next)

       // remove the node

       ptr = ptrDirectory[phonedir(phoneNumber)];
       prevPtr = ptr;

       while(ptr)
         {

           if (strcmp(ptr->phoneNumber,phoneNumber)==0)
           break;
          prevPtr = ptr;
          ptr = ptr->next;


         }  

       if(ptr != NULL)

         {

           if(prevPtr == ptr)
               {

                 ptrDirectory[phonedir(phoneNumber)] = prevPtr->next;
                 free(ptr);

               }

            else

               {

                  prevPtr = ptr-> next;
                  free(ptr);
            }
         }







 }



// function to delete all entries in the given last name

void delBylName(FILE *fout, FILE *fin, DIRECTORY *ptrDirectory[])

{

     int n = 0;
 DIRECTORY *prevPtr = (DIRECTORY *)NULL;
     DIRECTORY *ptr =( DIRECTORY*) NULL;
     char lName;

     fscanf(fin," %s \n", lName);


     for (ptr = ptrDirectory[n]; ptr !=NULL; ptr = ptr ->next)

       // remove the node

       ptr = ptrDirectory[lName];
       prevPtr = ptr;

       while(ptr)
         {

           if (strcmp(ptr->lName,lName)==0)
           break;
 prevPtr = ptr;
          ptr = ptr->next;

            }

       if(ptr != NULL)

         {

           if(prevPtr == ptr)
               {

                 ptrDirectory[lName] = prevPtr->next;
                 free(ptr);

               }

            else

               {
       prevPtr = ptr-> next;

                  free(ptr);

               }
         }




}




// function to print  entire directory

void printDirectory(FILE  *fout, DIRECTORY *ptrDirectory[])
{

   int i = 0;
   DIRECTORY *ptr;

   for ( i = 0; i < BUFLEN ; i++)

     {
        ptr = ptrDirectory[i];
        while( ptr)
         {
           fprintf(fout, " %s%s\n", ptr->fName,ptr->lName);
           fprintf(fout,   "%s\n", ptr->address);
           fprintf(fout, "%s\n", ptr->city);
           fprintf(fout, " %s\n",ptr-> state);
           fprintf(fout, " %s\n", ptr->zip);
           fprintf(fout, "%s\n",ptr->phoneNumber);

         }

     }


}



THE FOLLOWING IS phone.h file


#ifndef PHONE_H
  #define PHONE_H  // Avoids duplication




  // Defines

#define BUFLEN 80
#define ADD   1
#define PBLN  2
#define DBPN  3
#define DBLN  4
#define PDIR  5





typedef struct directory
{

  char fName[10];
  char lName[10];
  char address[25];
  char city[20];
  char state[10];
  char zip[10];
  char phoneNumber[12];

  struct directory *next;




}DIRECTORY;





//prototypes

int lineWithBlanks ( char *s );

void rmNl ( char str[] );

int fun1 ( char cmdStr[] );


DIRECTORY *readEntry(FILE *fout, FILE  *fin, DIRECTORY *directory);

DIRECTORY *createDirectory (DIRECTORY *head);


void initphoneDirectory( DIRECTORY  *pDirectory[]);

int phonedir(char *phoneNumber);

void printBylName(FILE *fout,  FILE *fin,  DIRECTORY *ptrDirectory[]);

void delByPhone (FILE *fout, FILE *fin, DIRECTORY *ptrDirectory[]);

void delBylName(FILE *fout, FILE *fin, DIRECTORY *ptrDirectory[]);

void printDirectory(FILE  *fout, DIRECTORY *ptrDirectory[]);

#endif


THE FOLLOWING IS llist.c file ( this is not  my code, it was given)

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


/* Function: createNode
 * Input: inpData - input data to be copied to 'data' part of node
 *         nextPtr - address to be copied to 'next' part of node
 * Returns: On success, the address of the newly created node,
 *          otherwise NULL
 * Description: This function creates a new node from the heap space to
 *              contain a given data record and returns a pointer to
 *              this node. If there is not enough space to create a
 *              node, then, it will return NULL.
 */

LINKLIST * createNode ( ELMTYPE inpData, LINKLIST *nextPtr )
{
   LINKLIST *newNode = (LINKLIST *) malloc ( sizeof (LINKLIST) );

   if ( newNode )
   {
      newNode -> data = inpData;
      newNode -> next = nextPtr;
   }
   return newNode;
}

/* Function: freeList
 * Input: headPtr - pointer to the head of the list
 * Returns: NULL
 * Description: Given the pointer to the first node of the list, this
 *              function deletes all the nodes in the list.
 */

LINKLIST * freeList ( LINKLIST *headPtr )
{
   LINKLIST *cur = headPtr;
   while ( cur )
   {
      headPtr = headPtr -> next;
      free ( cur );
      cur = headPtr;
   }
   return NULL;
}

/* Function: searchList
 * Input: head - pointer to head of the linked list
 *        cur - pointer to hold the address of node whose key matches
 *          target
 *        prev - pointer to hold the address of the previous node
 *        target - target data that is to be located
 * Returns: if target is found, returns TRUE, else, FALSE
 * Description: Search a linked list for the node which matches a given
 *              target key. Two pointers will be set during the search.
 *              If the matching node is found, cur is set to the address
 *       of the node. If target is not found, then prev and cur
 *              are set such that if a node containing the target were
 *              to be in the list, it would be between the two pointers.
 *              ASSUMPTION made here, is that the nodes of the linked
 *              list are in increasing order by key field and that the
 *              keys are unique.
 */
BOOLEAN searchList (LINKLIST *head,LINKLIST **prev,LINKLIST **cur, KEYTYPE target)
{
   BOOLEAN result = FALSE;





 // Start search with head node
   *cur = head;
   *prev = NULL;

   while ( *cur && GT ( target, (*cur)->data.key ) )
   {
      *prev = *cur;
      *cur = (*cur)->next;
 }

   if ( *cur && EQ ( target, (*cur)->data.key ) )
      result = TRUE;

   return result;
}

/* Function: insertNode
 * Input: head - pointer to head of the linked list
 *        data - data to be inserted into new node
 * Returns: 1 on successful insertion of new node into list
 *          Otherwise, 0 to indicate existence of duplicate key
 *                     -1 to indicate memory overflow
 * Description: This function will attempt to add a new node to a
 *              linked list. Assumption made: the keys are of the data
 *              records are to be unique.
 */
int insertNode ( LINKLIST **head, ELMTYPE data )
{

   LINKLIST *prev, *cur, *newNode;
   BOOLEAN found = FALSE;
   int result;

   found = searchList ( *head, &prev, &cur, data.key );

   if ( found )
     result = 0; // duplicate key exists in the list
   else  // try to add a node for the data record to the list
   {
      newNode = createNode ( data, NULL );
      if ( !newNode )
         result = -1; // out of heap space
      else   // created a node, add it to the list
      {
         // prev has been set by searchList function
         addNode ( head, prev, newNode );
         result = 1;  // success in inserting the node
      }
    }
    return result;
}

/* Function: addNode
 * Input: head - pointer to head of the linked list
 *        prev - pointer to the node that will be the new node's
 *          predecessor
 *        newNode - pointer to the new node that is to be added to
 *          the list
 * Returns: None
 * Description: This fu *              linked list.
 */

void addNode ( LINKLIST **head, LINKLIST *prev, LINKLIST *newNode )
{
   if ( prev == NULL ) // insert at the start of the list
   {
      newNode->next = *head;
      *head = newNode;
   }
  else   // new node is any node other than the first node
   {
      newNode->next = prev->next;
      prev->next = newNode;
   }
}

/* Function: deleteNode
  * Input: head - pointer to head of the linked list
 *      : target - target data that is to be located
 *      : dataOut - copies target, if found, to the calling function
 * Returns: on success, TRUE, else FALSE
 * Description: This function will remove teh node containing the record
 *              which matches a given target key. If found, a copy of
 *              the record will be returned to the calling function
 *              before the node is released back to heap space. We
 *              assume the data of the list is sorted by increasing key field
 *              order.
 */

BOOLEAN deleteNode ( LINKLIST **head, KEYTYPE target, ELMTYPE *dataOut )
{
   LINKLIST *prev, *cur;
   BOOLEAN found = FALSE;

   found = searchList ( *head, &prev, &cur, target );

   if ( found )
   {
      // write out the record data  *dataOut = cur->data;

      // remove the node from the list
      if ( prev == NULL ) // deleting first node
         *head = cur->next;
      else
         prev->next = cur->next;
      free ( cur );
   }


   return found;
}


/* Function: retrieveNode
 * Input: head - pointer to head of the linked list
 *      : target - target data that is to be located
 *      : dataOut - copies target, if found, to the calling function
 * Returns: on success, TRUE, else FALSE
 * Description: This function will attempt to retrieve the record from a node
 *              of the linked list which matches a given target key. If found,
 *              a copy of the record will be returned to the calling function
 *              We assume the data of the list is sorted by increasing key field
 *              order.
 */

BOOLEAN retrieveNode ( LINKLIST **head, KEYTYPE target, ELMTYPE *dataOut )
{
   LINKLIST *prev, *cur;
   BOOLEAN found = FALSE;


 found = searchList ( *head, &prev, &cur, target );

   if ( found ) // write out the record data
      *dataOut = cur->data;

   return found;
}

/* Function: printList
 * Input: head - pointer to head of the linked list
 * Returns: None
 * Description: This function will traverse the linked list and print
 *              the data part of each node
 */

void printList ( LINKLIST **head )
{
   LINKLIST *cur = *head;

   if ( !cur )
 return;  // print message - no data in the list

   for ( ; cur; cur = cur->next ) {
      // insert lines here that are specific to the application
      // an example line could be the following:
      printf ("%d ", cur->data.key );
   }
   printf ("\n");
}

/*****************************************************************/

/* Function: initLlist
 * Input: head - pointer to head of the linked list
 * Returns: None
 * Description: This function will initialize a linked list
 */

void initLlist ( LINKLIST ** head )
{
  *head = NULL;
}

/* Function: delLlist
 * Input: head - pointer to head of the linked list
 * Returns: None
 * Description: This function will delete all nodes of linked list
 *              and set the head to NULL
 */

void delLlist ( LINKLIST ** head )
{
   *head = freeList ( *head );
}

/* Function: listCount
 * Input: head - pointer to head of the linked list
 * Returns: Number of nodes in the list
 * Description: This function will return a count of the number of nodes in
 *              the linked list
 */

int listCount ( LINKLIST *head )
{
   LINKLIST *cur = head;
   int i = 0;
   while ( cur ) {
     i++;
     cur = cur->next;
   }
   return i;
}

/* Function: insertLast
 * Input: head - pointer to head of the linked list
 *        data - data to be inserted into new node
 * Returns: TRUE on successful insertion of new node into list
 *        : FALSE otherwise
 * Description: This function will insert the node to the end of the linked
 *              list. Duplicate keys are allowed. Further, the list will
 *              not be in any sorted order.
 */

BOOLEAN insertLast ( LINKLIST **head, ELMTYPE data )
{
   LINKLIST *prev, *cur, *newNode;
 BOOLEAN result = FALSE;

   for ( prev = NULL, cur = *head; cur; cur = cur->next )
     prev = cur;

   newNode = createNode ( data, NULL );
   if ( newNode )
   {
      // prev has been set by searchList function
      addNode ( head, prev, newNode );
      result = TRUE;
   }
   return result;
}


/* Function: reverseList
 * Input: head - pointer to head of the linked list
 * Returns: None
 * Description: This function will reverse the nodes of a linked list
 *              such that the head will point to the previously last
 *              node, and the previously first node, will now be the
 *              last node.
 */

void reverseList ( LINKLIST **head )
{
   LINKLIST *cur, // will visit nodes of the list
            *prev, // last node visited
            *nextNode; // the node which follows cur

   cur = *head;
  prev = NULL;

   // Loop and change the links backward for each node
   while ( cur )
   {
      nextNode = cur->next; // set next node to go to
      cur->next = prev; // bend the link back
   prev = cur; // move up prev and cur
      cur = nextNode;
   }
   // the last node visited is now the first node of the list
   *head = prev;
}


THE FOLLOWING IS llist.h file

#ifndef LLIST_H
   #define LLIST_H

   #include "defs.h"

   typedef enum boolean_type
     {FALSE, TRUE}
   BOOLEAN;

   typedef struct linklist
   {
      ELMTYPE data;
      struct linklist *next;
   } LINKLIST;

   LINKLIST * createNode ( ELMTYPE inpData, LINKLIST *nextPtr );
   LINKLIST * freeList ( LINKLIST *headPtr );
   BOOLEAN searchList ( LINKLIST *head, LINKLIST **prev, LINKLIST **cur, KEYTYPE target);
   int insertNode ( LINKLIST **head, ELMTYPE data );
   void addNode ( LINKLIST **head, LINKLIST *prev, LINKLIST *newNode );
   BOOLEAN deleteNode ( LINKLIST **head, KEYTYPE target, ELMTYPE *dataOut );
   BOOLEAN retrieveNode ( LINKLIST **head, KEYTYPE target, ELMTYPE *dataOut );
   void printList ( LINKLIST **head );

  /*********************************/
   void initLlist ( LINKLIST **head );
   void delLlist ( LINKLIST **head );
   int listCount ( LINKLIST *head );
   BOOLEAN insertLast ( LINKLIST **head, ELMTYPE data );
   void reverseList ( LINKLIST **head );
#endif



THE FOLLOWING IS MAKEFILECC = gcc -Wall
ALL =  phone

all: $(ALL)

# End of macros

phone: phone.o llist.o phoneFns.o
        $(CC) phone.o llist.o phoneFns.o -o phone

llist.o: llist.c llist.h defs.h
        $(CC) -c llist.c

phone.o: phone.c llist.h defs.h phone.h
        $(CC) -c phone.c
phoneFns.o: phoneFns.c llist.h defs.h phone.h
        $(CC) -c phoneFns.c

tidy:
        rm -f *.o core

clean:
        rm -f *.o core phone


when I compile I have the following errors

gcc -Wall -c phoneFns.c
In file included from phoneFns.c:9:
phone.h:56: error: syntax error before '*' token
phone.h:64: error: syntax error before '*' token
phone.h:66: error: syntax error before '*' token
phone.h:68: error: syntax error before '*' token
phone.h:70: error: syntax error before '*' token
phoneFns.c: In function `delBylName':
phoneFns.c:305: warning: format argument is not a pointer (arg 3)
phoneFns.c:312: warning: subscript has type `char'
phoneFns.c:318: warning: passing arg 2 of `strcmp' makes pointer from integer without a cast
phoneFns.c:332: warning: subscript has type `char'
make: *** [phoneFns.o] Error 1





definition of ELMTYPE is missing. Can you poet that also?
Avatar of subira

ASKER

#ifndef DEFS_H
  #define DEFS_H  // Avoids duplication

  // Defines

  #define EQ(a, b)      ( (a) == (b) )
  #define LT(a, b)      ( (a) < (b) )
  #define GT(a, b)      ( (a) > (b) )
  #define BUFLEN        80

   // typedefs

   typedef int KEYTYPE;

   typedef struct student
   {
      char fName[BUFLEN],
           lName[BUFLEN];
      KEYTYPE key;   // student id
      int hw[5],
          exm[3];
   } STUDENT;

  typedef STUDENT ELMTYPE;

#endif
ASKER CERTIFIED SOLUTION
Avatar of GranMod
GranMod

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial