/* v_regdb.c ****************************************************************/
/*                                                                          */
/*                                                                          */
/*                                                                          */
/*	This is a maintenance program for an existing Vehicle Database.          */
/* The program is an interactive menu system, which allows the user to      */
/*	edit, delete and insert records into an existing database.               */
/*	All input is validated with any relevent error messages, should an       */
/*	error occur. In the event of an error the input is not written to file   */
/*	and the user is returned to the Main Menu screen.                        */
/*                                                                          */
/*                                                                          */
/*                                                                          */
/****************************************************************************/

/* Header files *************************************************************/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <conio.h>
#include <ctype.h>
#include <time.h>

#define   FILENAME "VREGDB.DAT"/* This is the actual file used -            */
										 /* initialized & working (26000 records)     */
										 /* record no. 000 - 25999.                   */
/*Structure Declarations ****************************************************/
						  /********************************************************/
struct t_date{      /*  tag ~ t_date stores the  tempory date & checks if a */
						  /* specific file has existing data or not .             */
	int  temp_day;   /* format DD.                                           */
	int  temp_month; /* format MM.                                           */
}temp_date;         /* var temp_date is declared as an instace of struct    */
						  /* t_date.                                              */
						  /********************************************************/
										 /*********************************************/
struct date{                   /* tag ~ date stores the actual date.        */
	int  day;                   /* format DD.                                */
	int  month;                 /* format MM.                                */
};                             /*********************************************/
                               /*********************************************/   
struct pnc{                    /*tag ~ pnc stores the main data input.      */
	int  RecNo;                 /* Record Number.                            */
	char V_RegNo   [8];         /* Vehicle Registration Number.              */
	struct date V_Regdate;      /* struct of type date.                      */
	char V_Maker  [11];         /* Vehicle Manufacturer.                     */
	char V_Model  [11];         /* Vheicle Model.                            */
	char V_Colour  [9];         /* Vehicle Colour.                           */
	char V_Owner  [26];         /* Vehicle Owners Name.                      */
	char V_Address[31];         /* Vehicle Owners Address.                   */
	struct date V_Expiry;       /* struct of type date.                      */
}vehicle;                      /* var vehicle is declared as an instance    */
										 /* of struct pnc.                            */
										 /*********************************************/
/*Function Declarations *****************************************************/
										 /*********************************************/
int  validate_VReg(char *reg); /* Validates The Vehicle Reg Format & returns*/
										 /* an error message or a valid Record Number */

void error_scr(char *reason, int delay);/* Dislays any errors on the screen */

void gotoxy(int col, int row); /* Mainly used for screen positioning        */

void clrscr(void);             /* Used to clear screen between displays     */

void pause_msg(int ln_x, int ln_y,char *msg, int delay);/*Displays a message*/
										 /* on the screen for a given length of time. */
void input_details(void);      /*Inputs data from the user.                 */

										 /*********************************************/
/*Globle Variables **********************************************************/
										 /*********************************************/
int  ch,flag,recno;
char temp_regno[8],choice, Str;
int  ESC = 27;                /* Esc Used to escape or end program          */

FILE *fp;                     /* Pointer to FILE                            */
										/**********************************************/
