//HEADER FILES
#include<iostream.h>
#include<fstream.h>
#include<conio.h>
#include<stdio.h>
#include<string.h>
#include<iomanip.h>
#include<dos.h>

 
struct node	//The basic linked node declaration
{
	unsigned long recno;
	char pin[15];
	char name[64];
	node *link;
} *first,*ptr1,*ptr2,*ptr,*temp;
 
class person	//The global class from which we are managing the file "phoneno.dat"
{
	private:unsigned long record_id;
	char person_name[64];
	char res_address[64];
	char res_pincode[15];
	char res_phone_no1[15];
	char occu_pation[25];
	char company_name[25];
	char off_address[25];
	char off_pincode[15];
	char off_phone_no1[15];
	
	public:
	person()	//default constructor
	{
		record_id=0;
		strcpy(person_name,"");
		strcpy(res_address,"");
		strcpy(res_pincode,"");
		strcpy(res_phone_no1,"");
		strcpy(occu_pation,"");
		strcpy(company_name,"");
		strcpy(off_address,"");
		strcpy(off_pincode,"");
		strcpy(off_phone_no1,"");
		
	}
 
	unsigned long get_rec_no();
	void get_data();
	void show_data();
	void add_object();
	void make_index();
	void sort_name();
	void sort_recno();
	void sort_pin();
	void show_object();
	void sort_print();
	void del_object();
	void modify_object();
	void search_object();
	void sort_object();
	void reports();
}pers;

unsigned long person::get_rec_no()	//gets the lowest +ve unclaimed record id
{
	int found=0;
	unsigned long rec_no,temp_recno;
	struct node1
	{
		unsigned long recno;
		node1 *link;
	};
	node1 *start,*ptr,*ptr1,*ptr2;
	fstream infile;
	infile.open("phoneno.dat",ios::in|ios::binary);
	infile.seekg(0,ios::end);
	int n=infile.tellg();
	infile.close();
	if(n==0)
		rec_no=1;
	else
	{
		infile.open("phoneno.dat",ios::in|ios::binary);
		start=ptr=new node1;
		infile.seekg(0,ios::beg);
		infile.read((char*)&pers,sizeof(pers));
		while(!infile.eof())
		{
			ptr->recno=record_id;
			ptr->link=new node1;
			ptr=ptr->link;
			infile.read((char*)&pers,sizeof(pers));
		}
		ptr->link=NULL;
		ptr1=start;
		while(ptr1->link!=NULL)	//find the largest occupied record no
		{
			ptr2=ptr1->link;
			while(ptr2!=NULL)
			{
				if(ptr2->recno < ptr1->recno)
				{
					temp_recno=ptr2->recno;
					ptr2->recno=ptr1->recno;
					ptr1->recno=temp_recno;
				}
				ptr2=ptr2->link;
			}
			ptr2=ptr1->link;
			ptr1=ptr2;
		}
		ptr1=start;
		while(ptr1!=NULL && found!=1)
		{
			ptr2=ptr1;
			ptr1=ptr1->link;
			if((ptr2->recno)+1!=ptr1->recno)
			{
				rec_no=(ptr2->recno)+1;
				found=1;
			}
		}
		if(found!=1)rec_no=(ptr2->recno)+1;
		ptr=start;
		
		//clear up the memory lest memory leaks
		while(start!=NULL)
		{
			start=start->link;
			delete ptr;
		}
	}
    return rec_no;
}

