/* 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.

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.

This article has been dead for over six months. Start a new discussion instead.