/*Star of Main **************************************************************/
void main()
{
/* Test to see if the file exists and it can be opened in read mode.
  If an error is detected print a message & terminate the program. */
	if((fp=fopen(FILENAME,"rb"))==NULL)
	{
		error_scr("ERROR ! READING FILE!", 3);
		exit(1);
	}

	while(1)           /* Start of infinate loop */
	{
		
/* Start of main menu with a list of choises*/
		printf("\n%14s//¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯\\\\","");
		printf("\n%13s||%20sMAIN MENU%21s||","","","");
		printf("\n%14s\\\\________________________________________________//","");
		printf("\n\n\n%30s1 : Add New Vehicle"
					"\n\n%30s2 : Edit Details"
					"\n\n%30s3 : Delete Entry"
				 "\n\n%28sESC : Exit           [ ] ","","","","");
		gotoxy(51,13);
		choice = getch();
		switch(choice)
		{
			case '1' :/*If 1 is chosen then Add Vehicle Details page is displayed*/
			{
				clrscr();
				if((fp=fopen(FILENAME,"wb"))==NULL)
				{
					error_scr("ERROR ! READING FILE!", 3);
					exit(1);
				}
				printf("\n%14s//¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯\\\\","");
				printf("\n%13s||%15sADD VEHICLE DETAILS%16s||","","","");
				printf("\n%14s\\\\________________________________________________//","");
				gotoxy(18,7);printf("Enter Vehicle Reg No. : ");
				gets(vehicle.V_RegNo);

/* Flags are use mostley in validate_VReg() Function to determin wheather a
	specific event has taken place. If so they are set again within Validate_VReg()
	in order to inform the program how to execute the rest of the statements in
	case '1':  i.e. If an error is detcted while in the validation process an
	error message is displayed control is returned to main(); */

				flag=0;
				validate_VReg(vehicle.V_RegNo);
				if(flag==1)
					break;      /*Return to main menu */
				input_details();

/* The user is asked if they wish to add the new record. If they dont choose
	the letter y A message is displayed and the user is returned to the main menu.
	If y is chosen the record is added. */
				gotoxy(18,16);	printf("Are you sure you want to INSERT this record   [ ]");
				gotoxy(65,16);
				ch=toupper(getch());
				if(ch != 'Y')
				{
						pause_msg(32,17,"RECORD NOT INSERTED!",3);
						break;    /*Return to main menu */
				}
				fread(&vehicle,sizeof(vehicle),1,fp);   /* Read the file */

/* Check if the record exists. Write it to file if it dosent exist else display
	a message. */
	 		if(vehicle.V_Regdate.day == 99 || vehicle.V_Regdate.month == 99)
				{
					vehicle.V_Regdate.day=temp_date.temp_day ;
					vehicle.V_Regdate.month=temp_date.temp_month;
				 
					fwrite(&vehicle,sizeof(vehicle),1,fp);
					pause_msg(32,17,"RECORD ADDED!",3);
					break;      /*Return to main menu */
				}
				else
				{
					error_scr("A RECORD ALLREADY EXISTS!",3);
						break;   /*Return to main menu */
				}
			}
			case '2' :/*If 2 is chosen then ammend Vehicle Details page is displayed*/
			{
				clrscr();
				printf("\n%14s//¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯\\\\","");
				printf("\n%13s||%14sAMMEND VEHICLE DETAILS%14s||","","","");
				printf("\n%14s\\\\________________________________________________//","");
				gotoxy(18,7);printf("Enter Vehicle Reg No. : ");
				gets(vehicle.V_RegNo); 
				flag=1;
				validate_VReg(vehicle.V_RegNo);  /*Validate the registration number*/
				if(flag==1)                  /*flag is set to 1 if an error occured*/
					break;                    /*Return to main menu */

/*Test to see if the record exists, if not display a message*/
				if((vehicle.V_Regdate.day == 99) && (vehicle.V_Regdate.month== 99))
				{
					pause_msg(32,17,"RECORD DOSE NOT EXIST!",3);
						break;    /*Return to main menu */
				}
				flag=0;
/*If the record exists input all the details*/
				input_details();

/*Get confirmation before ammending the record*/
				gotoxy(18,16);printf("Are you sure you want to AMMEND this record   [ ]");
				gotoxy(65,16);ch=toupper(getch());
				if(ch != 'Y')
				{
					pause_msg(32,17,"RECORD NOT AMMENDED!",3);
						break;    /*Return to main menu */
				}
/* The record is then written, and confirmation
	is displayed*/
				fwrite(&vehicle,sizeof(vehicle),1,fp);
				pause_msg(32,17,"RECORD AMMENDED!",3);
					break;      /*Return to main menu */
			}

			case '3' :/*If 3 is chosen then delete Vehicle Details page is displayed*/
			{
				clrscr();
				printf("\n%14s//¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯\\\\","");
				printf("\n%13s||%14sDELETE VEHICLE DETAILS%14s||","","","");
				printf("\n%14s\\\\________________________________________________//","");
				gotoxy(18,7);printf("Enter Vehicle Reg No. : ");
				gets(temp_regno);
				flag=0;
				validate_VReg(temp_regno);
				if(flag==1)
					break;       /*Return to main menu */
/*A warning message is displayed on the screen and the user is prompted for
  confirmation to delete the record*/
				gotoxy(35,9);printf("WARNING!!");
				gotoxy(18,10);printf("Are you sure you want to DELETE this record   [ ]");
				gotoxy(65,10);	ch=toupper(getch());
				if(ch != 'Y')
				{
					pause_msg(32,17,"RECORD NOT DELETED!",3);
						break;     /*Return to main menu */
				}
				fread(&vehicle,sizeof(vehicle),1,fp);
				if(vehicle.V_Regdate.day==99 && vehicle.V_Regdate.month==99)
				{
					error_scr("REG NO.DOESN'T EXIST",3);
						break;     /*Return to main menu */
				}
/*If the record exists change the dates to 99 & write it to disc*/
				vehicle.V_Regdate.day=99 ;
				vehicle.V_Regdate.month=99;
				
				fwrite(&vehicle,sizeof(vehicle),1,fp);
				pause_msg(32,17,"RECORD DELETED!",3);
					break;           /*Return to main menu */
			}
/* If the Esc button is pressed the program terminates normally after displaying
	the exit screen*/
			case 27 :
			{
				fclose(fp);        /*Close the opened file*/
				clrscr();
				printf("\n%14s//¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯\\\\","");
				printf("\n%13s||%15sPROGRAM TERMINATED%17s||","","","");
				printf("\n%14s\\\\________________________________________________//","");
				printf("\n\n\n%20sThank You for using this Vehicle Database!"
						"\n\n\n\n%31sProgrammer : K.Angel"
						 "\n\n\n%38s2005.","","","","","","","");
						exit(0);     /* Normal termination  of the program */
						break;       /*This break is never reached */
			}
			default : /* If an invalid choise was made a message is displayed*/
			error_scr("INVALID CHOICE!",2);  /*Return to main menu after running
														/*error message */
		}
	}
}
/************************************************************** End of Main */