void person::get_data()	//function to enter the values to the class variable
{
	clrscr();
	record_id=pers.get_rec_no();
    gotoxy(5,7);	//move cursor to position (5,7)
    cout<<"ENTER THE NAME---------------------------> ";
    gets(person_name);
    gotoxy(5,8);
    cout<<"RESIDENTIAL ADDRESS----------------------> ";
    gets(res_address);
    gotoxy(5,9);
    cout<<"ENTER RESIDENTIAL PINCODE----------------> ";
    gets(res_pincode);
    gotoxy(5,10);
    cout<<"ENTER RESIDENTIAL PHONE NO---------------> ";
    gets(res_phone_no1);
    gotoxy(5,11);
    cout<<"ENTER THE OCCUPATION---------------------> ";
    gets(occu_pation);
    gotoxy(5,12);
    cout<<"ENTER COMPANY'S NAME---------------------> ";
    gets(company_name);
    gotoxy(5,13);
    cout<<"ENTER COMPANY'S ADDRESS------------------> ";
    gets(off_address);
    gotoxy(5,14);
    cout<<"ENTER OFFICE PINCODE---------------------> ";
    gets(off_pincode);
    gotoxy(5,15);
    cout<<"ENTER OFFICE PHONE NO--------------------> ";
    gets(off_phone_no1);
    gotoxy(5,16);
    clrscr();
}
 
 void person::show_data()	//view the the class members
 {
     clrscr();
     gotoxy(5,2);
     cout<<"RECORD NUMBER----------------------------->"<<record_id;
     gotoxy(5,3);
     cout<<"NAME-------------------------------------->"<<person_name;
     gotoxy(5,4);
     cout<<"RESIDENTIAL ADDERSS----------------------->"<<res_address;
     gotoxy(5,5);
     cout<<"RESIDENTIAL PINCODE----------------------->"<<res_pincode;
     gotoxy(5,6);
     cout<<"RESIDENTIAL PHONE NO---------------------->"<<res_phone_no1;
     gotoxy(5,7);
     cout<<"OCCUPATION-------------------------------->"<<occu_pation;
     gotoxy(5,8);
     cout<<"COMPANY's NAME---------------------------->"<<company_name;
     gotoxy(5,9);
     cout<<"COMPANY's ADDRESS------------------------->"<<off_address;
     gotoxy(5,10);
     cout<<"OFFICE PINCODE---------------------------->"<<off_pincode;
     gotoxy(5,11);
     cout<<"OFFICE PHONE NO--------------------------->"<<off_phone_no1;
     gotoxy(10,20);
     cout<<"PRESS ANY KEY TO CONTINUE";
     getch();
}
 
void person::add_object()	//write the entered data in class 'person' to the file
{
	fstream file;
    char choice='y';
    while(choice=='y')
    {
		file.open("phoneno.dat",ios::app|ios::binary);
		get_data();
		file.write((char*)&pers,sizeof(pers));
		file.flush();
		file.close();
		clrscr();
		gotoxy(10,11);
		cout<<"ANY MORE RECORDS YOU WANNA ADD<<Y/N>>-------------->";
		cin>>choice;
     }
}

void person::del_object()	//delete a record based on its record id no.
{
	fstream infile,outfile;
    unsigned long rec_no;
    clrscr();
    cout<<"ENTER THE RECORD ID.NO.TO BE DELETED--------->";
    cin>>rec_no;
    infile.open("phoneno.dat",ios::in|ios::binary);
    infile.seekg(0);
    outfile.open("tempno.dat",ios::app|ios::binary);
	//As the file cannot be modified directly, we create a temporary file where we don't copy the record.
    infile.read((char*)&pers,sizeof(pers));
    while(!infile.eof())
    {
		if(pers.record_id!=rec_no)
			outfile.write((char*)&pers,sizeof(pers));
		outfile.flush();
		infile.read((char*)&pers,sizeof(pers));
     }
	infile.close();
	outfile.close();
	//Replace the original file with the temporary file.
	remove("phoneno.dat");
	rename("tempno.dat","phoneno.dat");
}

