Reading data issue in file - c

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);//!!

Related

I can't display binary content

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.

Data saving issue in file

I'm trying to write phone book program.I completed the first function(which saves knowledge). Program is running. However, after I enter the person's knowledge from keyboard and close the program it shows me just the last person's knowledge in file. I am using the program w mode, I tried w+ mode, too. But the problem still didn't change. For example as I use the first function I enter three people's knowledge but it shows me just one. How can I solve this ?
#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
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;
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();
break;
}
case 2:
{
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");
break;
}
}
} 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\tNumber\n");
fprintf(ptrFILE, "--------\t\t ----------------\t\t------------------------\n");
fprintf(ptrFILE, "\n%s%33s%38s\n", p->name, p->surname, p->number);
free(p);
printf("Please wait, information is saving to file..\n");
Sleep(750);
printf("*-* Saving operation has been completed. *-*");
}
fclose(ptrFILE);
}
You are using write mode to write output to an already existing file. To preserve it's contents, use append modes like a or a+. For example
FILE * ptrFILE = fopen("Phone Book.txt", "a");
The description of other modes (may not be compatible with all platforms):
r or rb - Open file for reading.
w or wb - Truncate to zero length or create file for writing.
a or ab - Append; open or create file for writing at end-of-file.
r+ or rb+ or r+b - Open file for update (reading and writing).
w+ or wb+ or w+b - Truncate to zero length or create file for update.
a+ or ab+ or a+b - Append; open or create file for update, writing at end-of-file.
You should open it in append mode. Try this: if ((ptrFILE = fopen("Phone Book.txt", "a")) == NULL) Append mode will add contents to the end of your existing file contents.
If you open in write mode ("w" or "w+"), the last text is saved in file, but if you will open in append mode ("a" or "a+"), your file will include all of your writing.
Well in above mentioned programs-
Fisrt Program always enters the last record you enetres as you opened file in "w" mode and you call function void newRecord() again to enter another record thus closing file then again opening it. As already contains data you want next record after it but as file is opened in "w" mode it discards already present data in file and the file is treated as a new empty file.
In second program you mentioned in your answer is just main function thus not causing opening and closing of file again and again. That is why it normally saves your data.
Use "a" or "a+" mode to make your first program work normally.
No need a or a+ mode. I insist :) Here are new codes. The problem has been solved.
#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
struct personKnowledge
{
char number[16];
char name[16];
char surname[16];
};
void newRecord(FILE *);///
void display();
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:
{
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. *-*");
counter++;
free(p);
}

How can I read data from file?

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.

Update record file in file