/* Functions ****************************************************************/
/****************************************************************************/
/* Func ~                                                                   */
/*          int validate_vReg( char *reg);                                  */
/*          ==============================                                  */
/*          This function is used to validate the format of the vehicle     */
/*          registration input by the user.                                 */
/*          It also creates a unique record number which is used to         */
/*          calculate the offset for the file pointer positioning.          */
/*          The record size (sizeof(vehicle)) is multiplied by the record   */
/*          number to give the offset from the begining of the file         */
/*          (SEEK_SET).                                                     */
/*          The file pointer is tested to see if it is starting off at      */
/*          position 0. The program will terminate with an error message    */
/*          if the statement is not true.                                   */
/*Arguments~                                                                */
/*          A string (vehicle regitration number) input by the user is      */
/*          passed to the function.                                         */
/*Returns ~                                                                 */
/*         nill                                                             */
/****************************************************************************/
int validate_VReg(char *reg)
{
	/*Local variable ~ only visable within Func validate_VReg();*/
	char *str, *str_ptr=vehicle.V_RegNo;
	int  j=0, x=0, i=0;

	while(i<7)
	{
/*Test Format of the Registration number*/
		if((!isalpha(reg[0]))||(!isdigit(reg[1]))||
			(!isdigit(reg[2]))||(!isdigit(reg[3]))||
			(!isalpha(reg[4]))||(!isalpha(reg[5]))||
			(!isalpha(reg[6])))
		{
/*If an error is detected print an error message and set the flag to 1 to
  inform the next program executable statement that an error has occured*/
			error_scr("ERROR - Invalid Reg Format", 2);
			flag = 1;
			return (0);
		}
/*If no error in the file format. Convert the first Charater to uppercase*/
		if(i==0)
		{
			ch = toascii(reg[0]);
			ch=toupper(ch);
			str_ptr++;
		}
/*Covert the character into its integer value*/
		if(i==1)
		{  str = str_ptr;
			j= atoi(str);
		}
		i++;
	}
/*Formula to create th record number*/
	x = ch - 65;
	recno = (x * 1000) + j;
/*Move the fp to the correct possition & test it if an error is detected display
  an error message and terminate the program*/
	if(fseek(fp,(recno * sizeof(vehicle)),SEEK_SET)!=0)
	{
		error_scr("FILE READ ERROR! EXITING PROGRAM",4);
		exit(1);
	} 

/*The flag is set to 0 in Add case 1 so at this point the program will continue
 to execute passed this flag test. In case 2 the flag is set to 1 so at this
 flag test the program returns to main(). The flag is reset to 0 to indecate
 no errors occured*/
	if(flag == 1)
	{
		flag=0;
		return(0);
	}
	/*Display the vehicle record number only in case 1 as case 2 never
	  reaches here*/
	gotoxy(18,5);printf("VEHICLE RECORD NUMBER : %d", recno);
	vehicle.RecNo = recno;

	return(0);
}
/********************************************** End of Func validate_VReg() */