void person::search_object()	//searching and counting of records based on the user's choice
{
	fstream infile;
    int search_choice;
    unsigned long rec_no;
    char phno[15];
    char name[64];
    do
    {
		clrscr();
		int counter=0;//for counting values
		gotoxy(22,7);
		cout<<"  SEARCH MENU    ";
		gotoxy(22,9);
		cout<<"-----------------";
		gotoxy(22,11);
		cout<<setiosflags(ios::left) << setw(30)<<"RECORD ID NO."<<"...1";
		gotoxy(22,12);
		cout<<setiosflags(ios::left) << setw(30)<<"NAME"<<"...2";
		gotoxy(22,13);
		cout<<setiosflags(ios::left) << setw(30)<<"PHONE NO."<<"...3";
		gotoxy(22,14);
		cout<<setiosflags(ios::left) << setw(30)<<"EXIT SEARCH MENU"<<"...4";
		gotoxy(1,20);
		cout<<"ENTER THE FIELD CHOICE ACCORDING TO WHICH A RECORD";
		cout<<"IS TO BE SEARCHED--------->";
		cin>>search_choice;
		switch(search_choice)
		{
			case 1:
				clrscr();
				cout<<"\n ENTER THE RECORD ID.NO. TO BE SEARCHED----->";
				cin>>rec_no;
				infile.open("phoneno.dat",ios::in|ios::binary);
				infile.seekg(0,ios::beg);
				infile.read((char*)&pers,sizeof(pers));
				while(!infile.eof())
				{
					if(pers.record_id==rec_no)	//count record no matching the one being searched
					{
						counter++;
						pers.show_data();
					}
					infile.read((char*)&pers,sizeof(pers));
				}
				infile.close();
				gotoxy(20,24);
				cout<<"RECORDS FOUND="<<counter;
				getch();
				break;

			case 2:
				clrscr();
				cout<<"\n ENTER THE NAME TO BE SEARCHED---------->";
				gets(name);
				infile.open("phoneno.dat",ios::in|ios::binary);
				infile.seekg(0,ios::beg);
				infile.read((char*)&pers,sizeof(pers));
				while(!infile.eof())
				{
					if(strcmpi(pers.person_name,name)==0)
					{
						counter++;
						pers.show_data();
					}
					infile.read((char*)&pers,sizeof(pers));
				}
				infile.close();
				gotoxy(20,24);
				cout<<"RECORDS FOUND="<<counter;
				getch();
				break;

			case 3:
				clrscr();
				cout<<"\nENTER THE PHONE NO.TO BE SEARCHED-------->";
				cin>>phno;
				infile.open("phoneno.dat",ios::in|ios::binary);
				infile.seekg(0,ios::beg);
				infile.read((char*)&pers,sizeof(pers));
				while(!infile.eof())
				{
					if(strcmp(pers.res_phone_no1,phno)==0||strcmp(pers.off_phone_no1,phno)==0)
					{
						counter++;
						pers.show_data();
					}
					infile.read((char*)&pers,sizeof(pers));
				}
				infile.close();
				gotoxy(20,24);
				cout<<"RECORDS FOUND="<<counter;
				getch();
				break;

			case 4:
				clrscr();
				gotoxy(22,15);
				cout<<"YOU HAVE ENDED THE SEARCH SESSION";
				gotoxy(27,18);
				cout<<"THANK YOU!";
				delay(700);	//This is a strictly dos command. For windows use 'Sleep(int);'
				break;
		}
    }while(search_choice!=4);
}

void person::modify_object()	//modify a record present in the file
{
	fstream file;
    unsigned long code;
    int modify_choice;
    do
    {
		clrscr();
		gotoxy(22,7);
		cout<<"     MODIFY MENU     ";
		gotoxy(22,8);
		cout<<"---------------------";
		gotoxy(22,10);
		cout<<setiosflags(ios::left) << setw(40)<<"RESIDENTIAL INFORMATON"<<"...1";
		gotoxy(22,11);
		cout<<setiosflags(ios::left) << setw(40)<<"OFFICIAL INFORMATION"<<"...2";
		gotoxy(22,12);
		cout<<setiosflags(ios::left) << setw(40)<<"EXIT"<<"...3";
		gotoxy(22,13);
		cout<<"SELECT THE INFORMATION TO BE CHANGED : ";
		gotoxy(22,14);
		cout<<"ENTER YOUR CHOICE----->";
		cin>>modify_choice;
		//The files are modified by looking for the position of the entered record no. and then modifying the record
		if(modify_choice!=3)
		{
			clrscr();
			gotoxy(10,15);
			cout<<"ENTER THE RECORD NO. OF THE PERSON---->";
			cin>>code;
			file.open("phoneno.dat",ios::in|ios::out);
			file.seekg(0,ios::beg);
			file.read((char*)&pers,sizeof(pers));
			int n=file.tellg();
			while(!file.eof())
			{
				if(pers.record_id==code)
				{
					switch(modify_choice)
					{
						case 1:
							clrscr();
							cout<<"***** The Details of "<<pers.person_name;
							cout<<"\n\nThe old Address is :-"<<pers.res_address;
							cout<<"\nENTER NEW RESIDENTIAL ADDRESS-------------->";
							gets(pers.res_address);
							cout<<"The old Pin code is :-"<<pers.res_pincode;
							cout<<"\nENTER NEW PINCODE-------------------------->";
							gets(pers.res_pincode);
							cout<<"The old Phone No.is :-"<<pers.res_phone_no1;
							cout<<"\nENTER NEW RESIDENTIAL PHONE NO------------->";
							gets(pers.res_phone_no1);
							file.seekg(n-sizeof(pers));
							file.write((char*)&pers,sizeof(pers));
							file.flush();
							break;
						case 2:
							clrscr();
							cout<<"\nENTER THE OCCUPATION------------->";
							gets(pers.occu_pation);
							cout<<"\nENTER NEW COMPANY'S NAME--------->";
							gets(pers.company_name);
							cout<<"\nENTER NEW OFFICE ADDRESS--------->";
							gets(pers.off_address);
							cout<<"\nENTER NEW OFFICE PIN CODE-------->";
							gets(pers.off_pincode);
							cout<<"\nENTER NEW OFFICE PHONE NO-------->";
							gets(pers.off_phone_no1);
							file.seekg(n-sizeof(pers));
							file.write((char*)&pers,sizeof(pers));
							file.flush();
							break;
					}
				}
				file.read((char*)&pers,sizeof(pers));
				n=file.tellg();
			}
			file.close();
		}
	}while(modify_choice!=3);
		clrscr();
		gotoxy(22,10);
		cout<<"YOU ENDED MODIFY INFORTION SESSION";
		gotoxy(30,13);
		cout<<"THANK YOU";
		delay(700);
}

