Database not outputting on C even though I'm saving - c

I am doing an Order's Database in which in this case deals with a transaction.
The procedure is as follows:
First the Customer enters his ID. If it is not found, it exits to the main menu otherwise it proceeds (The Customer MUST have an ID registered within the database which is stored on another file)
It asks which Product they are going to buy (it asks for PRODUCT NAME [that's how lecturer wanted it by Name] and if it is not found it exists otherwise it proceeds
It asks how many they are going to buy and checks whether there is enough in Stock. If it is it proceeds otherwise asks the user whether they want to input another number or exit
Price is calculated automatically and a Confirmation is ASKED. if Customer CONFIRMS then the saving is done otherwise it exits to Main Menu
Now my problem is that even though my STRUCT is saving, whenever I come to output ANY ORDER in the database (for now testing as I need the LAST order of a customer first) The Database is always showing as EMPTY. Below is the Coding [it is rather long I am sorry but I cannot understand where is wrong] and also will provide the List All function.
Screenshots are provided as well to understand better how the program works:
void customerOrder()
{
int checkID = 0; //variable to hold the ID input
char ch;
char ch1;
char ch2;
char option;
char tempName [100];
int order = 0;
int tempStock = 0;
float tempPrice = 0;
printf ("\n\n\n\n\t\t ************* Add Customer Order *************\n \n \n");
// ----------- LOADING OF THE 3 DATA FILES -----------//
if ((ofp = fopen ("orders.dat","a+b")) == NULL)
{
fputs ("Error! Cannot open orders.dat\n",stderr);
system ("PAUSE");
orderMainMenu();
}
rewind (ofp);
if ((cfp = fopen ("customers.dat","r"))== NULL)
{
fputs ("Error! Cannot open customers.dat\n",stderr);
system ("PAUSE");
orderMainMenu();
}
rewind (cfp);
if ((pfp = fopen ("products.dat","r+b"))== NULL)
{
fputs ("Error! Cannot open products.dat\n",stderr);
system ("PAUSE");
orderMainMenu();
}
rewind (pfp);
//-------- Confirm whether to start Order ------------//
printf ("WARNING: In order for an Order to be made, the Customer must be in the Database\n");
printf ("Are you sure you want to continue? Y or N\n");
while (getchar() !='\n')
{
}
ch1 = getchar ();
if (ch1 == 'Y' || ch1 == 'y')
{
// ---- INPUT OF CUSTOMER ID --------------//
printf ("\nPlease Enter ID: ");
while (scanf ("%d",&checkID) == 0)
{
printf ("\n\nInvalid Input!!!\n");
printf ("Either you have entered a Letter!!\n");
printf ("Press 'Y' to enter another ID or any key to return to MainMenu\n\n");
while (getchar()!='\n')
{
}
option = getchar();
if (option == 'Y' || option == 'y')
{
printf ("\nPlease Enter Another ID Number:\n");
}
else
{
printf ("\nReturning to Order Management Menu\n");
system ("PAUSE");
fflush(stdin);
orderMainMenu();
}
}
//---------- CHECK WHETHER ID EXISTS OTHERWISE EXIT TO MENU --------------//
while (fread (&c, STRUCTSIZEC,1,cfp) == 1)
{
if (c.ID == checkID)
{
clrscr();
printf ("\n\n\n\n\t\t ************* Add Customer Order *************\n \n \n");
// SHOWS WHICH ID IS BEING SERVED //
printf ("\n\nNew Order For ID: %d\n", c.ID);
// ASKS WHICH PRODUCT TO BUY //
printf ("\nWhich Product do you want to buy?\n\n");
printf ("WARNING! Product Name is CASE SENSITIVE:\n");
// INPUT NAME //
printf ("Product Name: ");
while (getchar() !='\n')
{
}
fgets (tempName, 100, stdin);
while (fread (&p, STRUCTSIZEP,1,pfp)== 1)
{
if (strncmp (tempName,p.pName,sizeof(tempName)) == 0)
{
// --- SHOWING ID and WHICH PRODUCT CUSTOMER IS GOING TO BUY -- //
clrscr ();
printf ("\n\n\n\n\t\t ************* Add Customer Order *************\n \n \n");
printf ("Order for ID: %d\n", c.ID);
printf ("Product Name: %s\n\n", p.pName);
tempStock = p.pStock;
printf ("How many do you wish to buy?\n");
printf ("Currently there is %d in Stock", tempStock);
printf ("Order: ");
while (scanf ("%d",&order) == 0)
{
printf ("Invalid Order! Only Numbers are allowed!\n");
while (getchar() !='\n')
{
}
}
//---- CHECK WEHTHER ORDER IS BIGGER THAN WHAT IS FOUND IN STOCK ----//
//---- IF YES ASK IF USER WANTS TO INPUT ANOTHER NUMBER OR EXIT ----//
while (order > tempStock)
{
printf ("There is not enough items in Stock to satisfy that quantity!\n");
printf ("Do you want to enter another quantity? 'Y' for yes, any key to return to Menu\n");
fflush (stdin);
ch2 = getchar();
if (ch2 == 'Y' || ch2 == 'y')
{
printf ("Please enter another quantity:\n");
scanf ("%d",&order);
}
else
{
printf ("Order Canceled! Returning to Main Menu");
system ("PAUSE");
fclose (cfp);
fclose (ofp);
fclose (pfp);
orderMainMenu();
}
}
printf ("\nTotal Price for this Order will be:\n");
tempPrice = (order * p.pPrice);
printf ("Total: %.2f\n", tempPrice);
// ---- SHOW THE TRANSACTION OF THE USER AND ASK WHETHER TO CONFIRM ---- //
clrscr();
printf ("\n\n\n\n\t\t ************* Add Customer Order *************\n \n \n");
printf ("This is the Customer's Overview of Purchase:\n\n");
printf ("Customer's ID: %d\n",c.ID);
printf ("Customer's Product: %s",p.pName);
printf ("Order: %d\n",order);
printf ("Total Price: %.2f\n\n",tempPrice);
printf ("\n\n----------------------------------------\n\n");
printf ("Are you sure you of this transaction?\n");
printf ("Warning: After Confirming you cannot change the Order!\n");
printf ("Press 'Y' to confirm the Transaction otherwise press 'N' to cancel the order and return to Main Menu\n");
while (getchar() !='\n')
{
}
ch = getchar();
if (ch == 'N' || ch == 'n')
{
printf ("Transaction CANCELLED! Returning to Order Main Menu!\n");
system ("PAUSE");
orderMainMenu();
}
else if (ch == 'y' || ch == 'Y')
{
tempStock = (tempStock - order);
p.pStock = tempStock; //Updates the new stock number in Products' Database
fseek (pfp,-STRUCTSIZEP,SEEK_CUR);
fwrite(&p, STRUCTSIZEP,1,pfp);
fclose (pfp);
o.quantity = order;
o.cID = c.ID;
o.price = tempPrice;
strncpy(o.pName,p.pName, sizeof(p.pName));
o.timer = time(NULL);
fwrite (&o,STRUCTSIZEO,1,ofp);
fclose (ofp); //Closing of Files
fclose (cfp);
fclose (pfp);
printf("The Transaction Order saved is as follows:\n");
printf("ID: %d\nProduct: %sQuantity: %d\nPrice: %.2f\n",o.cID,o.pName,o.quantity,o.price);
printf("Transaction Made at: %s\n",asctime(localtime(&o.timer)));
system ("PAUSE");
orderMainMenu();
}
}
}
}
}
}
else
{
printf ("Returning to Order Main Menu\n");
system ("PAUSE");
orderMainMenu();
}
}
ListAll method:
void oListAll()
{
order o;
printf ("\n\n\n\n\t\t ********** Current Products in the Database *******\n \n \n");
//--------------- LOADING OF FILE ------------ //
if ((ofp = fopen ("orders.dat","rb")) == NULL)
{
fputs ("Cannot open products.dat file!\n",stderr);
printf ("Returning to Order Main Menu\n");
system ("PAUSE");
orderMainMenu();
}
rewind (ofp);
// --------- START TO TRAVERSE THE DATABASE AND OUTPUT DATA -------- //
printf ("Current Orders in the Database:\n");
while (fread (&o, STRUCTSIZEO,1,pfp)==1)
{
printf (" Name: %s Price: %.2f\n In Stock: %d\n\n", o.pName, o.price, o.quantity);
}
system ("PAUSE");
productMainMenu();
}
These are the screenshots:
http://tinypic.com/r/110x7c2/6
http://tinypic.com/r/1446ya/6
http://tinypic.com/r/315iy3s/6
http://tinypic.com/r/15xo4lt/6
http://tinypic.com/r/2ze9wfr/6
http://tinypic.com/r/jtx8xw/6
I know it's rather long but please bear with me, I've been over 4 hours trying to figure out what's wrong with it. Thanks a bunch

Your oListAll() function opens FILE *ofp, but reads from pfp. Try reading from ofp

As this is not the whole program I can't find the issue but my guess it that it has something to do with your file pointers being global vars. You should make them local and always ensure they are closed properly.
I would break up the customerOrder() function in to smaller functions. This will make your code much easier to read, debug, and modify. For example (this is just pseudo-code, you have to fill in the blanks):
void customerOrder()
{
int checkId = getCustomerID(); // Checks the DB to see if user exists
bool productExists = checkProduct(tempName); // Checks the DB to see if product exists
int productCount = getProductCount(tempName); // Checks the DB to get count of items in stock
saveOrder(checkId, tempName, order); // Save the order
}
// Save the order in DB. Ensures FILE pointers are closed when done
void saveOrder(int customerID, const char * productName, int count)
{
order o;
// Create the order here....
FILE *ofp = fopen ("orders.dat","ab");
if (NULL != ofp) {
fwrite (&o,STRUCTSIZEO,1,ofp);
fclose (ofp); //Closing of Files
}
}

Related

Segmentation Fault from printing a linked list after reading from a file

I've almost completed my C program to add, view, save and load patient details. I've completed the add, save and load but can't seem to get the save function implemented correctly.
The program will allow users to add patient details, then save the details into a text file database. Users can then exit from the program, start the program and load the text file database. Finally, users will be able to see the patient details in the program.
In my code, I've also added some code to print out the contents after reading the text file, which works, printing out all the patient details onto the terminal. However, after I read from the text file, I try to use the view patient function and get a segmentation fault. Any help would be appreciated. Thanks!
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define DB_NAME "database"
struct dob
{
int day, month, year;
};
typedef struct dob dob_t;
struct medicine
{
int medicine_id;
char medicine_name[100];
};
typedef struct medicine medicine_t;
struct patient
{
int patient_id;
dob_t date_db;
char patient_name[20];
medicine_t patient_med;
struct patient* nextp;
};
typedef struct patient patient_t;
void print_menu (void);
patient_t* add_patients (patient_t* patient_headp, patient_t* temp, patient_t* patient_currentp, int num_patients);
void view_patients (patient_t* patient_currentp, patient_t* patient_headp);
void save_patients (patient_t* patient_currentp, patient_t* patient_headp);
patient_t* read_patients (patient_t* patient_currentp, patient_t* patient_headp, patient_t* temp);
int main (void){
patient_t* patient_headp = NULL;
patient_t* temp = NULL;
patient_t* patient_currentp = NULL;
int option_picked = 0;
int num_patients = 0;
while(option_picked != 5)
{
print_menu ();
scanf("%d", &option_picked);
if (option_picked == 1){
patient_headp = add_patients(patient_headp, temp, patient_currentp, num_patients);
}
else if (option_picked == 2){
view_patients (patient_currentp, patient_headp);
}
else if (option_picked == 3){
save_patients (patient_currentp, patient_headp);
}
else if (option_picked == 4){
patient_headp = read_patients (patient_currentp, patient_headp, temp);
}
}
return 0;
}
void print_menu (void)
{
printf("\n"
"1. add a patient\n"
"2. display all patients\n"
"3. save the patients to the database file\n"
"4. load the patients from the database file\n"
"5. exit the program\n"
"Enter choice (number between 1-5)>\n");
}
patient_t* add_patients (patient_t* patient_headp, patient_t* temp, patient_t* patient_currentp, int num_patients){
char choice;
do
{
temp = (patient_t*) malloc(sizeof(patient_t));
if (temp == NULL){
printf("Error allocating memory\n");
}
printf("Enter Patient ID: ");
scanf("%d", &temp->patient_id);
printf("Enter Patient DOB(DD MM YY): ");
scanf("%d %d %d", &temp->date_db.day, &temp->date_db.month,
&temp->date_db.year);
printf("Enter Patient Name: ");
scanf("%s", temp->patient_name);
printf("Enter Patient Medicine Prescription: ");
scanf("%s", temp->patient_med.medicine_name);
printf("Enter Patient Medicine Prescription ID: ");
scanf("%d", &temp->patient_med.medicine_id);
temp->nextp = NULL;
if(patient_headp == NULL){
patient_headp = temp;
}
else{
patient_currentp = patient_headp;
while(patient_currentp->nextp != NULL){
patient_currentp = patient_currentp->nextp;
}
patient_currentp->nextp = temp;
}
printf("Add more patients? (Y/N) ");
scanf(" %c", &choice);
num_patients++;
}
while (choice == 'Y');
return patient_headp;
}
void view_patients (patient_t* patient_currentp, patient_t* patient_headp){
/*patient_currentp = (patient_t*) malloc(sizeof(patient_t));
if (patient_currentp == NULL){
printf("Error allocating memory\n");
}
patient_currentp = patient_headp;
do{
printf("%05d %02d/%02d/%02d %s %s %d\n", patient_currentp->patient_id,
patient_currentp->date_db.day, patient_currentp->date_db.month,
patient_currentp->date_db.year, patient_currentp->patient_name,
patient_currentp->patient_med.medicine_name,
patient_currentp->patient_med.medicine_id);
patient_currentp = patient_currentp->nextp;
}while(patient_currentp->nextp != NULL);*/
printf("%05d %02d/%02d/%02d %s %s %d\n", patient_headp->patient_id,
patient_headp->date_db.day, patient_headp->date_db.month,
patient_headp->date_db.year, patient_headp->patient_name,
patient_headp->patient_med.medicine_name,
patient_headp->patient_med.medicine_id);
}
void save_patients (patient_t* patient_currentp, patient_t* patient_headp){
FILE *output = fopen(DB_NAME, "a");
if (output == NULL){
printf("Failed to open file\n");
}
patient_currentp = patient_headp;
do{
fprintf(output, "%05d %02d/%02d/%02d %s %s %d\n", patient_currentp->patient_id,
patient_currentp->date_db.day, patient_currentp->date_db.month,
patient_currentp->date_db.year, patient_currentp->patient_name,
patient_currentp->patient_med.medicine_name,
patient_currentp->patient_med.medicine_id);
patient_currentp = patient_currentp->nextp;
}while(patient_currentp != NULL);
fclose(output);
}
patient_t* read_patients (patient_t* patient_currentp, patient_t* patient_headp, patient_t* temp){
FILE *input = fopen(DB_NAME, "r");
if (input == NULL){
printf("Failed to open file\n");
}
do{
temp = (patient_t*) malloc(sizeof(patient_t));
if (temp == NULL){
printf("Error allocating memory\n");
}
while ((fscanf(input, "%05d %02d/%02d/%02d %s %s %d",
&temp->patient_id, &temp->date_db.day,
&temp->date_db.month, &temp->date_db.year,
temp->patient_name,
temp->patient_med.medicine_name,
&temp->patient_med.medicine_id)) != EOF)
printf("%05d %02d/%02d/%02d %s %s %d\n", temp->patient_id,
temp->date_db.day, temp->date_db.month,
temp->date_db.year, temp->patient_name,
temp->patient_med.medicine_name,
temp->patient_med.medicine_id);
temp->nextp = NULL;
if(patient_headp == NULL){
patient_headp = temp;
}
else{
patient_currentp = patient_headp;
while(patient_currentp->nextp != NULL){
patient_currentp = patient_currentp->nextp;
}
patient_currentp->nextp = temp;
}
}while(patient_currentp != NULL);
return patient_headp;
}
The reality of your problem is (1) without input validation there are so many potential sources of error that could lead to Undefined Behavior and a Segmentation Fault that it is difficult to pin down (2) any time the address of the list could change in a function (e.g. the first node changes), you need to pass the address of patient_headp so that the function receives the actual list pointer instead a copy of a pointer holding the list address, and (3) your read_patients() is non-functional (for a number of reasons), but fundamentally because setting patient_currentp = patient_currentp->nextp; guarantees while(patient_currentp != NULL); test false.
There is no reason to pass patient_currentp as a parameter. There is no reason to pass num_patients in its current form, the parameter is unused, and for it to be useful you would need to pass a pointer to num_patients so you could update it within your add and read functions and make the updated counts available back in the calling function.
Before we even look at code, taking user input with scanf is wrought with pitfalls for the unwary in the event of a matching or input failure. To even begin to use scanf correctly you must validate the return every time. This means handling EOF, a matching or input failure, and handling the valid input case. At minimum, you must check that the anticipated number of conversions took place before making use of the input.
In the event of a matching failure, character extraction from the input buffer stops, leaving the offending character unread just waiting to bite you on your next attempt to read. To facilitate recovering from a matching failure, it is up to you to removed the offending characters from the input buffer. The normal approach for stdin is simply reading with getchar() until '\n' or EOF is encountered. A short helper-function makes life easier, e.g.
void empty_stdin (void)
{
int c = getchar();
while (c != '\n' && c != EOF)
c = getchar();
}
In addition to the validation issue, you may find it more robust to indicate success/failure in your add_patients() function by returning a pointer to the node added (or NULL on failure). This is somewhat complicated by your looping within the function to add multiple patients rather than simply calling the function again from the menu. Regardless, returning a pointer to the last node added works equally well.
There is no way possible to step through every issue in your code in the characters allotted for this answer. Instead, I've tidied up your code in a way that addresses each user-input validation, removes unnecessary parameters from your function declarations, and changed the return types for save_patients() and read_patients() to int to provide 1 on successful write or read, 0 otherwise.
(note the validation of fclose in save_patients(). Any time you are writing to a file, you should validate fclose as it will catch stream errors as well as errors with your last write that may not have been capable of reporting until close)
The code follows your approach, it has just been refined in several places. Look it over:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define DB_NAME "database"
#define MAXRX 100 /* if you need constants, #define on (or more) */
#define MAXNM 20 /* (don't use "magic numbers" in your code ) */
typedef struct {
int day, month, year;
} dob_t;
typedef struct {
int medicine_id;
char medicine_name[MAXRX];
} medicine_t;
typedef struct patient {
int patient_id;
dob_t date_db;
char patient_name[MAXNM];
medicine_t patient_med;
struct patient* nextp;
} patient_t;
void empty_stdin (void)
{
int c = getchar();
while (c != '\n' && c != EOF)
c = getchar();
}
void print_menu (void);
patient_t *add_patients (patient_t **patient_headp, int *num_patients);
void view_patients (patient_t *patient_headp);
int save_patients (patient_t *patient_headp);
int read_patients (patient_t **patient_headp, int *num_patients);
int main (void) {
patient_t *patient_headp = NULL;
int option_picked = 0,
num_patients = 0;
while(option_picked != 5)
{
print_menu ();
if (scanf("%d", &option_picked) != 1) { /* VALIDATE EVERY USER INPUT */
fputs ("\n error: invalid input.\n", stderr);
empty_stdin();
continue;
}
if (option_picked == 1)
add_patients (&patient_headp, &num_patients);
else if (option_picked == 2)
view_patients (patient_headp);
else if (option_picked == 3)
save_patients (patient_headp);
else if (option_picked == 4)
read_patients (&patient_headp, &num_patients);
}
return 0;
}
void print_menu (void)
{
printf ("\n"
"1. add a patient\n"
"2. display all patients\n"
"3. save the patients to the database file\n"
"4. load the patients from the database file\n"
"5. exit the program\n\n"
"Enter choice (number between 1-5)> ");
}
patient_t *add_patients (patient_t **patient_headp, int *num_patients)
{
patient_t *patient_currentp = *patient_headp,
*temp = NULL;
char choice = 0;
do
{
temp = malloc (sizeof *temp); /* allocate */
if (temp == NULL){ /* validate */
perror ("add_patients-malloc");
return NULL;
}
temp->nextp = NULL; /* initialize */
printf ("Enter Patient ID: ");
if (scanf ("%d", &temp->patient_id) != 1)
goto error_add_pt;
printf ("Enter Patient DOB(DD MM YY): ");
if (scanf ("%d %d %d", &temp->date_db.day, &temp->date_db.month,
&temp->date_db.year) != 3)
goto error_add_pt;
printf ("Enter Patient Name: ");
if (scanf ("%s", temp->patient_name) != 1)
goto error_add_pt;
printf ("Enter Patient Medicine Prescription: ");
if (scanf ("%s", temp->patient_med.medicine_name) != 1)
goto error_add_pt;
printf ("Enter Patient Medicine Prescription ID: ");
if (scanf ("%d", &temp->patient_med.medicine_id) != 1)
goto error_add_pt;
if (*patient_headp == NULL){
*patient_headp = patient_currentp = temp;
}
else {
while (patient_currentp->nextp != NULL){
patient_currentp = patient_currentp->nextp;
}
patient_currentp->nextp = temp;
}
(*num_patients)++;
printf ("Add more patients? (Y/N) ");
if (scanf (" %c", &choice) < 1) {
fputs (" user canceled input.\n", stderr);
break;
}
}
while (choice == 'Y' || choice == 'y');
return temp; /* return pointer to most recent node added */
error_add_pt:;
fputs ("error: invalid input\n", stderr);
empty_stdin();
free (temp);
return NULL;
}
void view_patients (patient_t *patient_headp)
{
patient_t *patient_currentp = patient_headp;
while (patient_currentp != NULL) {
printf ("%05d %02d/%02d/%02d %s %s %d\n", patient_currentp->patient_id,
patient_currentp->date_db.day, patient_currentp->date_db.month,
patient_currentp->date_db.year, patient_currentp->patient_name,
patient_currentp->patient_med.medicine_name,
patient_currentp->patient_med.medicine_id);
patient_currentp = patient_currentp->nextp;
}
}
int save_patients (patient_t *patient_headp)
{
patient_t *patient_currentp = patient_headp;
FILE *output = fopen(DB_NAME, "a");
if (output == NULL) { /* validate file open to append */
fprintf (stderr, "error: file open failed '%s'\n", DB_NAME);
return 0;
}
while(patient_currentp != NULL) {
fprintf (output, "%05d %02d/%02d/%02d %s %s %d\n",
patient_currentp->patient_id,
patient_currentp->date_db.day, patient_currentp->date_db.month,
patient_currentp->date_db.year, patient_currentp->patient_name,
patient_currentp->patient_med.medicine_name,
patient_currentp->patient_med.medicine_id);
patient_currentp = patient_currentp->nextp;
}
if (fclose (output) == EOF) {
fputs ("error: stream error on fclose.\n", stderr);
return 0;
}
return 1;
}
int read_patients (patient_t **patient_headp, int *num_patients)
{
patient_t tmp = {0},
*patient_currentp = *patient_headp;
FILE *input = fopen(DB_NAME, "r");
if (input == NULL){ /* validate file open for reading */
fprintf (stderr, "error: file open failed '%s'\n", DB_NAME);
return 0;
}
while (patient_currentp && patient_currentp->nextp != NULL)
patient_currentp = patient_currentp->nextp;
while (fscanf (input, "%05d %02d/%02d/%02d %19s %99s %d",
&tmp.patient_id, &tmp.date_db.day,
&tmp.date_db.month,
&tmp.date_db.year,
tmp.patient_name,
tmp.patient_med.medicine_name,
&tmp.patient_med.medicine_id) == 7) {
patient_t *node = malloc (sizeof *node);
if (node == NULL) {
perror ("read_patients-malloc");
return 0;
}
node->nextp = NULL;
*node = tmp;
if (!patient_currentp)
*patient_headp = patient_currentp = node;
else {
patient_currentp->nextp = node;
patient_currentp = patient_currentp->nextp;
}
(*num_patients)++;
printf ("%05d %02d/%02d/%02d %s %s %d\n", node->patient_id,
node->date_db.day, node->date_db.month,
node->date_db.year, node->patient_name,
node->patient_med.medicine_name,
node->patient_med.medicine_id);
}
fclose (input);
return 1;
}
(note: your repeated allocation for patient_currentp in read_patients() was leaking memory and overwriting the pointer values you had previously assigned to your list. That is why an additional node variable is used)
Example Use/Output - Entering Data
$ ./bin/llpatients
1. add a patient
2. display all patients
3. save the patients to the database file
4. load the patients from the database file
5. exit the program
Enter choice (number between 1-5)> 1
Enter Patient ID: 10001
Enter Patient DOB(DD MM YY): 1 1 72
Enter Patient Name: Epoch
Enter Patient Medicine Prescription: Clonapin
Enter Patient Medicine Prescription ID: 2001
Add more patients? (Y/N) y
Enter Patient ID: 10002
Enter Patient DOB(DD MM YY): 31 10 72
Enter Patient Name: Halloween
Enter Patient Medicine Prescription: Potion
Enter Patient Medicine Prescription ID: 2002
Add more patients? (Y/N) n
1. add a patient
2. display all patients
3. save the patients to the database file
4. load the patients from the database file
5. exit the program
Enter choice (number between 1-5)> 2
10001 01/01/72 Epoch Clonapin 2001
10002 31/10/72 Halloween Potion 2002
1. add a patient
2. display all patients
3. save the patients to the database file
4. load the patients from the database file
5. exit the program
Enter choice (number between 1-5)> 3
1. add a patient
2. display all patients
3. save the patients to the database file
4. load the patients from the database file
5. exit the program
Enter choice (number between 1-5)> 5
Example Use/Output - Reading From File
$ ./bin/llpatients
1. add a patient
2. display all patients
3. save the patients to the database file
4. load the patients from the database file
5. exit the program
Enter choice (number between 1-5)> 4
10001 01/01/72 Epoch Clonapin 2001
10002 31/10/72 Halloween Potion 2002
1. add a patient
2. display all patients
3. save the patients to the database file
4. load the patients from the database file
5. exit the program
Enter choice (number between 1-5)> 2
10001 01/01/72 Epoch Clonapin 2001
10002 31/10/72 Halloween Potion 2002
1. add a patient
2. display all patients
3. save the patients to the database file
4. load the patients from the database file
5. exit the program
Enter choice (number between 1-5)> 5
Again, look things over, understand why the changes that were made, were made, and ask if you have any further questions.
in add_patients the following happens
Create Node
/* Create a temporary node */
temp = (patient_t*) malloc(sizeof(patient_t));
Fill Node with what ever Data
/* Copy Data to temporary Node */
printf("Enter Patient ID: ");
..
..
temp->nextp = NULL;
The linked list alterations
if(patient_headp == NULL){
patient_headp = temp;
}
else{
patient_currentp = patient_headp;
while(patient_currentp->nextp != NULL){
patient_currentp = patient_currentp->nextp;
}
patient_currentp->nextp = temp;
}
at this point temp is still pointing to the allocated memory so does linked list
and then this
free(temp);
results in segfault. so remove the free

I keep getting an infinite loop when I choose a certain option in my program

i have this program that asks users to enter info stores it in file and allows u to edit entries or add new ones or delete ones by setting gross salary to 0.
However when i try to modify a name , it doesn't modify , and when i try to modify gender, it causes an infinite loop can any1 tell me whats wrong?
And i think there something wrong with my break statements i made within the loop , thanks in advance
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int employee_number;
char employee_name[20];
char employee_sex;
int employee_gross_salary;
}information;
int main()
{//open main function
information customer;
int i;
int choice;
int number;
int choice2;
int number2;
FILE *fptr = fopen("emp.dat", "wb+");
//asking user to enter atleast 5 customers into datarecords
for(i = 0; i<1;i++)
{//open for
printf("enter employee's number\n");
scanf("%d",&customer.employee_number);
getchar();
printf("enter the employee's name\n");
scanf("%s", customer.employee_name);
getchar();
printf("enter employee's gender\n");
scanf("%d",&customer.employee_sex);
getchar();
printf("enter employee's salary\n");
scanf("%d",&customer.employee_gross_salary);
getchar();
fwrite(&customer,sizeof(customer),1,fptr);
}//close for
for(;;)
{//open for
printf("\n what would you like to do\n1]Add entry\n 2]Delete entry \n3]Modify entry\n4]view entries\n5]exit\n");
scanf("%d", &choice);
if(choice == 5)
{break;}
else if(choice == 1)
{//open else if
fseek(fptr,0, SEEK_END);// check the parameters here
printf("enter new employee's number\n");
scanf("%d",&customer.employee_number);
getchar();
printf("enter the new employee's name\n");
scanf("%s", customer.employee_name);
getchar();
printf("enter new employee's gender\n");
scanf("%d",&customer.employee_sex);
getchar();
printf("enter new employee's salary\n");
scanf("%d",&customer.employee_gross_salary);
getchar();
fwrite(&customer,sizeof(customer),1,fptr);
continue;
}//close else if
else if( choice == 2)
{//open else if
printf("enter the employee number of person\n");
scanf("%d",&number);
fseek(fptr,0,SEEK_SET);
while((fread(&customer,sizeof(customer), 1,fptr))!=NULL)
{//open while
if(customer.employee_number == number)
{//open if
customer.employee_gross_salary = 0;
}//close if
}//close while
continue;
}//clsoe else if
else if(choice == 3)
{//open else if
printf("enter the employee number of the employee you would like to modify\n");
scanf("%d",&number2);
printf("what would you like to modify\n");
scanf("%d", &choice2);
fseek(fptr,0,SEEK_SET);
while((fread(&customer, sizeof(customer),1,fptr))!= NULL)
{//open while within else if
//1 to midify name, 2 to modify gender 3 for salary
if(customer.employee_number == number2)
{//open if
if(choice2 == 1)
{
printf("enter new name\n");
scanf("%s",customer.employee_name );
break;
}
else if(choice2 == 2)
{
printf("enter new gender");
scanf("%d", &customer.employee_sex);
break;
}
else if(choice2 == 3)
{
printf("enter new gross salary\n");
scanf("%d", &customer.employee_gross_salary);
break;
}
}//close if
}//close while within else if
continue;
}//close else if
else if(choice == 4)
{
fseek(fptr,0,SEEK_SET);
while((fread(&customer,sizeof(customer),1,fptr))!= NULL)
printf("\n%d\t%s\t%c\t%d\n", customer.employee_number,customer.employee_name,customer.employee_sex,customer.employee_gro ss_salary);
continue;
}
}//close for
return 0;
}//close main function
This is NOT the answer for your debug, just some advice for refactoring your code and future writing:
1.
Avoid using break and continue, they are flow breaker, bug sources, bad and evil, it is the same for go to, they are here for specific no-other-way cases.
You can do something like:
int end = 0,
choice = 0;
do
{
fprintf(stdout, "1:Do stuff\n2:Do other stuff\n3: Do another stuff\nX: end\n");
while(fscanf(stdin, "%d", &choice) != 1){}
if(choice == 1)
{
//Do stuff
}
else if (choice == 2)
{
//Do other stuff
}
else if (choice == 3)
{
//Do another stuff
}
else
{
end = 1;
}
}while(end == 0);
return 0;
No continue, no break, easier to modify, easier to write, easier to read, shorter, in two word: way better
2.
Write in english, always, you have a full keyboard and do not pay by letter, it is almost as fast to type the entire word, and help a lot other to understand.
Also, it will help you to make less error when you write text or code.
3.
You can declare multiple variable at once if they are of the same type:
int var1;
int var2;
int var3;
...
Is long and repetitive, instead you can write:
int var1,
var2,
var3;
A good habit can be to always initialize variables, it help prevent some bug:
int var1=0,
var2=0,
var3=0;
4.
Whenever you use a function, test its return, there is a lot of bug that happen from thinking "it is a stdio function, it is bug-proof". As exemple, your fopen of emp.dat. It can fail (and in fact will fail at some point).
FILE *fptr = fopen("emp.dat", "wb+");
if (fptr == NULL)
{
fprintf(stderr, "Error while opening emp.dat\n");
return -1;
}
5.
If you are a begginner (there is no shame about that, everyone begin at some point, and we can say everyone is still begginning even after 10+years of coding), write your algorithm first, then code. Exemple:
//Get user's choice
//If user choice is do stuff
//Do stuff
//If it is do other stuff
//Do other stuff
//If it is do another stuff
//Do another stuff
//Else if he want to quit
//Quit
Which then become
int choice=0, //User's choice
end=0; //End of program
do
{
//Get user's choice
fprintf(stdout, "1:Do stuff\n2:Do other stuff\n3: Do another stuff\nX: end\n");
while(fscanf(stdin, "%d", &choice) != 1){}
//If user choice is do stuff
if(choice == 1)
{
//Do stuff
}
//If it is do other stuff
else if(choice == 1)
{
//Do other stuff
}
//If it is do another stuff
else if(choice == 1)
{
//Do another stuff
}
//Else if he want to quit
else
{
//Quit
end = 1;
}
}while (end == 0);
return 0;
It also prevent you from going to comment your code weeks later when you don t know anymore why you did that or that stuff.
6.
Log, log, log, especially at debug!
You can put it on stderr if you want, so you can separate it from your output.
Exemple:
int end = 0,
choice = 0;
fprintf(stderr, "Start\n");
do
{
fprintf(stderr, "\tBegin loop\n");
fprintf(stdout, "1:Do stuff\n2:Do other stuff\n3: Do another stuff\nX: end\n");
while(fscanf(stdin, "%d", &choice) != 1){}
fprintf(stderr, "\tChoice is: %d\n", choice);
if(choice == 1)
{
fprintf(stderr, "\t\tStarting do stuff\n");
//Do stuff
fprintf(stderr, "\t\tEnding do stuff\n");
}
else if (choice == 2)
{
fprintf(stderr, "\t\tStarting do other stuff\n");
//Do other stuff
fprintf(stderr, "\t\tEnding do other stuff\n");
}
else if (choice == 3)
{
fprintf(stderr, "\t\tStarting do another stuff\n");
//Do another stuff
fprintf(stderr, "\t\tEnding do another stuff\n");
}
else
{
fprintf(stderr, "\t\tEnd order\n");
end = 1;
}
fprintf(stderr, "\tEnd of loop\n");
}while(end == 0);
fprintf(stderr, "End\n");
return 0;
So you know when and where is your program right now, it is a HUGE help for debug!
That s all I have in mind right now, hope it can help you.
Also, welcome to Stack Overflow.
Edit:
Thanks to chunk, another important point:
7.Always checking scanf for valid user's input. User's input can and will be almost eveything, and will at some point not be what you think, test it, always. (it is not valid only for (f)scanf, but for EVERY ways you get your data from other sources but your own source code)
int check = 0;
fprintf(stderr, "\tBegin loop\n");
fprintf(stdout, "1:Do stuff\n2:Do other stuff\n3: Do another stuff\nX: end\n");
check = fscanf(stdin, "%d", &choice);
if(check != 1)
{
fprintf(stderr, "Bad input\n");
return -1;
}
fprintf(stderr, "\tValid choice is: %d\n", choice);
This way, any other input but a decimal number will be discarded and will close the program, of course you can do it better.
int check = 0;
fprintf(stderr, "\tBegin loop\n");
fprintf(stdout, "1:Do stuff\n2:Do other stuff\n3: Do another stuff\nX: end\n");
while(fscanf(stdin, "%d", &choice) != 1)
{
fprintf(stderr, "Bad input!\n");
}
fprintf(stderr, "\tValid choice is: %d\n", choice);
In this version, when the user type something invalid, he just have to try again.
In addition to DrakaSAN's answer I would add that you should always flush the input buffer when you take character/string input after taking integer input.
One way to flush the input buffer is to use getchar():
while ((ch = getchar()) != '\n');
But if the user gives the input as "123 abc\n" (as mentioned by chux in comment) assuming 123 goes to the integer variable and "abc" to the character array, then there are ways to resolve this:
//can be modified according to programmer's requirements
int a;
char arr[10],ch;
scanf("%d",&a);
while((ch=getchar())==' ' || ch=='\t' || ch=='\n') //loop until non-whitespace character
{
if (ch=='\n')
{
ch=getchar();
break;
}
}
if (ch!='\n') //ch contains the first character of the character array
{
arr[0]=ch;
gets(arr+1);
}
else //if two consecutive new lines after integer, string contains nothing
arr[0]='\0';
You need to write the results when choice == 2 and choice == 3 before the continue, like
fseek(fptr, -sizeof(customer), SEEK_CUR);
fwrite(&customer,sizeof(customer), 1, fptr);

Search Method Failing

I'm trying to do a search Method in which checks 2 IDs which only store integer.
Firstly I have a database of customers. I input the Name,Surname,ID and Address after each other in this order and then these are immediately saved into the file
When the User inputs the ID card this calls this Search Method and checks through all the file to see whether the ID is unique or not. If it is not, then it returns 0 otherwise it returns 1
Now the problem is this.
When I am inputting the ID, whether it is unique or not it keeps on going, but then when it outputs what I wrote it, for the NAME and SURNAME it shows only the first record I have stored there (like stuck in some kind of buffer), the ID and the address outputs normally.
The File is Also NOT Updated meaning, the save file did not occur.
Now when I Remove this method, the appending works normally, but I won't have access to the comparing of IDs.
Any suggestions why this is happening? and if possible any idea how I can fix it?
it's like whenever I'm doing this search method the whole file is getting started from the beginning and getting stuck there. I Tried using the method with boolean but still no avail. When I tried using it with Boolean instead of the line "if (customerID(scanf ("%d",&cCheck)) == 1)" I made it == TRUE, it was giving me an error that the output will
always be == FALSE because the data is not NULL.
and oh TRUE and FALSE are valid in my case as I have a typedef enum boolean in the common.h
The code is as follows [posting the whole file]:
The methods concerned are [ void addCustomer()] and [int customerID (int cCheck)
but I posted all as some of them are interconnecting.
EDIT!!! - The ID even if they are NOT unique, it is still Accepted...
/*
* CustomerMainMenu.c
* Author: DodoSerebro
*
* This class will output the Customer's Main Menu and re-directs to the
* corresponding section
*
*/
#include<io.h>
#include<fcntl.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include "..\Headers\common.h"
#include "..\Headers\customerManagement.h"
static FILE *cfp;
static customer c;
#define STRUCTSIZE sizeof (customer)
/** This is the Customers's Main Menu in which the various sections can be
* accessed from here
*/
boolean customerMainMenu()
{
int optionC;
clrscr();
copyright();
printf ("\n\n\n\n\t\t ************* Customer's Main Menu *************\n \n \n");
printf ("Press [1] to add a new Customer\n");
printf ("Press [2] to edit a Customer\n");
printf ("Press [3] to list all Customers\n");
printf ("Press [4] to Show a Customer's last Order\n");
printf ("Press [5] to go back to Main Menu\n\n\n");
if (scanf ("%d",&optionC) == 1)
{
switch (optionC)
{
case 1:
{
clrscr();
getchar();
addCustomer();
break;
}
case 2:
{
printf ("Edit a Customer\n");
break;
}
case 3:
{
clrscr();
listCustomers();
system ("PAUSE");
break;
}
case 4:
{
printf ("Customer's Last Order\n");
break;
}
case 5:
{
system ("PAUSE");
break;
}
default:
{
if (optionC != 1 || optionC != 2 || optionC != 3 || optionC != 4 || optionC !=5)
{
clrscr();
printf ("Invalid option!\n");
system ("PAUSE");
customerMainMenu();
}
break;
}
}
}
return TRUE;
}
/**
* This following method will append a customer to the
* database at the end of the file
*
* */
void addCustomer ()
{
char ch;
copyright();
printf ("\n\n\n\n\t\t ************* Add Client **********\n \n \n");
if ((cfp = fopen ("customers.dat","a+b")) == NULL)
{
fputs("Can't open customers.dat file\n",stderr);
}
printf ("\tThis will add another customer to the the database\n");
printf ("\tPress 'Y' to confirm or 'N' to return to the Client Main Menu\n\tWITHOUT adding a customer\n");
ch = getchar();
if (ch == 'n' || ch == 'N')
{
customerMainMenu();
}
else if (ch == 'y' || ch == 'Y')
{
fflush(stdin);
clrscr();
printf ("\n\n\n\n\t\t ************* Add Client **********\n \n \n");
printf ("Please enter Name:\n");
while (scanf ("%s", c.name) == 0 || cCheck(c.name,100) == FALSE);
{
}
printf ("Please Enter Surname: \n");
while (scanf ("%s",c.surname) == 0 && cCheck (c.surname,100) == FALSE);
{
}
printf ("Please Enter ID Card, [NOTE! Only numbers are allowed!]\n");
int cCheck;
if (customerID(scanf ("%d",&cCheck)) == 1)
{
printf ("ID already Taken, Client exists!\n");
printf ("Do you want to enter another ID? 'Y' for Yes and 'N' to return to Main Menu\n");
ch = getchar();
if (ch == 'Y' || ch == 'y')
{
scanf ("%d",&cCheck);
customerID(cCheck);
c.ID = cCheck;
}
else
{
customerMainMenu();
}
}
else
{
c.ID = cCheck;
}
getchar();
printf ("Please Enter Address:\n");
gets(c.address);
fwrite (&c,STRUCTSIZE, 1, cfp);
printf ("For Testing purposes:\n");
printf (" %s\n %s\n %s\n %d\n", c.name, c.surname, c.address, c.ID);
askAnother();
}
else
{
printf ("\nInvalid choice! Either Y or N is accepted\n");
system ("PAUSE");
getchar();
clrscr();
addCustomer();
}
}
void listCustomers()
{
if ((cfp = fopen ("customers.dat","rb")) == NULL)
{
fputs("Can't open customers.dat file\n",stderr);
printf ("Returning to Customer Main Menu");
system ("PAUSE");
customerMainMenu();
}
rewind (cfp);
while (fread (&c,STRUCTSIZE,1,cfp)==1)
{
printf ("Customer: %s %s ID: %d\n", c.surname, c.name, c.ID);
}
fclose (cfp);
}
void askAnother()
{
printf ("Do you want to add another Customer?\n");
printf ("Enter 'Y' for yes and 'N' to return to the Main Menu\n");
char input;
input = getchar();
if (input == 'Y' || input == 'y')
{
getchar();
addCustomer();
}
else if (input == 'N'|| input == 'n')
{
fclose (cfp);
customerMainMenu();
}
else
{
printf ("Invalid Option! Only Y or N are allowed\n");
system ("PAUSE");
clrscr();
askAnother();
}
}
boolean cCheck(char *test, int max)
{
int x;
for (x =0; x<max; x++)
{
if (isdigit(test[x]))
{
return FALSE;
}
if (x==max)
{
return TRUE;
}
x++;
}
return TRUE;
}
/**
* This method will compare the ID passed from the ID of the customer to check
* whether it is exists or not. If it exists it will output 1 otherwise it
* will output -1. This will make sure that the Person's ID is unique
*
*/
int customerID (int cCheck)
{
rewind (cfp);
while (fread (&c,STRUCTSIZE,1,cfp)==1)
{
if (c.ID == cCheck)
{
return 1;
}
else
{
return 0;
}
}
return 1;
}
EDIT!!
Uploading Image to show what I mean if I'm not clear
(Notice how the name and surname differ from those Input)
!http://s017.radikal.ru/i443/1212/c8/1ea9bc56d980.jpg
The following shows what I have in the file
(only one file)
!http://s017.radikal.ru/i431/1212/49/2a0df6acf9ec.jpg
if (customerID(scanf ("%d",&cCheck)) == 1)
Here, you are the return value of scanf() to function customerID() whereas you actually wanted to pass the scanned value cCheck.
You can separate the call to function and input reading as below:
if(scanf ("%d",&cCheck) != 1) {
// Input error handling
}
else if (customerID(cCheck) == 1) {
...
Another issue is, you have a function named cCheck and you also have a local variable named cCheck. Rename one of them appropriately.

Method to Batch Update on C Programming

I need to do this Batch Update on a products list. This batch update has to retrieve EVERY product from within the database and get it's "quantity in Order". This "Quantity in Order" then has to be added to the current stock:
For e.g:
Current in Stock : 100
In order: 150
After the Batch Update they have to be:
Current in Stock :250
In Order: 0
I have done this method (see below) BUT when I run it, it's not updating my Stock and neither my Order.
void batchUpdate()
{
printf ("\n\n\n\n\t\t ********** Batch Update *******\n \n \n");
int tempOrder;
int tempStock;
int tempAdding;
if ((pfp = fopen("products.dat","r+b")) == NULL)
{
printf ("Error! Cannot Open Products.dat!\n");
printf ("Returning to Main Menu\n");
system ("PAUSE");
orderMainMenu();
}
while (fread(&p,STRUCTSIZE,1,pfp) == 1)
{
tempOrder = p.pOrder;
tempStock = p.pStock;
tempAdding = tempOrder + tempStock;
p.pOrder = 0;
p.pStock = tempAdding;
fwrite (&p,STRUCTSIZE,1,pfp);
}
fclose (pfp);
printf ("Orders and Stock Updated!\n");
printf ("Returning to Main Menu!\n");
system ("PAUSE");
orderMainMenu();
}
I tried using fseek (pfp, -STRUCTSIZE,SEEK_CUR); but that turned my program into an infinite Loop.
Also when I tried to use show All products in database, they skipped my first record and just went into an infinite loop showing the last record only. I just have to end up deleting the products.dat file from the system and redo it again.
Any suggestion? I do believe that there is something wrong with the fseek().
Thanks in advance
Found the error,
did not do an fflush (pfp); after the fwrite();
This is the final working code;
void batchUpdate()
{
printf ("\n\n\n\n\t\t ********** Batch Update *******\n \n \n");
int tempOrder;
int tempStock;
int tempAdding;
if ((pfp = fopen("products.dat","r+b")) == NULL)
{
printf ("Error! Cannot Open Products.dat!\n");
printf ("Returning to Main Menu\n");
system ("PAUSE");
orderMainMenu();
}
while (fread(&p,STRUCTSIZE,1,pfp) == 1)
{
tempOrder = p.pOrder;
tempStock = p.pStock;
tempAdding = tempOrder + tempStock;
p.pOrder = 0;
p.pStock = tempAdding;
fseek (pfp,-STRUCTSIZE,SEEK_CUR);
fwrite (&p,STRUCTSIZE,1,pfp);
fflush(pfp); //THIS WAS EMITTED AND WAS CAUSING PROBLEMS
}
fclose (pfp);
printf ("Orders and Stock Updated!\n");
printf ("Returning to Main Menu!\n");
system ("PAUSE");
orderMainMenu();
}

How to check whether ID already exists in File with C Programming

I have this coding down below (just posting the Customers Management only).
This a database in which I am adding a customer each time it passes. Now I need to check whether the c.ID which is the client ID exists or not.
I tried doing a method called searchID which returns 1 if it's found or -1 if it's not found.
Problem is when I try to run the program, the program literally hangs there. Whether I press 23 or "ENTER" nothing happens and I would need to exit it using the CTRL + C;
so this is how it works:
When I add a customer (Which is a struct) it saves into the file but I first need to check
whether the ID exists in the database or not otherwise I need to ask the user to either input another ID or go back to the Main Menu
Any suggestions please?? thank you
#include<io.h>
#include<fcntl.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include "..\Headers\common.h"
#include "..\Headers\customerManagement.h"
static FILE *cfp;
static customer c;
#define STRUCTSIZE sizeof (customer)
/** This is the Customers's Main Menu in which the various sections can be
* accessed from here
*/
boolean customerMainMenu()
{
int optionC;
clrscr();
copyright();
printf ("\n\n\n\n\t\t ************* Customer's Main Menu *************\n \n \n");
printf ("Press [1] to add a new Customer\n");
printf ("Press [2] to edit a Customer\n");
printf ("Press [3] to list all Customers\n");
printf ("Press [4] to Show a Customer's last Order\n");
printf ("Press [5] to go back to Main Menu\n\n\n");
if (scanf ("%d",&optionC) == 1)
{
switch (optionC)
{
case 1:
{
clrscr();
getchar();
addCustomer();
break;
}
case 2:
{
printf ("Edit a Customer\n");
break;
}
case 3:
{
clrscr();
listCustomers();
getchar();
while (getchar()!='\n')
{
}
break;
}
case 4:
{
printf ("Customer's Last Order\n");
break;
}
case 5:
{
system ("PAUSE");
break;
}
default:
{
if (optionC != 1 || optionC != 2 || optionC != 3 || optionC != 4 || optionC !=5)
{
clrscr();
printf ("Invalid option!\n");
system ("PAUSE");
customerMainMenu();
}
break;
}
}
}
return TRUE;
}
/**
* This following method will append a customer to the
* database at the end of the file
*
* */
void addCustomer ()
{
char ch;
copyright();
printf ("\n\n\n\n\t\t ************* Add Client **********\n \n \n");
if ((cfp = fopen ("customers.dat","a+b")) == NULL)
{
fputs("Can't open customers.dat file\n",stderr);
}
printf ("\tThis will add another customer to the the database\n");
printf ("\tPress 'Y' to confirm or 'N' to return to the Client Main Menu\n\tWITHOUT adding a customer\n");
ch = getchar();
if (ch == 'n' || ch == 'N')
{
customerMainMenu();
}
else if (ch == 'y' || ch == 'Y')
{
clrscr();
printf ("\n\n\n\n\t\t ************* Add Client **********\n \n \n");
printf ("Please enter Name:\n");
while (scanf ("%s", c.name) == 0 || cCheck(c.name,100) == FALSE);
{
}
printf ("Please Enter Surname: \n");
while (scanf ("%s",c.surname) == 0 && cCheck (c.surname,100) == FALSE);
{
}
printf ("Please Enter ID Card, [NOTE! Only numbers are allowed!]\n");
int cID;
cID = 0;
while (scanf ("%d",&cID)==0)
{
printf ("Only Numbers are allowed!\n");
while (getchar() != '\n')
{
}
}
if (searchID(cID) == 1)
{
printf ("This ID already exists. Client already exists!\n");
printf ("Do you want to input another ID or return to Main Menu?\n");
printf ("Press 'Y' if you enter another ID, press any other key to return to Main Menu\n:");
ch = getchar();
if (ch == 'y' || ch == 'Y')
{
printf ("Enter another ID:\n");
while (scanf ("%d",&cID)==0)
{
printf ("Only Numbers are allowed!\n");
while (getchar() != '\n')
{
}
}
searchID(cID);
}
else if (searchID(cID) == -1)
{
cID = c.ID;
getchar();
}
}
while (getchar()!='\n')
{
}
printf ("Please Enter Address:\n");
gets(c.address);
fwrite (&c,STRUCTSIZE, 1, cfp);
printf ("For Testing purposes:\n");
printf (" %s\n %s\n %s\n %d\n", c.name, c.surname, c.address, c.ID);
askAnother();
}
else
{
printf ("\nInvalid choice! Either Y or N is accepted\n");
system ("PAUSE");
getchar();
addCustomer();
}
}
void listCustomers()
{
if ((cfp = fopen ("customers.dat","rb")) == NULL)
{
fputs("Can't open customers.dat file\n",stderr);
printf ("Returning to Customer Main Menu");
system ("PAUSE");
customerMainMenu();
}
rewind (cfp);
while (fread (&c,STRUCTSIZE,1,cfp)==1)
{
printf ("Customer: %s %s ID: %d\n", c.surname, c.name, c.ID);
}
fclose (cfp);
// system ("PAUSE");
}
void askAnother()
{
printf ("Do you want to add another Customer?\n");
printf ("Enter 'Y' for yes and 'N' to return to the Main Menu\n");
char input;
input = getchar();
if (input == 'Y' || input == 'y')
{
getchar();
addCustomer();
}
else if (input == 'N'|| input == 'n')
{
fclose (cfp);
customerMainMenu();
}
else
{
printf ("Invalid Option! Only Y or N are allowed\n");
system ("PAUSE");
askAnother();
}
}
boolean cCheck(char *test, int max)
{
int x;
for (x =0; x<max; x++)
{
if (isdigit(test[x]))
{
return FALSE;
}
if (x==max)
{
return TRUE;
}
x++;
}
return TRUE;
}
int fileSize()
{
int lengthOfFile;
int file;
file = open("Customers.dat",O_RDONLY,0);
lengthOfFile = lseek (file,0, SEEK_END);
return lengthOfFile;
}
int getNoOfRecords()
{
return (fileSize()/(STRUCTSIZE));
}
/**
* This method will compare the ID passed from the ID of the customer to check
* whether it is exists or not. If it exists it will output 1 otherwise it
* will output -1. This will make sure that the Person's ID is unique
*
*/
int searchID (int cID)
{
// for the while loop
int index;
index = 0;
//gets the number of records currently held in the file.
int records;
records = getNoOfRecords();
//User will input the ID into this variable and it will be checked
//whether it exists or not
int IDstatus;
IDstatus = 0;
while (index != records)
{
fread (&c,STRUCTSIZE,1,cfp);
if (c.ID == cID)
{
IDstatus = 1;
}
else
{
IDstatus = -1;
}
}
return IDstatus;
}
EDIT:
There are either 2 things:
Either the Method is not working the SearchID() method because even though I have 2 IDs which are 0 now, they are still accepting it
or else because of the c.ID which is staying 0.
When I'm inputting the data, it is accepting it BUT when I try to output the whole record, the Client ID stays 0.
Added to that, it IS letting me having Two IDs which are 0 so most probably the method is not working.... Thanks for all the help until now!
You missed to increment index, and of course you should exit the loop when you found the id:
while (index != records)
{
fread (&c,STRUCTSIZE,1,cfp);
if (c.ID == cID)
{
IDstatus = 1;
break; // <<<< otherwise IDStatus will be overwritten by next iteration
}
else
{
IDstatus = -1;
}
index++; // <<< otherwise endless loop
}

Resources