This is my code for a project I'm working on, my aim is to create a database where i can add edit and delete records. The program is compiling but very slowly and often crashes. I am a mere beginner and I cant figure out why this is happening. Maybe somebody can help me improve the code or point me in the right direction?
enter code here
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
void clearInput(void);
void listAll (void);
void deleteAccount(void);
void addNewAccount(void);
void modifyAccount(void);
int prompt(void);
struct account{
int number;
char lastname[15];
char firstname[15];
float balance;
struct account*next;
};
struct account *firsta, *currenta, *newa;
int anum = 0;
int main()
{
FILE *datafile;
char *filename="studentdatabase.txt";
char ch;
firsta=NULL;
datafile=fopen(filename, "r");
if (datafile) /*assume doesnt exist otherwise*/
{
firsta=(struct account*)malloc(sizeof(struct account));
currenta=firsta;
while (1)
{
newa=(struct account*)malloc(sizeof(struct account));
fread(currenta, sizeof(struct account),1,datafile);
if (currenta->next==NULL)
break;
currenta->next=newa;
}
fclose(datafile);
anum=currenta->number;
}
do
{
clearInput();
puts("\nA - Add a new account");
puts("D - Delete account");
puts("L - List all accounts");
puts("M - Modify account");
puts("Q - Quit this program\n");
printf("\tYour Choice:");
ch=getchar();
ch=toupper(ch);
switch(ch)
{
case 'A':
puts("Add new account\n");
clearInput();
addNewAccount();
break;
case 'D':
puts("Delete account\n");
deleteAccount();
break;
case 'L':
puts("List all accounts\n");
listAll();
break;
case 'M':
puts("Modify an account\n");
modifyAccount();
break;
case 'Q':
puts ("Quit\n");
default:
break;
}
}
while(ch!='Q');
/*Save the records to disc*/
currenta=firsta;
if(currenta==NULL)
return(0); /*No data to write - End of Program*/
datafile=fopen(filename,"w");
if (datafile=NULL)
{
printf("Error writing to %s\n", filename);
return(1);
}
/*write each record to disc*/
while(currenta!=NULL)
{
fwrite(currenta, sizeof(struct account),1,datafile);
currenta=currenta->next;
}
fclose(datafile);
return(0);
}
/*This function clears any text from the input stream*/
void clearInput(void)
{
fflush(stdin);
}
void addNewAccount(void)
{
newa=(struct account*)malloc(sizeof(struct account));
/*Check to see if this is the first record, if so then
itialize all the pointers to this, first ftrusture in
the database*/
if(firsta==NULL)
firsta=currenta=newa;
/*Otherwise you must find the end of the structure list
(easily spotted by the NULL pointer) and add on the new
structure you just allocated memory for*/
else
{
currenta=firsta; /*makes the first current*/
/*loop throught all records*/
while(currenta->next!=NULL)
currenta=currenta->next;
/*last record found*/
currenta->next=newa; /*save the address of new*/
currenta=newa; /*makes current new*/
}
/*now you just fill in the new structure*/
anum++;
printf("%27s:%5i\n","Account number", anum);
currenta->number=anum;
printf("%27s:","Enter customer's lastname");
gets(currenta->lastname);
printf("%27s:","Enter firstname");
gets(currenta->firstname);
printf("%27f:€","Enter account balance");
scanf("%f", ¤ta->balance);
/*Finally cap the new record with a NULL pointer so
that you know its the last record*/
currenta->next=NULL;
}
void listAll(void)
{
if (firsta==NULL)
puts("There are no records to print out");
else
{
printf("%6s %-15s %-15s €%8.2f\n",
currenta->number,
currenta->lastname,
currenta->firstname,
currenta->balance);
}
while ((currenta=currenta->next) !=NULL);
}
void deleteAccount(void)
{
int record;
struct account *previousa;
if(firsta==NULL)
{
puts("There are no records to delete");
return;
}
listAll();
/*Shows all record first*/
printf("Enter account number to delete: ");
scanf("%d",&record);
currenta=firsta;
while(currenta!=NULL)
{
{
if(currenta->number==record)
{
if(currenta==firsta) /*special condition*/
firsta=currenta->next;
else
previousa->next=currenta->next;
free(currenta);
printf("Account %d deleted! \n", -record);
return;
}
previousa=currenta;
currenta=currenta->next;
}
}
printf("Account %d was not found!\n", record);
puts("Nothing deleted.");
}
void modifyAccount(void)
{
int record;
if (firsta==NULL)
{
puts("There are no records to modify!");
return;
}
listAll(); /*Show all records first*/
printf("Enter account number to modify or change: ");
scanf("%d",&record);
currenta=firsta;
while (currenta!=NULL)
{
if(currenta->number==record)
{
printf("Account €%d:\n", currenta->number);
printf("Last name: %s\n", currenta->lastname);
if (prompt())
gets (currenta->lastname);
printf("firstname %s \n", currenta->firstname);
if (prompt())
gets(currenta->firstname);
printf("Balance %8.2f\n", currenta->balance);
if (prompt())
scanf("%f", ¤ta->balance);
return;
}
else
{
currenta=currenta->next;
}
}
printf("Account %d was not found!\n", record);
}
int prompt(void)
{
char ch;
clearInput();
printf("Update?");
ch=getchar();
ch=toupper(ch);
clearInput();
if(ch=='Y')
{
printf("Enter new. ");
return(1);
}
else return(0);
}
Your input loop in the start looks a bit odd to me.
while (1)
{
newa=(struct account*)malloc(sizeof(struct account));
fread(currenta, sizeof(struct account),1,datafile);
if (currenta->next==NULL)
break;
currenta->next=newa;
}
I understand that you are relying on the fact that when you wrote out the list the last structure written should have had the 'next' field set to NULL as your end marker, but I would suggest you might want find a cleaner way to check for end. This will also have a small memory leak since you allocate newa but then break on the last read, so that last newa is never used.
Also, the load routine results in the first record in the list being an empty record because you allocate firsta, set currenta to it, then allocate newa for the first read and set it to the next of the empty currenta.
After loading, though you will only ever have 1 record. Notice that you are not reading into newa you read into currenta
fread(currenta, sizeof(struct account),1,datafile);
Your attempt to save the data also has an issue, you have one of the classic typo errors:
datafile=fopen(filename,"w");
if (datafile=NULL)
^^^
you are reassigning NULL to the datafile variable, you need == here.
You appear to assume through out the code that currenta, which is global, is in a known state. For example, in the listAll function, your code is not setting currenta before printing out a record. Note also listAll is not looping and printing all records, you print only whatever currentA is then move that variable to being NULL.
I would suggest you keep only firsta as a global to locate the head of the list, but everywhere else you use local variables and set them up correctly.
As previously mentiond, your printf statements need to match their data types. That can cause failures.
One problem is in the printf:
printf("%6s %-15s %-15s €%8.2f\n",
currenta->number,...
Here you are printing an integer currenta->number using %s format specifier, use %d instead.
Another problem is when you are trying to print the list:
printf(...);
while ((currenta=currenta->next) !=NULL);
This is not how you print the list. You need to have a printf as the body of the while loop:
while (currenta != NULL) {
printf(...);
currenta = currenta->next;
}
Related
This code read/write data to/from binary file. Here modify() will take input from user, search for it in the file. If found, will prompt user to give new entry and the older entry would be replaced.
The question is, in modify() after fwrite() if I break the while loop then everything would be fine but, if I don't then the entry would still be modified but along with that the content of the file would be duplicated, why so ?
As in the beginning there are no duplicate entries in the file. So what I expect is, that even if I don't use break the loop should go on and finally terminate when whole file has been read. Here, the if(strcmp(e.name,user)==0) would only be true for one entry therefore the control should enter only once in this if block. Then how the entries are getting duplicated ?
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void add(FILE *);
void list(FILE *);
void modify(FILE *);
struct emp
{
char name[20];
int id;
float sal;
}e;
void add(FILE *f)
{
char *p=NULL;
printf("\nEnter name id sal\n");
scanf(" %s %d %f", e.name,&e.id,&e.sal);
fseek(f,0,SEEK_END);
if((fwrite(&e,sizeof(struct emp),1,f))==1)
{
printf("\nAdded Successfully\n");
}
else
{
printf("\nError wrting to file in ADD func\n");
}
}
void list(FILE *f)
{
rewind(f);
while(fread(&e,sizeof(struct emp),1,f)>0)
{
printf("\nRead %s %d %f\n",e.name,e.id,e.sal);
}
}
void modify(FILE *f)
{
char user[20];
char *p=NULL;
printf("\nEnter name to modify\n");
scanf(" %s", user);
rewind(f);
while(fread(&e,sizeof(struct emp),1,f)==1)
{
//printf("\n --------------- %s %d %f\n",e.name,e.id,e.sal);
if(strcmp(e.name,user)==0)
{
//fseek(f,-sizeof(struct emp),SEEK_CUR);
printf("\nEnter new name id salary\n");
scanf(" %s %d %f", e.name,&e.id,&e.sal);
fseek(f,-sizeof(struct emp),SEEK_CUR);
if(fwrite(&e,sizeof(struct emp),1,f)==1)
{
printf("\nModified successfull!!\n");
//break;
}
else
{
printf("\nError while modifying\n");
}
}
else
{
printf("\n\nstring not matched\n\n");
}
}
}
int main()
{
char val='T';
FILE *fp=NULL;
if((fp=fopen("database.dat","rb+"))==NULL)
{
if((fp=fopen("database.dat","wb+"))==NULL)
{
printf("\nError opening file in wb+ mode\n");
exit(0);
}
}
do
{
printf("\nEnter a to add, l to list, d to delete, m to modify and e to exit\n");
scanf(" %c", &val);
switch(val)
{
case 'a':
add(fp);
break;
case 'l':
list(fp);
break;
case 'm':
modify(fp);
break;
case 'd':
// del(fp);
break;
case 'e':
fclose(fp);
exit(0);
break;
default:
printf("\nInvalid Input\n");
break;
}
}
while(1);
}
I think it's a problem between fread() and fwrite().
After you use fwrite() to modify the emp, you continue the while loop without using fseek().
In fact, before, you used fseek() to go back and it was OK.
Now you have to place another fseek() which doesn't move, like this:
fseek(f, 0, SEEK_CUR);
Now you can remove the break and your Modify() function would seems like this:
void modify(FILE *f)
{
char user[20];
printf("\nEnter name to modify\n");
scanf("%s",user);
fflush(stdin);
rewind(f);
while(fread(&e,sizeof(struct emp),1,f)==1)
{
if(strcmp(e.name,user)==0)
{
printf("\nEnter new name id salary\n");
scanf("%s %d %f",e.name,&e.id,&e.sal);
fflush(stdin);
fseek(f,-sizeof(struct emp),SEEK_CUR);
if(fwrite(&e,sizeof(struct emp),1,f)==1)
{
printf("\nModified successfull!!\n");
//break; //This can be removed
fseek(f, 0, SEEK_CUR); //Place this here
}
else
{
printf("\nError while modifying\n");
}
}
else
{
printf("\n\nstring not matched\n\n");
}
}
}
I'm trying to write a simple phone book program. I have completed the first function and according to I observe it works without error. However, in second function (which is ""display()"") I can't show to user after I enter person knowledge. I'm working with binary mode. What the problem is in second function I couldn't understand. If you examine and help I'll be satisfied. Thanks in advance.
#include <stdio.h>
#include <stdlib.h> // "stdlib" library contains of exit() function
#include <malloc.h> // "malloc" library contains of malloc() function
#include <Windows.h> // "Windows" library contains of Sleep() function which waits the system as you want
#include <io.h> // "io" library contains of filelength() function
struct personKnowledge
{
char name[32];
char surname[32];
char number[32];
};
FILE *ptrFILE,*ptrFILE1;
long int recordLength,totalRecordLength,location;
static int counter = 0;
int number,totalRecordNumber;
void newRecord();
void display();
void deletE();
void add();
void update();
int main()
{
int choice;
do
{
printf("\n\t\t --- Phone Book Program ---");
printf("\n\n\t\t 1) New record"); // The options are being presented to user
printf("\n\n\t\t 2) Display person knowledge");
printf("\n\n\t\t 3) Delete someone");
printf("\n\n\t\t 5) Update person knowledge");
printf("\n\n\t\t 6) Exit");
printf("\n\n\nEnter your choice: ");
scanf("%d", &choice);
switch (choice)
{
case 1:
{
newRecord();
break;
}
case 2:
{
display();
break;
}
case 3:
{
break;
}
case 4:
{
break;
}
case 5:
{
break;
}
case 6:
{
printf("\nWorking has been completed.\n");
return 0;
}
default:
{
printf("\nWrong entry! The program has been terminated.\n");
break;
}
}
} while (choice >= 1 && choice <= 6);
return 0;
}
void newRecord()
{
if ((ptrFILE = fopen("Phone Book.dat", "wb")) == NULL)
{
printf("The file couldn't open\n");
exit(0);
}
system("cls"); // Screen is being cleaned
struct personKnowledge *p; // p means person
p = (struct personKnowledge *)malloc(sizeof(struct personKnowledge)); // Memory is being allocated
fflush(stdin);
recordLength = sizeof(p); // size of p
printf("|| For the %d. person ||\n", counter+1);
printf("\n\Express person name: "); // User is entering the person's knowledge and they are being saved in file
gets(p->name);
printf("Express %s's surname: ", p->name);
gets(p->surname);
printf("Express %s's number: ", p->name);
gets(p->number);
fwrite(&(*p), recordLength, 1, ptrFILE);
printf("\nPlease wait, information is saving to file..\n");
Sleep(750);
printf("*-* Saving operation has been completed succesfully. *-*\n");
free(p);
counter++;
fclose(ptrFILE);
}
void display()
{
if ((ptrFILE = fopen("Phone Book.dat", "rb")) == NULL)
{
printf("The file couldn't open\n");
exit(0);
}
system("cls"); // Screen is being cleaned
struct personKnowledge *s; // s means searching
s = (struct personKnowledge *)malloc(sizeof(struct personKnowledge));
fflush(stdin);
recordLength = sizeof(s);
totalRecordLength = filelength(fileno(ptrFILE));
totalRecordNumber = totalRecordLength / recordLength;
printf("\n\nExpress person record number which you search: ");
scanf("%d", &number);
location = (number - 1)*recordLength;
fseek(ptrFILE, location, SEEK_SET);
fread(&(*s), recordLength, 1, ptrFILE);
printf("\n*-* Person knowledge which you search *-*\n");
Sleep(750);
printf("Name: %s\n", s->name);
printf("Surname: %s\n", s->surname);
printf("Number: %s\n", s->number);
free(s);
fclose(ptrFILE);
}
recordLength = sizeof(p);
is wrong, this is the size of the pointer which is normally 4 on a 32 bit system and 8 on a 64 bit syste.
you need
recordLength = sizeof(*p);
or
sizeof(struct personKnowledge);
which gives you the size of the structure pointed by p.
I am writing a phone book program. I completed first function.
However, in second function (("" display() function "")) there is something wrong which is I couldn't find.
In display() function, I'm taking another name which is searched by user and comparing it with names into file to show that person's knowledge (Just one person) on the screen. But it doesn't work. How can I solve this problem?
#include <stdio.h>
#include <stdlib.h> // "stdlib" library contains of exit() and malloc function
#include <Windows.h> // "Windows" library contains of Sleep() function which waits the system as you want
#include <string.h> // "string" library contains of strcmp() function which compares string statements
struct personKnowledge
{
char number[16];
char name[16];
char surname[16];
char sName[16];
};
void newRecord(FILE *);
void display(FILE *);
void deletE();
void add();
void update();
FILE *ptrFILE;
int main()
{
int choice;
if ((ptrFILE = fopen("Phone Book.txt", "w+")) == NULL)
{
printf("The file couldn't open\n");
}
do
{
printf("\n\t\t --- Phone Book Program ---");
printf("\n\n\t\t 1) New record"); // The options are being presented to user
printf("\n\n\t\t 2) Display person knowledge");
printf("\n\n\t\t 3) Delete someone");
printf("\n\n\t\t 4) Add new person");
printf("\n\n\t\t 5) Update person knowledge");
printf("\n\n\t\t 6) Exit");
printf("\n\n\nEnter your choice: ");
scanf("%d", &choice);
switch (choice)
{
case 1:
{
newRecord(ptrFILE);
break;
}
case 2:
{
display(ptrFILE);
break;
}
case 3:
{
break;
}
case 4:
{
break;
}
case 5:
{
break;
}
case 6:
{
printf("\nWorking has been completed.\n");
exit(EXIT_SUCCESS);
break;
}
default:
{
printf("\nWrong entry! The program has been terminated.\n");
}
}
} while (choice >= 1 && choice <= 6);
fclose(ptrFILE);
return 0;
}
void newRecord(FILE *ptrFILE)
{
static int counter = 0;
system("cls"); // Screen is being cleaned
struct personKnowledge *p; // p means person
p = (struct personKnowledge *)malloc(sizeof(struct personKnowledge)); // Memory is being allocated
fflush(stdin);
printf("\n\nDetermine person name: "); // User is entering the person's knowledge and they are being saved in file
gets(p->name);
printf("Determine %s's surname: ", p->name);
gets(p->surname);
printf("Determine %s's number: ", p->name);
gets(p->number);
if (counter == 0)
{
fprintf(ptrFILE, "Name\t\t\t\tSurname\t\t\t\tNumber\n");
fprintf(ptrFILE, "--------\t\t ----------------\t\t------------------------\n");
}
fprintf(ptrFILE, "\n%-33s%-33s%-38s\n", p->name, p->surname, p->number);
printf("Please wait, information is saving to file..\n");
Sleep(750);
printf("*-* Saving operation has been completed. *-*\n");
counter++;
free(p);
}
void display(FILE *ptrFILE)
{
if ((ptrFILE = fopen("Phone Book.txt", "r")) == NULL)
{
printf("The file couldn't open\n");
}
else
{
system("cls"); // Screen is being cleaned
struct personKnowledge *s; // s means searching
s = (struct personKnowledge *)malloc(sizeof(struct personKnowledge));
fseek(ptrFILE, 0L, SEEK_SET);
fflush(stdin);
printf("\n\nExpress name which you search: ");
gets(s->sName);
while (!feof(ptrFILE))
{
fscanf(ptrFILE, "\n%-33s%-33s%-38s\n", &s->name, &s->surname, &s->number);
if (strcmp(s->name, s->sName) == 0)
{
printf("*-* Person knowledge who is you search *-*\n");
Sleep(750);
printf("\n\nName: %s\nSurname: %s\nNumber: %s\n", s->name, s->surname, s->number);
}
}
free(s);
}
}
The MSVC documentation of fopen says about mode: "w" Opens an empty file for both reading and writing. If the file exists, its contents are destroyed.
Since the first file open in main is
if ((ptrFILE = fopen("Phone Book.txt", "w+")) == NULL)
you destroy anything you already have.
To read the content, use mode "r" to open the file, read the content, then close it.
To add new content, either re-open with mode "w" and write the whole content, or open in append mode "a" and just write the new records(s).
Or you can open in mode "r+" for reading and writing, but before writing you need to fseek the end of the file.
In int main() you opened file with "w+" mode so everything is discarded in file when it is called.
Also in function void display(FILE *ptrFILE) you have not closed the text file.And you have used feof() inside while loop which may create problem .
Please see following link why you should not use while(!feof())-Why is “while ( !feof (file) )” always wrong?
void display(FILE *ptrFILE)
{
fclose(ptrFILE);//!! flush out
if ((ptrFILE = fopen("Phone Book.txt", "r")) == NULL)
{
printf("The file couldn't open\n");
}
else
{
char buff[128];//!!for fgets
system("cls"); // Screen is being cleaned
struct personKnowledge *s; // s means searching
s = (struct personKnowledge *)malloc(sizeof(struct personKnowledge));
//fseek(ptrFILE, 0L, SEEK_SET);//!!no need
fflush(stdin);
printf("\n\nExpress name which you search: ");
gets(s->sName);
while (fgets(buff, sizeof buff, ptrFILE))//!!
{
sscanf(buff, "%15s%15s%15s\n", s->name, s->surname, s->number);//!!
I'm trying to create phone book which has five function in c. I have formed just first function which takes and saves in file people's knowledge. However, I cannot succeed the second function which search just a person's (Not all people) knowledge from file.
To run this function (""display() function"") I want to a name from user to search and to display that name's knowledge on the screen. I wrote something but it didn't work. The problem is display() function. How can I read just one line and print it on the screen? Thanks in advance.
#include <stdio.h>
#include <stdlib.h> // "stdlib" library contains of exit() and malloc function
#include <Windows.h> // "Windows" library contains of Sleep() function
#include <string.h> // "string" library contains of strcmp() function
struct personKnowledge
{
char number[16];
char name[16];
char surname[16];
};
void newRecord();
void display();
void deletE();
void add();
void update();
FILE *ptrFILE;
int main()
{
int choice;
printf("\n\t\t *-* Phone Book Program *-*");
do
{
printf("\n\n\t\t 1) New record"); // The options are being presented to user
printf("\n\n\t\t 2) Display person knowledge");
printf("\n\n\t\t 3) Delete someone");
printf("\n\n\t\t 4) Add new person");
printf("\n\n\t\t 5) Update person knowledge");
printf("\n\n\t\t 6) Exit");
printf("\n\n\nEnter your choice: ");
scanf("%d", &choice);
switch (choice)
{
case 1:
{
newRecord();
break;
}
case 2:
{
display();
break;
}
case 3:
{
break;
}
case 4:
{
break;
}
case 5:
{
break;
}
case 6:
{
printf("\nWorking has been completed.\n");
exit(0);
break;
}
default:
{
printf("\nWrong entry! The program has been terminated.\n");
}
}
} while (choice >=1 && choice <=6 );
return 0;
}
void newRecord()
{
system("cls"); // Screen is being cleaned
if ((ptrFILE = fopen("Phone Book.txt", "w")) == NULL)
{
printf("The file couldn't open\n");
}
else
{
struct personKnowledge *p; // p means person
p = (struct personKnowledge *)malloc(sizeof(struct personKnowledge)); // Memory is being allocated
fflush(stdin);
printf("\n\nDetermine person name: "); // User is entering the person's knowledge and they are being saved in file
gets(p->name);
printf("Determine %s's surname: ", p->name);
gets(p->surname);
printf("Determine %s's number: ", p->name);
gets(p->number);
fprintf(ptrFILE, "Name\t\t\t\tSurname\t\t\t\t\tNumber\n");
fprintf(ptrFILE, "--------\t\t ----------------\t\t\t---------------------\n");
fprintf(ptrFILE, "\n%s%33s%38s\n", p->name, p->surname, p->number);
fclose(ptrFILE);
free(p);
printf("Please wait, information is saving to file..\n");
Sleep(1000);
printf("*-* Saving operation has been completed. *-*");
}
fclose(ptrFILE);
}
void display()
{
struct personKnowledge *s; // s means searching
char name[16];
if ((ptrFILE = fopen("Phone Book.txt", "r")) == NULL)
{
printf("The file couldn't open\n");
}
else
{
fseek(ptrFILE, 0L, SEEK_SET);
printf("Express name which you search: ");
gets(s->name);
while (!feof == NULL)
{
fscanf(ptrFILE,"%s", &name);
if (strcmp(s->name, name) == 0)
{
printf("qawsdsdf");
}
}
}
fclose(ptrFILE);
}
In answer to one of your questions, I recommend rewriting this loop in display()
while (!feof == NULL) // wrong way to use feof
{
fscanf(ptrFILE,"%s", &name); // might overflow the string space
if (s->name == name) // wrong way to compare strings
{
printf("qawsdsdf"); // missing newline?
}
}
with this
while (fgets(name, sizeof(name), ptrFILE) != NULL) // safer way to read to a small buffer
{
name [ strcspn(name, "\r\n") ] = 0; // remove trailing newline etc
if (strcmp(s->name, name) == 0) // compare the strings
{
printf("qawsdsdf\n"); // added newline
}
}
EDIT in any case your posted code does not even compile properly:
while (!feof == NULL)
is rubbish, it should have been
while (!feof(ptrFILE))
although as I said is not the way to use feof anyway. This would not have happened if you had compiler warnings enabled and dealt with them.
I think these minor changes will solve your problem
Allocate memory for storing personKnowledge s = (struct personKnowledge *)malloc(sizeof(struct personKnowledge));
Make file pointer reach the starting location of data. A simple trick has been used to achieve this fscanf(ptrFILE, "Name\t\t\t\tSurname\t\t\t\t\tNumber\n");
fscanf(ptrFILE, "--------\t\t ----------------\t\t\t---------------------\n");
Make change in while loop.while (!feof(ptrFILE))
Scanning one row of data.fscanf(ptrFILE, "\n%s%33s%38s\n", s->name, s->surname, s->number)
Make change in string comparison.if (strcmp(name,s->name) == 0)
The modified display function
void display(){
struct personKnowledge *s;
s = (struct personKnowledge *)malloc(sizeof(struct personKnowledge)); // Memory is being allocated for s
fflush(stdin);
char name[16];
if ((ptrFILE = fopen("Phone Book.txt", "r")) == NULL)
{
printf("The file couldn't open\n");
}
else
{
fseek(ptrFILE, 0L, SEEK_SET);
printf("Express name which you search: ");
scanf("%s",name); //the name you want to retrieve
fscanf(ptrFILE, "Name\t\t\t\tSurname\t\t\t\t\tNumber\n");
fscanf(ptrFILE, "--------\t\t ----------------\t\t\t---------------------\n"); //when we read the file for first time we need to start from the first location of person data, this is a trick to make ptrFILE reach there
fflush(stdin);
while (!feof(ptrFILE))
{
fscanf(ptrFILE, "\n%s%33s%38s\n", s->name, s->surname, s->number);//same format as fprintf used in newRecord
if (strcmp(name,s->name) == 0) //comparison
{
printf("qawsdsdf");
}
}}fclose(ptrFILE);}
My solution was to change how the file is formatted
fprintf(ptrFILE, "\n%s%33s%38s", p->name, p->surname, p->number);
Because if you're using a program to retrieve information, there's no need to fill it with a bunch of junk headers every time you write to it.
I then edited the display function to be able to retrieve said information.
void display()
{
struct personKnowledge s; // s means searching
char name[16];
char sname[16];
char number[16];
char surname[16];
if ((ptrFILE = fopen("Phone Book.txt", "r")) == NULL)
{
printf("The file couldn't open\n");
}
else
{
printf("Express name which you search: ");
scanf("%s", &sname);
do
{
fscanf(ptrFILE,"%s%33s%38s", &name, &surname, &number);
if (strcmp(sname, name) == 0)
{
printf("%s %s %s", name, surname, number);
}
}
while (strcmp(sname, name) != 0);
}
}
P.S. I'm still new to c myself and I don't think I could give you a good explanation as to why my code works and yours doesn't. But I can say that those headers you were writing to the file every time was a major part of the problem when I was troubleshooting your code.
I am slowly learning C, but not very well. I have been reading over the countless topics and questions on reading and writing, but I have yet to be able to find anything that makes this all click for me.
I was given the following code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 100
struct YouTubeVideo {
char video_name[1024]; // YouTube video name
int ranking; // Number of viewer hits
char url[1024]; // YouTube URL
};
struct YouTubeVideo Collection[MAX];
int tail = 0;
//-- Forward Declaration --//
void printall();
void insertion();
void branching(char option);
void menu();
int main()
{
char ch;
// TODO: Add code to load save data from file
printf("\n\nWelcome to CSE240: YouTube Classic Hits\n");
do {
menu();
fflush(stdin); // Flush the standard input buffer
ch = tolower(getchar()); // read a char, convert to lower case
branching(ch);
} while (ch != 'q');
return 0;
}
void menu()
{
printf("\nMenu Options\n");
printf("------------------------------------------------------\n");
printf("i: Insert a new favorite\n");
printf("p: Review your list\n");
printf("q: Save and quit\n");
printf("\n\nPlease enter a choice (i, p, or q) ---> ");
}
void branching(char option)
{
switch(option)
{
case 'i':
insertion();
break;
case 'p':
printall();
break;
case 'q':
// TODO: Add code to save data into a file
break;
default:
printf("\nError: Invalid Input. Please try again...");
break;
}
}
void insertion()
{
if(tail < MAX)
{
printf("\nWhat is the name of the video? (No spaces characters allowed)\n");
scanf("%s", Collection[tail].video_name);
printf("\nHow many viewer hits does this video have?\n");
scanf("%d", &Collection[tail].ranking);
printf("\nPlease enter the URL: ");
scanf("%s", &Collection[tail].url);
tail++;
}
else
{
printf("\nERROR: Your collection is full. Cannot add new entries.\n");
}
}
void printall()
{
int i;
printf("\nCollections: \n");
for(i = 0; i < tail; i++)
{
printf("\nVideo Name: %s", Collection[i].video_name);
printf("\nRanking (Hits): %d", Collection[i].ranking);
printf("\nURL: %s", Collection[i].url);
printf("\n");
}
}
I am suppose to write the code that will store the collection into a file and the likewise right the code that will load the file and read from it.
Thanks to a fairly helpful TA I was able to formulate the following code for each
void store()
{
FILE * fileName;
fileName = fopen ( "Ranking.dbm" , "wb" );
fwrite ( Collection, sizeof(struct YouTubeVideo), MAX, fileName);
fclose (fileName);
}
and
void read()
{
FILE *fileName;
fileName = fopen("ranking.dbm", "rb");
if (fileName != NULL){
fread ( Collection, sizeof(struct YouTubeVideo), MAX, fileName);
}
else {
printf("ERROR");
}
}
I believe these each to function but the real problem is I don't think I quite understand how and I believe that since I dont even know how they function, I dont know how to use them in the code.
I added both methods to the given code and came up with this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MAX 100
struct YouTubeVideo {
char video_name[1024]; // YouTube video name
int ranking; // Number of viewer hits
char url[1024]; // YouTube URL
};
struct YouTubeVideo Collection[MAX];
int tail = 0;
//-- Forward Declaration --//
void printall();
void insertion();
void branching(char option);
void menu();
void store();
void read();
int main()
{
char ch;
read();
printf("\n\nWelcome to CSE240: YouTube Classic Hits\n");
do {
menu();
fpurge(stdin); // Flush the standard input buffer
ch = tolower(getchar()); // read a char, convert to lower case
branching(ch);
} while (ch != 'q');
return 0;
}
void menu()
{
printf("\nMenu Options\n");
printf("------------------------------------------------------\n");
printf("i: Insert a new favorite\n");
printf("p: Review your list\n");
printf("q: Save and quit\n");
printf("\n\nPlease enter a choice (i, p, or q) ---> ");
}
void branching(char option)
{
switch(option)
{
case 'i':
insertion();
break;
case 'p':
printall();
break;
case 'q':
store();
break;
default:
printf("\nError: Invalid Input. Please try again...");
break;
}
}
void insertion()
{
if(tail < MAX)
{
printf("\nWhat is the name of the video? (No spaces characters allowed)\n");
scanf("%s", Collection[tail].video_name);
printf("\nHow many viewer hits does this video have?\n");
scanf("%d", &Collection[tail].ranking);
printf("\nPlease enter the URL: ");
scanf("%s", &Collection[tail].url);
tail++;
}
else
{
printf("\nERROR: Your collection is full. Cannot add new entries.\n");
}
}
void printall()
{
int i;
printf("\nCollections: \n");
for(i = 0; i < tail; i++)
{
printf("\nVideo Name: %s", Collection[i].video_name);
printf("\nRanking (Hits): %d", Collection[i].ranking);
printf("\nURL: %s", Collection[i].url);
printf("\n");
}
}
void store()
{
FILE * fileName;
fileName = fopen ( "Ranking.dbm" , "wb" );
if (fileName != NULL)
{
fwrite ( Collection, sizeof(struct YouTubeVideo), MAX, fileName);
fclose (fileName);
}
else {
perror("Following error occurred(): ");
}
}
void read()
{
FILE *fileName;
fileName = fopen("Ranking.dbm", "rb");
if (fileName != NULL)
{
fread ( Collection, sizeof(struct YouTubeVideo), MAX, fileName);
fclose(fileName);
}
else {
perror("Following error occurred with fopen(): ");
}
}
Now I am sure anyone who has read this has probably already face palmed themselves cause they see the problem, but I do not. The code does not create the file to write to and likewise it has nothing to read from so I cant even begin to see what is wrong with that.
Now I am not looking for a given answer, but I would really like to know what it is I am doing incorrectly, what concepts I appear to not understand, and how I can go about fixing these. I have done a few hours of research on this already and I realize it is elementary, but I really would like a hand in learning. Its frustrating spending hours on a topic that the professor said should only take a couple of hours to complete at most.
You really should check the return value of fopen() against NULL - if there is a problem opening the file, it will return NULL and set errno. This is probably a permissions mistake, and by checking the return value and printing the error if one is set, you'll get more information on what went wrong.
Minor: Make sure to check the return values for things like fopen, fread, fwrite etc. more often.
Mild: You've got a potential typo in the filename (some operating systems have case-sensitive file names)
Severe: read() doesn't set up a value for tail... :)
I believe you may have a problem with the read function, which does not call fclose on the file handle (by the way, calling it fileName is a little misleading).
Because you leave the file open, it's entirely likely that you won't be able to overwrite it when you eventually call store. You haven't output any error messages if the file cannot be opened in that function, so it's quite easy to slip under the radar... At least until you wonder why your file date doesn't change.
Otherwise the code looks okay. All it does is dump the entire contents of your array out of memory and read it back in again. What you'll probably want to do is also write out the value of tail, since it is keeping track of how many elements you are keeping. So with minimal code changes, do this:
fwrite ( &tail, sizeof(int), 1, fileName);
fwrite ( Collection, sizeof(struct YouTubeVideo), MAX, fileName);
And of course the corresponding calls to fread in your read method.
fread ( &tail, sizeof(int), 1, fileName);
fread ( Collection, sizeof(struct YouTubeVideo), MAX, fileName);
To reiterate: don't forget to close your file!!!!
fclose(fileName);