void ex_change()	//exchange the lvalues in pointers ptr1 & ptr2
{
	temp=new node;
	temp->link=NULL;
	temp->recno=ptr2->recno;
	strcpy(temp->pin,ptr2->pin);
	strcpy(temp->name,ptr2->name);
	ptr2->recno=ptr1->recno;
	strcpy(ptr2->pin,ptr1->pin);
	strcpy(ptr2->name,ptr1->name);
	ptr1->recno=temp->recno;
	strcpy(ptr1->pin,temp->pin);
	strcpy(ptr1->name,temp->name);
	delete temp;
 }

void person::make_index()	//create a linked stack containing name, record id no., pin no.
{
	fstream infile;
	first=new node;
	ptr=first;
	infile.open("phoneno.dat",ios::in|ios::binary);
	infile.seekg(0,ios::beg);
	infile.read((char*)&pers,sizeof(pers));
	while(!infile.eof())
	{
		ptr->recno=record_id;
		strcpy(ptr->pin,res_pincode);
		strcpy(ptr->name,pers.person_name);
		ptr->link=new node;
		ptr=ptr->link;
		infile.read((char*)&pers,sizeof(pers));
	}
	ptr->link=NULL;
	infile.close();
}

void person::sort_name()	//sort the records in the liked stack made by name in ascending order
{
	pers.make_index();
	ptr1=first;
	while(ptr1->link!=NULL)
	{
		ptr2=ptr1->link;
		while(ptr2->link!=NULL)
		{
			if(strcmpi(ptr2->name,ptr1->name)<0)
				ex_change();
			ptr2=ptr2->link;
		}
		ptr2=ptr1->link;
		ptr1=ptr2;
    }
}

void person::sort_recno()	//sort the records in the liked stack by record no. in ascending order
{
	pers.make_index();
	ptr1=first;
	while(ptr1->link!=NULL)
	{
		ptr2=ptr1->link;
		while(ptr2->link!=NULL)
		{
			if(ptr2->recno<ptr1->recno)
				ex_change();
			ptr2=ptr2->link;
		}

		ptr2=ptr1->link;
		ptr1=ptr2;
	}
}

void person::sort_pin()	//sort the records in the liked stack by pin no. in ascending order
{
	pers.make_index();
	ptr1=first;
	while(ptr1->link!=NULL)
	{
		ptr2=ptr1->link;
		while(ptr2!=NULL)
		{
			if(strcmpi(ptr2->pin,ptr1->pin)<0)
				ex_change();
			ptr2=ptr2->link;
		}
		ptr2=ptr1->link;
		ptr1=ptr2;
    }
}