Please help me. This is my code so far. The delete record function is not working and can someone help the update record function with following conditions:
- Ask user to input player name.
- Ask user to input player score.
- Ask user to input player level.
- If the player name does not exist on the list, then show message “name of [player name] not found!”
Thanks a lot.
#include <stdio.h>
#include <string.h>
struct Player {
char name[50];
int score;
int level;
};
struct Player data[50];
FILE *ptr;
FILE *ptr2;
int fileSize()
{
int lSize;
int end;
ptr = fopen("text.txt", "r");
lSize = ftell (ptr);
fseek (ptr, 0, SEEK_END);
end = ftell (ptr);
fseek (ptr, lSize, SEEK_SET);
return end;
}
int getNoOfRecords()
{
return (fileSize()/(sizeof(struct Player)));
}
void deletePlayerRecord()
{
char name[50];
int counter=0, i=0;
ptr2 = fopen("text2.txt","a");
int records = getNoOfRecords();
ptr = fopen("text.txt","a+");
do {
printf("Input player name[1..10]: ");
scanf("%[^\n]s", name);
fflush(stdin);
} while (strlen(name)<1 || strlen(name)>10);
while(counter!=records)
{
fread(&data,sizeof(struct Player),1,ptr);
if(strcmp(data[i].name,name)==0)
{
}
else
{
fwrite(&data,sizeof(struct Player),1,ptr2);
}
counter++;
}
fclose(ptr);
fclose(ptr2);
remove("text.txt");
rename("text2.txt","text.txt");
printf("\n%s successfully deleted.\n\n", name);
printf("Press Enter to continue....\n\n");
getchar();
}
void updatePlayerRecord()
{
char name[50];
int counter=0, i=0;
int records = getNoOfRecords();
ptr = fopen("text.txt","a+");
do {
printf("Input player name[1..10]: ");
scanf("%[^\n]s", name);
fflush(stdin);
} while (strlen(name)<1 || strlen(name)>10);
if(counter!=records)
{
fread(&data,sizeof(struct Player),1,ptr);
if(strcmp(data[i].name,name)==0)
{
}
counter++;
}
printf("\nScore and Level successfully updated.\n\n");
printf("Press Enter to continue....\n\n");
getchar();
}
void addPlayerRecord(){
int i=0;
do {
printf("Input player name[1..10]: ");
scanf("%[^\n]s", data[i].name);
fflush(stdin);
} while (strlen(data[i].name)<1 || strlen(data[i].name)>10);
fflush(stdin);
getchar();
data[i].score=0;
data[i].level=0;
ptr = fopen("text.txt", "a");
printf("\n");
fprintf(ptr, "\r\n%s#%d#%d", data[i].name, data[i].score, data[i].level);
fclose(ptr);
printf("\nData successfully added.\n\n");
printf("Press Enter to continue....\n\n");
getchar();
}
void viewPlayerRecord(){
int i=0;
ptr = fopen("text.txt", "r");
printf("Player Name\t\t|Average Score\t|Number of Playing\n");
printf("=======================================================\n");
while(fscanf(ptr, "%[^#]#%d#%d\n", data[i].name, &data[i].score, &data[i].level)!=EOF)
{
printf("%s\t\t\t|%d\t\t\t\t|%d\n", data[i].name, data[i].score, data[i].level);
i++;
}
fclose(ptr);
}
int main() {
int choice;
do{
printf("Score Record Dota Player\n");
printf("========================\n");
printf("1. View Record\n");
printf("2. Update Player Record\n");
printf("3. Add New Player\n");
printf("4. Delete Player\n");
printf("5. Save and Exit\n\n");
do {
printf("Input your choice[1..5]: ");
scanf("%d", &choice);
fflush(stdin);
getchar();
} while (choice < 1 || choice > 5);
switch (choice) {
case 1:
viewPlayerRecord();
break;
case 2:
updatePlayerRecord();
break;
case 3:
addPlayerRecord();
break;
case 4:
deletePlayerRecord();
break;
}
} while(choice!=5);
return 0;
}
There are many issues with your code:
Every operation works on the database file. That may be a good design, but a more usual approach would be to load the database into memory on startup, i.e. to populate your data and then work on this. When exiting the program, you commit all changes to the database file. (Your option 5 is named "Save and exit", but is effectively a null operation. That name hints at the outlined approach.)
You should make up your mind whether your database is a binary file or a text file. You use fprintf and fscanf, which are used for text files, when you add and display records, but you use fwrite and fread, which are used for binary files, when you update and delete records. In my opinion, binary access is a bit easier, because you just have to store and retrieve chunks of a fixed size, namely sizeof(struct Player). Text files are more user-friendly, because they can be displayed and modified in a text editor, but they have to be parsed and require more advanced error handling.
Your fileSize() will only work with binary files, but at the moment you write only text files. It is usually better to use the return values of the file functions to determine whether reading or writig was successful.
When the database file doesn't exist, your view function will crash. Check for file existence and for the correct format.
At the moment, you use data only as scratch space. You osften access data[i], but i is zero throughout your code.
A corrected delete function that works is:
void deletePlayerRecord()
{
struct Player p;
char name[50];
int del = 0;
ptr2 = fopen("text2.txt", "w");
ptr = fopen("text.txt", "r");
do {
printf("Input player name[1..10]: ");
scanf("%[^\n]s", name);
fflush(stdin);
} while (strlen(name)<1 || strlen(name)>10);
while (fscanf(ptr, "%[^#]#%d#%d\n", p.name, &p.score, &p.level) == 3) {
if(strcmp(p.name, name) == 0) {
printf("\n%s successfully deleted.\n\n", name);
del++;
} else {
fprintf(ptr2, "%s#%d#%d\n", p.name, p.score, p.level);
}
}
fclose(ptr);
fclose(ptr2);
remove("text.txt");
rename("text2.txt", "text.txt");
printf("%d character(s) deleted\n\n", del);
}
This code still has many drawbacks:
The success of fopen is not checked.
The fscanf and fprintf formats have to be copied verbatim from the view and add record options. That's bad style. You should probably write readPlayer and writePlayer functions.
The same goes for the input code. Write front-end functions that do the error checking so that you don't have to repeat the whole code over and over again. This makes the code hard to read and also prone to errors.

