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
}
Related
I want so that when the user enters e it will run my function called enter and scan in values but all I get is VECRQ?:, why is this? Did I call upon the function wrong?
I tried having the while loop to 1 also instead of menuoption != 'q' didn't work. I was thinking that with the menuoption is not equal to 'q' it will keep the loop running until the user actually enters 'q' to shut the program off.
#include <stdio.h>
int enter(int measurments[], int nrOfmeasurments)
{
while(nrOfmeasurments<10)
{
printf("Enter measurment #%d (or q to quit): ",nrOfmeasurments+1);
int oneMeasurment;
int readInteger = scanf("%d",&oneMeasurment);
if(readInteger)
{
measurments[nrOfmeasurments] = oneMeasurment;
nrOfmeasurments ++;
//return nrOfmeasurments;
}
else
{
char tmp;
scanf(" %c",&tmp);
break;
}
}
if(nrOfmeasurments==10)
{
printf("Array is full\n");
}
return nrOfmeasurments;
}
int main(void)
{
int measurments[10];
int nrOfmeasurments;
char menuoption;
printf("Measurment tool 2.0\n");
while (menuoption != 'q')
{
printf("VECRQ?:\n");
scanf(" %c",&menuoption);
if (menuoption == 'e')
{
//int MeasurmentData[10];
//int nrOfmeasurments;
//enter(measurments, nrOfmeasurments);
nrOfmeasurments = enter(measurments, nrOfmeasurments);
}
else if(menuoption == 'v')
{
}
else if(menuoption == 'c')
{
}
else if(menuoption == 'q')
{
printf("Exiting Measurment tool 2.0\n");
break;
}
}
}
Don't forget to init your variables with default values. Your problem is that nrOfmeasurments is not initialized and have some trash value. Also, set a default value to menuoption for some non q char to be sure, that your loop will be executed at least one time
while i'm working on my manii project phonebook , i faced some problems in delete function when there are multi result for the same first name (i use first name to search about the contact that i want to delete)
in this case i made extra variable in my structure called "ID" and this ID Auto fill in my program (so each user has a unique id) , so i can later find exactly the result that the user want to delete it ,and it works fine , but when i delete a contact from the file it left me with a gap and this effect on the next contact
For Example :
i have 3 contacts each one has an iD 1 , 2 and 3 , when i delete No.2 , it become 1 and 3 , when i add a new user my Auto fill loop will count the number of the contacts (2) and give the new one ID of 3 , that left me with 3 contacts with ID of 1 , 3 , and 3 and this's wrong
so i came with an idea to Reset all the IDs after each Delete operation , it seems good for me and this few line should do it , i don't know why this part doesn't work , even i tried to put this loop in add() function so it should be good at this position too , but it doesn't work too
// reset all ids
rewind(ft);
int id=1;
while(fread(&p,sizeof(p),1,ft)==1)
{
p.id = id;
fwrite(&p,sizeof(p),1,ft);
id++;
}
This is my Full code with 0 Errors and 0 warning , and it work fine except the part of reset ids
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <string.h>
#include <conio.h>
struct address // nested
{
char city[30],
street[30];
int flat;
};
struct phonebook // main
{
int id;
char firstName[20],
lastName[20];
struct address add;
long int phNumber;
char email[50];
};
// functions ...
void launcher();
void menu();
void add();
void load();
void query();
void Delete();
void modify();
void back();
void scan(char *name);
int main()
{
system("color 1e");
printf("Let's start!\n");
launcher();
return 0;
}
void launcher()
{
menu();
}
void back()
{
menu();
}
void menu()
{
system("cls");
printf("\t\t *********** PhoneBook! *************");
printf("\n\n\t\t\t\t <| Menu |>\t\t\n\n");
printf("\t\t1.Add \t2.Load \t3.Query \n\t\t4.Modify \t5.Delete\t6.Exit\n");
switch(getch())
{
case '1' :
add();
break;
case '2' :
load();
break;
case '3' :
query();
break;
case '4' :
modify();
break;
case '5' :
Delete();
break;
case '6' :
printf("the program exit successfully");
exit(0);
break;
default:
system("cls");
int i;
for(i=15 ; i>-1 ; i--)
{
system("cls");
printf("\nInvalid key Entered , please enter any key from 1 to 6 only!\n");
printf("you will back to the main menu automatically in %d seconds",i);
Sleep(1000);
}
menu();
}
}
void add()
{
system("cls");
struct phonebook p; // local define
FILE *f;
f= fopen("data","ab+");
int id=1;
while(fread(&p,sizeof(p),1,f)==1)
{
id++;
}
printf("\nFirst Name : ");
scan(p.firstName);
printf("\nLast Name : ");
scan(p.lastName);
printf("\nEnter the address .. ");
printf("\n\tCity : ");
scan(p.add.city);
printf("\n\tStreet : ");
scan(p.add.street);
printf("\n\tFlat : ");
scanf(" %d",&p.add.flat);
printf("\nPhone number : ");
scanf(" %ld",&p.phNumber);
printf("\nEmail : ");
scan(p.email);
p.id=id; // Auto fill
fwrite(&p,sizeof(p),1,f); // saving the data into a file
fclose(f);
puts("\n\n\t\tdata is saved successfully!");
puts("\t\tEnter any key to back to the main menu");
getch();
back();
}
void load()
{
struct phonebook p;
system("cls");
FILE* f;
f = fopen("data","rb");
if(f==NULL)
{
puts("\n An error occur while opening the file >");
exit(1);
}
while(fread(&p,sizeof(p),1,f)==1)
{
printf("\n\n\t\t\t\t <| loading List |>\t\t\n\n");
printf("First name : %s\nLast name : %s\nAddress Info ...\nCity : %s\nStreet : %s\nFlat : %d\nPhone Number : %ld\nEmail : %s\nid : %d\n",p.firstName,p.lastName,p.add.city,p.add.street,p.add.flat,p.phNumber,p.email,p.id);
puts("\t\t * Enter any key to show more *");
getch();
system("cls");
}
fclose(f);
puts("\t\tno more data to show !");
puts("\t\tEnter any key to back to the main menu");
getch();
back();
}
void query()
{
system("cls");
struct phonebook p;
FILE* f;
f = fopen("data","rb");
if(f==NULL)
{
puts("\n An error occur while opening the file >");
exit(1);
}
char name[50];
int flag=0;
printf("please enter a name : ");
scan(name);
system("cls");
while(fread(&p,sizeof(p),1,f)==1)
{
if(strcmp(name,p.firstName)==0)
{
flag++;
printf("\n[%d] result found\n",flag); // ==> static text
printf("First name : %s\nLast name : %s\nAddress Info ...\nCity : %s\nStreet : %s\nFlat : %d\nPhone Number : %ld\nEmail : %s\n",p.firstName,p.lastName,p.add.city,p.add.street,p.add.flat,p.phNumber,p.email);
puts("");
}
}
if(flag == 0)
{
puts("file not found");
}
fclose(f);
puts("\t\tEnter any key to back to the main menu");
getch();
back();
}
void modify()
{
system("cls");
struct phonebook p,s;
FILE* f;
f = fopen("data","rb+");
if(f==NULL)
{
puts("\n An error occur while opening the file >");
exit(1);
}
char name[50];
int flag=0;
printf("please enter a name : ");
scan(name);
system("cls");
int results[50];
while(fread(&p,sizeof(p),1,f)==1)
{
if(strcmp(name,p.firstName)==0)
{
results[flag] = p.id;
flag++;
printf("\n\n >> full information about the result No. [%d] :- \n",p.id);
printf("First name : %s\nLast name : %s\nAddress Info ...\nCity : %s\nStreet : %s\nFlat : %d\nPhone Number : %ld\nEmail : %s\n",p.firstName,p.lastName,p.add.city,p.add.street,p.add.flat,p.phNumber,p.email);
}
}
if(flag == 0)
{
puts("file not found");
}
else
{
int choice,i,found=0;
int lastResultID = p.id;
puts("Please enter the Number of the result to confirm your order");
scanf(" %d",&choice);
// confirmation
for(i=0 ; i<flag ;i++){
if(results[i] == choice){
found =1;
break;
}
}
if(found == 0){
puts("\n Ops! Result not found.\nmaybe you entered a wrong No. OR an Error occurs Try again.");
Sleep(5000);
back();
}else{
//printf("\n%d\n",lastResultID);
puts("\n >> Are you want to modify this result ? type (Y) for Yes or (N) for No !");
char c = getch();
if( c == 'Y' || c == 'y')
{
system("cls");
printf("\nFirst Name : ");
scan(s.firstName);
printf("\nLast Name : ");
scan(s.lastName);
printf("\nEnter the address .. ");
printf("\n\tCity : ");
scan(s.add.city);
printf("\n\tStreet : ");
scan(s.add.street);
printf("\n\tFlat : ");
scanf(" %d",&s.add.flat);
printf("\nPhone number : ");
scanf(" %ld",&s.phNumber);
printf("\nEmail : ");
scan(s.email);
fseek(f,-sizeof(p)*(lastResultID-choice+1),SEEK_CUR);
s.id=choice;
fwrite(&s,sizeof(p),1,f); // saving
puts("\n\t\tyour data is modified!");
fclose(f);
puts("\t\tEnter any key to back to the main menu");
getch();
back();
}
else
{
system("cls");
puts("nothing change ! , press any key to back to the main menu !");
getch();
back();
}
}
}
}
void Delete()
{
int found =0;
system("cls");
struct phonebook p,s;
FILE* f;
FILE* ft;
f = fopen("data","rb");
ft = fopen("temp","ab+");
if(f == NULL || ft == NULL)
{
puts("\n An error occur while opening the file >");
perror("fopen() failed");
exit(1);
}
char name[50];
int flag=0,i;
int results[50];
printf("please enter a name : ");
scan(name);
system("cls");
while(fread(&p,sizeof(p),1,f)==1)
{
if(strcmp(name,p.firstName)==0)
{
results[flag] = p.id;
flag++;
printf("\n\n >> full information about the result No. [%d] :- \n",p.id);
printf("First name : %s\nLast name : %s\nAddress Info ...\nCity : %s\nStreet : %s\nFlat : %d\nPhone Number : %ld\nEmail : %s\n",p.firstName,p.lastName,p.add.city,p.add.street,p.add.flat,p.phNumber,p.email);
}
}
if(flag == 0)
{
puts("file not found");
}
else{
puts(" ");
int choice,check=0;
puts("please enter the number of the result which you want to delete");
scanf(" %d",&choice);
// confirmation
for(i=0 ; i<flag ;i++){
if(results[i] == choice){
check =1;
break;
}
}
if(check == 0){
puts("\n Oops! Result not found.\nmaybe you entered a wrong No. OR an Error occurred Try again later.");
Sleep(3500);
back();
}else{
puts("\n >> Do you want to delete this result ? type (Y) for Yes or (N) for No !");
char c = getch();
rewind(f); // reset the pointer
if( c == 'Y' || c == 'y')
{
system("cls");
while(fread(&p,sizeof(p),1,f)==1)
{
if(choice != p.id)
fwrite(&p,sizeof(p),1,ft);
if(choice == p.id)
found++;
}
//perror("fread() failed");
if(found == 0)
{
puts("An error occurred , please try again");
remove("temp");
Sleep(3500);
back();
fclose(f); // ==?
fclose(ft); // ==?
}
else
{
// reset all ids
rewind(ft);
int id=1;
while(fread(&p,sizeof(p),1,ft)==1)
{
p.id = id;
fwrite(&p,sizeof(p),1,ft);
id++;
}
fclose(f); // ==?
fclose(ft); // ==?
remove("data");
int c = rename("temp","data");
puts("file is deleted successfully");
if(c != 0)
perror("rename() failed"); // handling for rename error
}
puts("\t\tEnter any key to back to the main menu");
getch();
back();
}
else
{
system("cls");
puts("nothing changed ! , press any key to back to the main menu !");
getch();
back();
}
}
}
/*else
{
puts("\n >> Are you want to delete this result ? type (Y) for Yes or (N) for No !");
char c = getch();
if( c == 'Y' || c == 'y')
{
rewind(f);
while(fread(&p,sizeof(p),1,f)==1)
{
if(strcmp(name,p.firstName)!=0)
fwrite(&p,sizeof(p),1,ft);
}
fclose(f);
fclose(ft);
remove("data");
int c = rename("temp","data");
puts("file is deleted successfully");
if(c != 0)
perror("rename() failed");
// reset all ids
int id=1;
while(fread(&p,sizeof(p),1,f)==1)
{
p.id = id;
fwrite(&p,sizeof(p),1,f);
id++;
}
puts("\t\tEnter any key to back to the main menu");
getch();
back();
}
else
{
system("cls");
puts("nothing change ! , press any key to back to the main menu !");
getch();
back();
}
}*/
}
void scan(char *name)
{
int i=0,j;
char c,ch;
do
{
c=getch();
if(c!=8&&c!=13)
{
*(name+i)=c;
putch(c);
i++;
}
if(c==8)
{
if(i>0)
{
i--;
}
// printf("h");
system("cls");
for(j=0; j<i; j++)
{
ch=*(name+j);
putch(ch);
}
}
}
while(c!=13);
*(name+i)='\0';
}
Thanks in advance
What about using the highest id+1 instead of counting them?
int id = 1;
while(fread(&p,sizeof(p),1,f)==1)
{
if (p.id >= id) id = p.id+1;
}
You cannot interleave fread and fwrite without an intervening fseek:
7.21.5.3/7 When a file is opened with update mode ('+' as the second or third character in the above list of mode argument values), both input and output may be performed on the associated stream. However, output shall not be directly followed by input without an intervening call to the fflush function or to a file positioning function (fseek, fsetpos, or rewind), and input shall not be directly followed by output without an intervening call to a file positioning function, unless the input operation encounters end-of-file.
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);
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.
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
}
}