void person::sort_print()	//display the sorted stack node by node
{
	fstream infile;
	ptr=first;
	while(ptr!=NULL)
	{
		infile.open("phoneno.dat",ios::in|ios::binary);
		infile.seekg(0,ios::beg);

		//convert the entire database into a linked stack
		infile.read((char*)&pers,sizeof(pers));
		while(!infile.eof())
		{
			if(ptr->recno==pers.record_id)
			{
				pers.show_data();
				infile.seekg(0,ios::end);
			}
			infile.read((char*)&pers,sizeof(pers));
		}
		infile.close();
		ptr=ptr->link;
    }
}

void del_index()	//clears up the stack completely
{
	while(first!=NULL)
	{
		ptr=first;
		first=first->link;
		delete ptr;
	}
}

void person::sort_object()	//function to display sort menu
{
	int sort_choice;
	do
	{
		clrscr();
		gotoxy(22,7);
		cout<<"    SORT MENU    ";
		gotoxy(22,8);
		cout<<"-------------------";
		gotoxy(22,10);
		cout<<setiosflags(ios::left) << setw(40)<<"SORTED RECORDS NOS."<<"...1";
		gotoxy(22,11);
		cout<<setiosflags(ios::left) << setw(40)<<"SORTED NAMES"<<"...2";
		gotoxy(22,12);
		cout<<setiosflags(ios::left) << setw(40)<<"SORTED PINCODES NOS."<<"...3";
		gotoxy(22,13);
		cout<<setiosflags(ios::left) << setw(40)<<"EXIT SORT MENU"<<"...4";
		gotoxy(22,20);
		cout<<"ENTER YOUR CHOICE NO.----->";
		cin>>sort_choice;
		switch(sort_choice)
		{
			case 1:
				clrscr();
				pers.sort_recno();
				pers.sort_print();
				del_index();//clear up the stack to prevent memory leaking
				delay(200);
				break;
			case 2:
				clrscr();
				pers.sort_name();
				pers.sort_print();
				del_index();
				delay(200);
				break;
			case 3:
				clrscr();
				pers.sort_pin();
				pers.sort_print();
				del_index();
				delay(200);
				break;
			case 4:
				clrscr();
				gotoxy(22,10);
				cout<<"YOU ENDED THE SORTED SESSION";
				gotoxy(27,13);
				cout<<"THANK YOU!";
				delay(700);
				break;
		}
    }while(sort_choice!=4);
}

