I have implemented a phonebook in C using a singly linked list sorted data structure. This is my first average-major project.
I need some reviews so that I can improve my coding standards. The program consists of 3 files:
header.h: custom header
/*
* File : header.h
* Custom Header Definition
*/
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<ctype.h>
#ifdef __linux__
#define CLEAR_SCREEN system("clear")
#elif _WIN32
#define CLEAR_SCREEN system("cls")
#endif
#define MAX_NAME 26
#define MAX_NO 11
typedef struct phonebook {
char * name ;
char * no ;
struct phonebook * next ;
} phonebook ;
/* Root Node */
extern phonebook * head ;
/* Temporary Storage */
extern char temp_name[] ;
extern char temp_no[] ;
/* Serial no while printing */
extern int START ;
/* Gets Input values From User , Returns 1 if it Fails */
extern int get_details() ;
/* Flushing stdin */
extern void input_flush() ;
/* basic verbs */
extern void add_contact ( ) ;
extern void print_book () ;
extern void search_contact ( ) ;
extern void delete_contact ( ) ;
extern void format_book ( struct phonebook ** ) ;
/* File Operations */
extern void file_read() ;
extern void file_write() ;
el.c: execution logic
#include "header.h"
char temp_name [ MAX_NAME ] ;
char temp_no [ MAX_NO ] ;
int START = 1 ;
phonebook * head = NULL ;
int run ()
{
char ch ;
char c ; /* flush */
int m =0 ;
CLEAR_SCREEN ;
printf ("\n\n\t PHONEBOOK MANAGER \n") ;
printf ("\n\n\n 1 . %-12s " , "Add Contact") ;
printf ("\n\n 2 . %-12s " , "Multiple") ;
printf ("\n\n 3 . %-12s " , "Search") ;
printf ("\n\n 4 . %-12s " , "Delete") ;
printf ("\n\n 5 . %-12s " , "Format") ;
printf ("\n\n 6 . %-12s " , "Print All") ;
printf ("{ Choice : }\b\b\b") ;
ch = getchar() ;
input_flush() ;
CLEAR_SCREEN ;
switch ( ch )
{
case '1':
if ( ! get_details() ) add_contact();
break ;
case '2':
printf (" \n How many Contacts ? : ") ;
if ( scanf ("%d" , &m ) !=1 )
break ;
else
input_flush() ;
while ( m>0 )
{
if ( ! get_details() ) add_contact() ;
m-- ;
}
break ;
case '3':
printf (" \n Enter Part/Full Contact Name/Number : ") ;
gets(temp_name ) ;
search_contact() ;
break ;
case '4':
printf (" \n Enter Full Contact Name : ") ;
gets(temp_name ) ;
delete_contact() ;
break ;
case '5':
printf (" \n Entire Data Will Be Lost ! Continue ?? { Y/other } : ") ;
ch = getchar () ; getchar() ;
if ( ch == 'Y' || ch == 'y' )
{
format_book( &head ) ;
printf ("\n Successful ! ") ;
}
else
printf ("\n Aborted ! ") ;
break ;
case '6':
print_book() ; break ;
default :
printf ("\n\n\nThank You ! \n") ;
return 0;
}
input_flush() ;
return 1 ;
}
int main ()
{
file_read() ;
while ( run () ) ;
file_write() ;
return 0 ;
}
bl.c: contain Implementations of Subroutines
#include"header.h"
/* helping subroutines */
void new_node ( phonebook ** ) ;
void fill_details () ;
void print_record ( phonebook * ) ;
void header () ;
void footer () ;
int duplicate_check() ;
int error_check () ;
void split (char * ) ;
void lowercase (char * ) ;
void input_flush() ;
void add_contact ( )
{
/* Traversing */
phonebook *temp = head ;
/* Storing Temporary Address */
phonebook * address = NULL ;
/* Adding First Contact */
if ( temp == NULL )
{
new_node ( &head ) ;
fill_details ( head ) ;
return ;
}
/* Modifying Root Node */
if ( strcmp ( temp->name, temp_name ) >0 )
{
new_node ( &head ) ;
fill_details ( head ) ;
head->next = temp ;
return ;
}
/* Adding Upcoming */
while ( temp->next !=NULL )
{
if ( strcmp( temp->next->name , temp_name ) < 0 )
temp=temp->next ;
else
break ;
}
/* Contact to add in the middle of two nodes */
if ( temp->next != NULL )
{
address = temp->next ;
new_node ( &temp->next ) ;
fill_details ( temp->next ) ;
temp->next->next = address ;
return ;
}
/* Adding contact at the end ( appending node at the end ) */
else
{
new_node ( &temp->next ) ;
fill_details ( temp->next ) ;
temp->next->next = NULL ;
return ;
}
}
void search_contact ()
{
phonebook * temp = head ;
/* How many contacts matched */
int cnt =0 ;
header () ;
START = 1 ;
if ( head ==NULL)
{
footer () ;
printf("\n\n Phone Book is Empty ..! ") ;
return ;
}
/* String to be searched is read to ' temp_name' */
while ( temp!= NULL )
{
if ( strstr (temp->name , temp_name ) !=NULL || strstr(temp->no , temp_name )!=NULL )
{
print_record( temp ) ; /* Detail Matched */
cnt++ ;
}
temp=temp->next ;
}
footer () ;
printf ("\n\n %d Contact%s have been Matched ! \n " , cnt , cnt==1?"":"s" ) ;
}
void delete_contact( )
{
/* Traversing */
phonebook * temp = head ;
/* Storing Temporary Address */
phonebook * address = NULL ;
if ( head ==NULL)
{
printf("\n\n Phone Book is Empty ..! ") ;
return ;
}
if ( strcmp( head->name , temp_name ) == 0 )
{
address = head ->next ;
free( head ) ;
head = address ;
printf("\n\n Contact deleted successfully...!! ") ;
return ;
}
while ( temp->next !=NULL )
{
if ( strcmp (temp->next->name , temp_name ) == 0 )
{
address = temp ->next->next ;
free ( temp->next ) ;
printf("\n\n Contact deleted successfully...!! ") ;
temp->next = address ;
return ;
}
else
temp=temp->next ;
}
printf ("\n\n Contact Does not Exist ! \n ") ;
}
void print_book ( )
{
phonebook *temp = head ;
/* Serial no is reset to 1 */
START = 1 ;
printf ("\n Complete List \n") ;
header () ;
if ( head ==NULL)
{
footer () ;
printf("\n\n Phone Book is Empty ..! ") ;
return ;
}
while ( temp!= NULL)
{
print_record( temp ) ;
temp = temp->next ;
}
footer () ;
}
void file_read ()
{
char data[44] ;
int i=-1 ;
char ch ;
FILE * fp1 ;
fp1 = fopen ("contacts.txt" , "r") ;
while ( ( ch = getc (fp1) ) != EOF )
{
if ( ch == '\n')
{
data[++i] ='\0', split (data) ;
add_contact() ;
i = -1 ;
}
else
{
data[++i] = ch ;
}
}
fclose( fp1 ) ;
remove ( "contacts.txt") ;
}
/* Separate Name and No. from "Data" store them in temp_name , temp_no */
void split (char * str )
{
int i=-1 ;
while ( *str!='=' )
{
temp_name[++i] = *str ;
str++ ;
}
temp_name[++i] = '\0' ;
str++ ;
i=-1 ;
while ( temp_no[++i] = *str )
str++ ;
}
void file_write ()
{
phonebook * temp = head ;
char data[40] ;
FILE * fp1 ;
fp1 = fopen ("contacts.txt" , "w") ;
while ( temp != NULL )
{
strcpy ( data , temp->name ) ;
strcat ( data , "=") ;
strcat ( data , temp->no ) ;
fprintf ( fp1 , "%s\n" , data) ;
temp=temp->next ;
}
fclose ( fp1 ) ;
}
void format_book ( phonebook ** temp )
{
if ( *temp == NULL )
return ;
format_book ( &( (*temp)->next ) ) ;
free ( *temp ) ;
*temp=NULL ;
}
int get_details ()
{
int response = 0 ;
printf("\n\n Enter Contact Name : " ) ;
gets(temp_name) ;
printf("\n Enter Mobile Number : " ) ;
gets(temp_no) ;
return error_check() ;
}
void new_node ( phonebook ** temp )
{
*temp = ( phonebook * ) malloc ( sizeof ( head ) ) ;
(*temp)->name = NULL ;
(*temp)->no = NULL ;
(*temp)->next = NULL ;
return ;
}
void fill_details ( phonebook * temp )
{
temp->name = ( char* ) malloc ( sizeof (char) * MAX_NAME ) ;
temp->no = ( char* ) malloc ( sizeof (char) * MAX_NO ) ;
strcpy ( temp->name , temp_name ) ;
strcpy ( temp->no , temp_no ) ;
return ;
}
void input_flush()
{
int c ;
while((c = getchar()) != '\n' && c != EOF) ;
}
void header ()
{
printf("\n %-50s" , "------------------------------------------------------- " ) ;
printf("\n %-8s %-29s %-11s" , "SL.NO" ,"CONTACT NAME " , "MOBILE NUMBER " ) ;
printf("\n %-50s" , "------------------------------------------------------- " ) ;
}
void footer ()
{
printf("\n %-50s" , "------------------------------------------------------- " ) ;
}
void print_record ( phonebook * temp )
{
printf ("\n %2d %-29s %-11s" , START , temp->name , temp->no ) ;
START++ ;
}
/* Arbitrary for strlwr */
void lowercase ( char * temp )
{
while ( *temp )
{
if (*temp>='A' && *temp<='Z' )
*temp= *temp+32 ;
temp++ ;
}
}
int error_check ( )
{
char * name = temp_name ;
char * no = temp_no ;
if ( strlen ( temp_name ) > MAX_NAME || strlen( temp_name ) <1 )
{
printf("\n\n Failed !\n Length exceeded/ No input for name { max 25 } \n") ;
return 1;
}
for ( ; *name ; name ++ )
if ( !isalpha (*name ) && *name != ' ' )
{
printf( "\n\n Failed !\n Invalid characters used for name { only alphabet , space allowed } \n" ) ;
return 1;
}
if ( strlen ( temp_no)!=10 )
{
printf("\n\n Failed !\n Invalid ten digit number { Ten Digits Please }.\n") ;
return 1;
}
if ( *temp_no <'7' )
{
printf("\n\n Failed !\n Currently No Numbers Exist on \'%c\' Series .\n" , *temp_no ) ;
return 1;
}
for ( ; *no ; no++ )
if ( ! isdigit (*no ) )
{
printf( "\n\n Failed !\n Invalid characters used for number { only digits allowed } \n" ) ;
return 1;
}
lowercase ( temp_name ) ;
if ( !duplicate_check() )
{
printf ("\n\n Successful ! \n ") ;
return 0;
}
}
int duplicate_check( )
{
phonebook * temp = head ;
while (temp!= NULL )
{
if ( strcmp( temp->name , temp_name )==0 )
{
printf ("\n\n Failed\n Contact Exists with Same Name ! ") ;
return 1 ;
}
if ( strcmp( temp->no , temp_no )==0 )
{
printf ("\n\n Failed\n Number Associated with \" %s \". " , temp->name ) ;
return 1 ;
}
temp=temp->next ;
}
return 0 ;
}