Loading a text file into a struct using C

I try to load the contents of a text file into a structure.
My idea looks like this:
I have two files, struct.h , main.c and a list.txt file .
in file struct.h :
struct analg {
char word[6];
char signature[6];
};
struct analg h[106];
FILE *fp;
In file main.c :
#include<stdio.h>
#include "struct.h"
void load() {
fp = fopen("list.txt", "r");
if(fp == NULL) {
printf("fail");
return 1;
}
else {
printf("file loaded!\n");
}
fclose(fp);
return;
}
void print() {
int i;
for(i=0; i<1000; i++) {
while(fgets(h[i].word, 6, fp)) {
printf("%s", h[i].word);
}
}
return;
}
int main () {
int choice;
do {
printf("choose L or P: ");
scanf("%s", &choice);
switch(choice) {
case 'l':
load();
printf("\n[l]oad - [p]rint\n");
break;
case 'p':
print();
printf("\n[l]oad - [p]rint\n");
break;
default:
break;
}
} while(choice!='q');
return;
}
In file list.txt :
throw
timer
tones
tower
trace
trade
tread
So I try to load the text file by pressing the "L" to the structure, and then when I press the 'p' will be displayed, but it is not!
In your code, I see there are 2 potential issues. The choice has to be a character to be switched based on l or p. You may have to add cases to handle the upper case also.
Another issue is that in load function, you are closing the file pointer. Hence, when you enter the print function fgets may not work as the fp is already closed.
To load your file into structure, the load has to be modified as
void load() {
fp = fopen("list.txt", "r");
if(fp == NULL) {
printf("fail");
return; // There was an error in original code as this was returning 1
}
do{
fgets(h[count++].word, 6, fp); // Count is a global variable - no. of elements read
}while(!feof(fp));
printf("file loaded!\n");
fclose(fp);
return;
}
The corresponding print function would become
void print(){
int i;
printf("Inside print\n");
for(i=0; i < count; i++) {
printf("%s", h[i].word);
}
return;
}
the main function would be,
int main (){
char choice;
do{
printf("choose L or P: ");
scanf("%c", &choice); //Only character is read and hence, %s is not required
switch(choice){
case 'l':
load();
printf("\n[l]oad - [p]rint\n");
break;
case 'p':
print();
printf("\n[l]oad - [p]rint\n");
break;
default:
case 'q':
break;
}
} while(choice !='q');
return 0;
}
One last point. In the scanf statement if scanf("%s", &choice); is employed, then a runtime check error is generated when main exits, with a message that stack is corrupted around the variable choice.
I'll comment up what your code is doing:
void load() {
fp = fopen("list.txt", "r"); // opens the file for reading
if(fp == NULL) {
printf("fail"); // if the file couldn't be opened, return an error
return 1; // (aside: a void function can't return an int)
}
else {
printf("file loaded!\n"); // tell the user that the file was opened
}
fclose(fp); // close the file, having read nothing from it
return;
}
At no point do you read anything from the file. What you have in memory will therefore have no relation to whatever you have on disk.
C has no built-in means for serialising and deserialising structs so what you need to do is define a formal grammar for your file on disk and write code that can parse that grammar into your structs.

Resources