void person::reports()	//function to display report menu (which uses a table to display)
{
	fstream infile;
	int report_choice;
	do
	{
		clrscr();
		gotoxy(22,7);
		cout<<"   REPORT MENU    ";
		gotoxy(22,8);
		cout<<"------------------";
		gotoxy(5,10);
		cout<<setiosflags(ios::left) << setw(61)<<"SORTED LIST OF NAMES WITH RESIDENCE AND OFFICE PHONE NOS"<<setw(5)<<"...1";
		gotoxy(5,11);
		cout<<setiosflags(ios::left) << setw(61)<<"LIST OF NAMES WITH THIER OFFICE DETAILS"<<setw(5)<<"...2";
		gotoxy(5,12);
		cout<<setiosflags(ios::left) << setw(61)<<"LIST OF NAMES WITH THEIR RECORD NOS.AND RESIDENTIAL ADDRESS"<<setw(5)<<"...3";
		gotoxy(5,13);
		cout<<setiosflags(ios::left) << setw(61)<<"EXIT REPORT SESSION"<<setw(5)<<"...4";
		gotoxy(5,14);
		cout<<"ENTER YOUR CHOICE NO.------>";
		cin>>report_choice;
		switch(report_choice)
		{
			case 1:
				clrscr();
				cout<<setiosflags(ios::left) << setw(28)<< "NAME" << setw(30)<< "RES.PHONE NO." << setw(30)<< "OFFICE PHONE NO.";
				cout<<"\n";
				cout<<"\n-------------------------------------------------------------------------------";
				pers.sort_name();
				ptr=first;
				while(ptr!=NULL)
				{
					infile.open("phoneno.dat",ios::in|ios::binary);
					infile.seekg(0,ios::beg);
					infile.read((char*)&pers,sizeof(pers));
					while(!infile.eof())
					{
						if(ptr->recno==pers.record_id)
						{
							cout<<"\n";
							cout<<setiosflags(ios::left)<<setw(28)<<pers.person_name<<setw(30)<<pers.res_phone_no1<<setw(30) <<pers.off_phone_no1;
							infile.seekg(0,ios::end);
						}
						infile.read((char*)&pers,sizeof(pers));
					}
					infile.close();
					ptr=ptr->link;
				}
				del_index();
				gotoxy(20,40);
				cout<<"PRESS ANY KEY TO CONTINUE";
				getch();
				break;
			case 2:
				clrscr();
				infile.open("phoneno.dat",ios::in|ios::binary);
				infile.seekg(0,ios::beg);
				infile.read((char*)&pers,sizeof(pers));
				while(!infile.eof())
				{
					gotoxy(10,5);
					cout<<"NAME-------------------->"<<pers.person_name;
					gotoxy(10,6);
					cout<<"COMPNAY'S NAME---------->"<<pers.company_name;
					gotoxy(10,7);
					cout<<"COMPANY'S ADDESS-------->"<<pers.off_address;
					gotoxy(10,8);
					cout<<"OFFICE PHONE NO--------->"<<pers.off_phone_no1;
					gotoxy(10,10);
					cout<<"PRESS ANY KEY TO CONTINUE";
					getch();
					infile.read((char*)&pers,sizeof(pers));
					clrscr();
				}
				infile.close();
				break;
			case 3:
				clrscr();
				cout<<setiosflags(ios::left)<<setw(16)<<"\nREC NO." << setw(15)<< "NAME" << setw(35)<< "RES.ADDRESS" << setw(18)<< "RES PHONE NO";
				cout<<"\n-------------------------------------------------------------------------------";
				infile.open("phoneno.dat",ios::in|ios::binary);
				infile.seekg(0,ios::beg);
				infile.read((char*)&pers,sizeof(pers));
				while(!infile.eof())
				{
					cout<<"\n";
					cout<<setiosflags(ios::left)<<setw(15)<<pers.record_id<<setw(15)<<pers.person_name<<setw(35)<<pers.res_address<<setw(18)<<res_phone_no1;
					infile.read((char*)&pers,sizeof(pers));
				}
				infile.close();
				gotoxy(20,40);
				cout<<"PRESS ANY KEY TO CONTINUE";
				getch();
				break;
			case 4:
				clrscr();
				gotoxy(22,10);
				cout<<"YOU HAVE ENDED REPORT SESSION";
				gotoxy(27,30);
				cout<<"THANK YOU";
				delay(700);
				break;
		}
	}
	while(report_choice!=4);
}

void main()	//MAIN FUNCTION
{
	int main_choice;
	do
	{
		clrscr();
		gotoxy(22,7);
		cout<<"    MAIN MENU       ";
		gotoxy(25,11);
		cout<<setiosflags(ios::left) << setw(30)<<"  ADD A NEW RECORD"<<"...1";
		gotoxy(25,12);
		cout<<setiosflags(ios::left) << setw(30)<<"  DELETE A RECORD"<<"...2";
		gotoxy(25,13);
		cout<<setiosflags(ios::left) << setw(30)<<"  MODIFY A RECORD"<<"...3";
		gotoxy(25,14);
		cout<<setiosflags(ios::left) << setw(30)<<"  SEARCH A RECORD"<<"...4";
		gotoxy(25,15);
		cout<<setiosflags(ios::left) << setw(30)<<"  SORTED INFORMATION"<<"...5";
		gotoxy(25,16);
		cout<<setiosflags(ios::left) << setw(30)<<"  REPORTS"<<"...6";
		gotoxy(25,17);
		cout<<setiosflags(ios::left) << setw(30)<<"  EXIT"<<"...7";
		gotoxy(25,20);
		cout<<"ENTER YOUR CHOICE NO.--------->";
		cin>>main_choice;
 
		switch(main_choice)
		{
			case 1:
				pers.add_object();
				break;
			case 2:
				pers.del_object();
				break;
			case 3:
				pers.modify_object();
				break;
			case 4:
				pers.search_object();
				break;
			case 5:
				pers.sort_object();
				break;
			case 6:
				pers.reports();
				break;
			case 7:
				clrscr();
				gotoxy(22,10);
				cout<<"YOU HAVE ENDED THE SESSION";
				gotoxy(27,13);
				cout<<"THANK YOU";
				delay(1000);
				break;
		}
	}while(main_choice!=7);
}