/****************************************************************************/
/* Func ~                                                                   */
/*          void error_scr(char *msg, int delay);                           */
/*          =====================================                           */
/*          This function displays a message under the title ERROR for a    */
/*          short period of time. The message is displayed through a        */
/*          seperate function call.                                         */
/*Arguments~                                                                */
/*          There are two arguments passed to this function.                */
/*          First is a string which is used to dislay the appopriate        */
/*          message on the screen.                                          */
/*          The second argument is used to store a number wich determins    */
/*          the length of time to display the message.                      */
/*Returns ~                                                                 */
/*         void.                                                            */
/****************************************************************************/
void error_scr(char *msg, int delay)
{
	clrscr();
	printf("\n%14s//¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯\\\\","");
	printf("\n%13s||%21sERROR!%23s||","","","");
	printf("\n%14s\\\\________________________________________________//","");
	pause_msg(30,9,msg,delay); /*Display a message*/
}
/************************************************** End of Func error_scr() */

/****************************************************************************/
/* Func ~                                                                   */
/*          void pause_msg(int ln_x, int ln_y,char *msg, int delay);        */
/*          ========================================================        */
/*          This function displays a message on the screen for a given      */
/*          amount of time.                                                 */
/*          It uses the standard C function time() & is measured in seconds.*/
/*Arguments~                                                                */
/*          There are four arguments passed to this function.               */
/*          1. int ln_x & int ln_y position the message on screen.          */
/*          3. char *msg the actual message.                                */
/*          4. int delay the length of time to display the message.         */
/*Returns~                                                                  */
/*        void.                                                             */
/****************************************************************************/
void pause_msg(int ln_x, int ln_y,char *msg, int delay)
{
	time_t start;
	time_t current;
	time(&start);
	gotoxy(ln_x,ln_y);printf(msg);fflush(stdin);
	do
	{
		time(&current);
	}
	while(difftime(current,start) < delay); 
		clrscr();
}
/**************************************************** End of Func pause_msg */

/****************************************************************************/
/* Func ~                                                                   */
/*          void input_details(void);                                       */
/*          =========================                                       */
/*          This function allows the user to input data to store.           */
/*          It's a simple function that cuts down on repetative coding      */
/*Arguments~                                                                */
/*          void                                                            */
/*Returns ~                                                                 */
/*          void                                                            */
/****************************************************************************/
void input_details(void)
{
	gotoxy(24,8); printf("Reg Date  DD/MM : ");
	scanf("%d%[ -/.,\n]%d",&temp_date.temp_day,&Str, &temp_date.temp_month);
	fflush(stdin);
	gotoxy(24,9); 	printf("Vehicle Make    : ");
	gets(vehicle.V_Maker);
	gotoxy(24,10);	printf("Model           : ");
	gets(vehicle.V_Model);
	gotoxy(24,11);	printf("Colour          : ");
	gets(vehicle.V_Colour);
	gotoxy(24,12);	printf("Owners Name     : ");
	gets(vehicle.V_Owner);
	gotoxy(24,13);	printf("Address         : ");
	gets(vehicle.V_Address);
	gotoxy(22,14);	printf("Expiry Date DD/MM : ");
	scanf("%2d%[ -/.,\n]%2d",&vehicle.V_Expiry.day,&Str,&vehicle.V_Expiry.month);
   fflush(stdin);
}
/********************************************** End of Func input_details() */

/********************************************************* End of Functions */

Please don't post any length of code without using code tags. -Narue
:?:

>void main()
Wrong, main returns int.

>gets(vehicle.V_RegNo);
Wrong, gets can never be made safe. Use fgets on stdin instead.

>fflush(stdin);
Wrong, fflush is only defined for output streams. stdin is an input stream. The equivalent correct code is:

int ch;
while ( ( ch = getchar() ) != EOF && ch != '\n' )
  ;

Everything else is tolerable. It could be made better, but that would require a very lengthy post on my part, and I lack the time to do it properly.

Thank you for taking the time to go through it and for the tips I'll continue to persivere again thanks.

What Other limitations can you find?

Your main is a tad long. You could easily modularize that into several smaller functions. It would make understanding how your program works much easier.

As opposed to using a switch statement would you suggest sepperate functions for each case?

You could still use a switch, but each case would call a function instead of have such large blocks of code:

switch ( choice ) {
case '1':
  add_vehicle();
  break;
case '2':
  modify_vehicle();
  break;
case '3':
  remove_vehicle();
  break;
case ESC:
  end_program();
  break;
default:
  error_scr("INVALID CHOICE!",2);
  break;
}

Not only is that shorter and easier to grasp at a glance, the code is self documenting. You can understand what's going on without a slew of comments.

Thanks I'll give it a try - will speak soon

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.