C file-handling program exited without running whole program - c

I'm using Dev-C++ (we're required to use either Turbo-C++ or Dev-C++). I'm supposed to delete one student (DATA 2) from a student record. Here is the data that we were given:
DATA 1:
2021-10-693
Clarisse
BSCS 1
1.00, 1.00, 1.00, 1.25, 1.25
DATA 2:
2021-10-705
Kricel
BSCS 1
1.00, 1.25, 1.00, 1.00, 1.25
DATA 3:
2021-01-256
Rafael
BSCS 1
1.00, 1.00, 1.00, 1.00, 1.25
We were given a student.dat file created using Turbo-C++ but I can't open it in Dev-C++ so I created my own student.dat by copy-pasting my teacher's code from Turbo-C++ to Dev-C++. The only thing I changed in this code is removing clrscr(); and replacing it with system("cls");:
/* This program will allow saving of records in the disk */
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
typedef struct{
char No[12];
char Name[25];
char Crsyr[10];
float Grade[5];
}Student_Record;
int main()
{
FILE *STUDFILE; /* defining FILE variable */
Student_Record STUDENT[50],TEMPREC;
int i,j,ns;
float TGrade;
char Temp,FName[15];
do{
system("cls");
printf("How many student records (max. of 50) ? ");
scanf("%d",&ns);
if ((ns<1)||(ns>50))
{
printf("\nInvalid Input!!!");
printf("\n\nPress Any Key To Continue...");
getch();
}
}while((ns<1)||(ns>50));
scanf("%c",&Temp);
for(i=0;i<ns;i++)
{
system("cls");
printf("<## STUDENT's INFORMATION ##>\n\n");
printf("Student No. : ");
gets(STUDENT[i].No);
printf("Student Name : ");
gets(STUDENT[i].Name);
printf("Course and Year: ");
gets(STUDENT[i].Crsyr);
printf("List of grades:\n");
for(j=0;j<5;j++)
{
printf("\tGrade No. %d => ",j+1);
scanf("%f",&TGrade);
STUDENT[i].Grade[j]=TGrade;
}
printf("\nPress any key to continue...");
getch();
scanf("%c",&Temp);
}
printf("\n\nEnter Filename where records will be saved => ");
gets(FName);
printf("\n\nSaving of Records being process...");
STUDFILE=fopen(FName,"w"); /* fopen-file opening; "w" - generate new file or overwrite existing file */
for(i=0;i<ns;i++)
{
TEMPREC=STUDENT[i];
fwrite(&TEMPREC,sizeof(TEMPREC),1,STUDFILE); /* fwrite - save records in the disk */
}
fclose(STUDFILE); /* fclose - file closing */
printf("Saving of Records Completed!!!\n\n");
printf("Press Any Key To Exit...");
getch();
return (0);
}
Here is the student.dat file:
2021-10-693 Clarisse þÿÿÿÿÿÿÿþÿÿÿÿBSCS 1 €? €? €? ? ?2021-10-705 Kricel Po `Of°û BSCS 1 €? ? €? €? ?2021-10-256 Rafael °û ˜im°û ˜im°ûBSCS 1 €? €? €? €? ?
My plan is to:
Open student.dat for reading
Open temp.dat for writing
Read content of student.dat
Compare studNo to data in student.dat
If studNo is not equal to student no. of Kricel, write it in temp.dat
If studNo is equal to student no. of Kricel, don't write in temp.dat
Close both files
Open temp.dat for reading
Open student.dat for writing
Overwrite student.dat with content from temp.dat
Close both files
Open student.dat for reading
Display student.dat
And here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
typedef struct
{
char no[12];
char name[25];
char crsYr[10];
float grade[5];
} studentRecord;
int main()
{
FILE *studFile, *tempFile;
studentRecord student[50], tempStudRec, tempFileRec;
int i = 0, j = 0, k = 0, found = 0;
float tGrade = 0.00;
char temp, fName[15], studNo[12], resp1, resp2;
system("cls");
printf("Enter file name of the record you want to alter: ");
gets(fName);
printf("Enter student no. of student you want to delete: ");
gets(studNo);
printf("Are you sure you want to remove this student (Y/N)? ");
scanf("%c", &resp1);
if (toupper(resp1) == 'Y')
{
printf("\nRetrieving records from %s...", fName);
//Sleep(2000);
printf("\nDeleting student %s from %s...", studNo, fName);
//Sleep(2000);
// Opens both files
studFile = fopen(fName, "r");
if (studFile == NULL)
{
printf("File opening is unsuccessful.");
return 1;
}
tempFile = fopen("temp.dat", "w");
// Reads student.dat
k = 0;
fread(&tempStudRec, sizeof(studentRecord), 1, studFile);
while(!feof(studFile))
{
student[k] = tempStudRec;
fread(&tempStudRec, sizeof(studentRecord), 1, studFile);
k++;
}
// Compare studNo to data in student.dat
for (i = 0; i < k; i++)
{
// If content is not equal to student no. of Kricel
if (strcmp(studNo, student->no) != 0)
{
// Write in temp.dat
tempFileRec = student[i];
fwrite(&tempFileRec, sizeof(studentRecord), 1, tempFile);
}
}
// Closes both files
fclose(studFile);
fclose(tempFile);
// Opens both files again
tempFile = fopen("temp.dat", "r");
if (tempFile == NULL)
{
printf("File opening is unsuccessful.");
return 1;
}
studFile = fopen(fName, "w");
// Reads temp.dat
k = 0;
fread(&tempFileRec, sizeof(studentRecord), 1, tempFile);
while(!feof(studFile))
{
student[k] = tempFileRec;
fread(&tempFileRec, sizeof(studentRecord), 1, tempFile);
k++;
}
// Copies temp.dat content to student.dat
for (i = 0; i < k; i++)
{
// Write in student.dat
tempStudRec = student[i];
fwrite(&tempStudRec, sizeof(studentRecord), 1, studFile);
}
// Closes both files
fclose(studFile);
fclose(tempFile);
// Opens student.dat for reading
studFile = fopen(fName, "r");
// Displaying records
printf("Student deleted!");
printf("\nDo you want to view record (Y/N)? ");
scanf("%c", &resp2);
if (toupper(resp2) == 'Y')
{
for(i = 0; i < k; i++)
{
system("cls");
printf("<## STUDENT INFORMATION ##>\n\n");
printf("Student No. : %s\n", student[i].no);
printf("Student Name : %s\n", student[i].name);
printf("Course and Year: %s\n", student[i].crsYr);
printf("List of Grades:\n");
for(j = 0; j < 5; j++)
{
printf("\tGrade No. %d => %0.2f\n", j + 1, student[i].grade[j]);
}
printf("\nPress any key to continue...");
}
}
// Closes student.dat
fclose(studFile);
}
return 0;
}
This is what the output looks like:
Enter file name of the record you want to alter: student.dat
Enter student no. of student you want to delete: 2021-10-705
Are you sure you want to remove this student (Y/N)? Y
Retrieving records from student.dat...
Deleting student 2021-10-705 from student.dat...
--------------------------------
Process exited after 16.78 seconds with return value 3221225477
Press any key to continue . . .
I checked student.dat after running the code and it's empty. Meanwhile, temp.dat contains all the contents of student.dat I showed above, including the student I'm supposed to delete. Can anyone give me an idea why is student.dat empty after running this program? And why wasn't student 2021-10-705 deleted? I'm having a hard time understanding online tutorials since we kinda just skimmed over pointers and we haven't discussed malloc(), etc. yet.

Rather than analyzing your two programs for you, I'll try to suggest how you can figure out what's going on.
Check library function call return values
Library function calls don't always succeed! When you try to open a new file - the directory might not be writeable; when you write data to disk - the disk may be full; etc. I'm not saying this is what happens in your case, but you should rarely, or perhaps never, assume a library function succeeds, if its return value can indicate an error.
Always check that return value; and if it doesn't indicate success, print a message describing the failure. See, for example, answers to this question:
Error handling in C code
on how that looks.
Use a debugger
It is often not sufficient to just scrutinize the code, or deduce from the output what actually happens when the program runs. You can, and probably should, actively debug a misbehaving program by tracking its execution with a debugger program.
Here are two Stackoverflow questions about debugging on Linux and on Windows:
How to debug a C program
How do you debug a C program on Windows?
(other platforms also have debugging tools available.)
Consider flushing the standard output stream
When your program does not seem to run to conclusion, you could insert fflush() calls at relevant 'suspicious' points in your code to ensure that whatever you printed up to that point does actually become visible on the output, rather than waiting in the output stream's buffers.
Note that, other than for debugging purposes, we generally want to avoid flushing.

Related

Why data read from the random access file and print twice of last line of the table on screen ? (Got picture) [duplicate]

This question already has answers here:
Why is “while( !feof(file) )” always wrong?
(5 answers)
Closed last year.
can I know why the last line of the table below will print twice? Everything is executed well and just has the problem stated above.
The type of file used is a random access file and data written into a binary file named toyota.txt.
Anyone can teach me what is the problem there? Thank you so much!
The code is shown below:
/*program 1 write the data into file toyota.txt*/
#include<stdio.h>
struct vehicledata{
char vnum[100];
int cnum;
float f50;
float f100;
float f200;
float f400;
float f800;
};
int main()
{
FILE *fptr;
struct vehicledata toyota;
if((fptr = fopen("toyota.txt","wb")) == NULL)
{
printf("Error! File fail opened!");
}
else
{
printf("This program can create a text file named toyota.txt \n");
printf("and save the value of car noise level(dB) with\ndifferent frequency and vehicle numbers into file\n\n");
printf("======================================================================\n");
printf("Enter car number(1 to 10, enter 0 to end input)\n");
printf("? ");
scanf("%d", &toyota.cnum);
while (toyota.cnum != 0)
{
printf("\nEnter Vehicle number\n");
printf("? ");
scanf("%s", toyota.vnum);
printf("Enter car noise level(dB) at 50Hz, 100Hz, 200Hz, 400Hz and 800Hz\n");
printf("? ");
scanf("%f %f %f %f %f", &toyota.f50, &toyota.f100, &toyota.f200, &toyota.f400, &toyota.f800);
fseek(fptr, (toyota.cnum - 1) * sizeof(struct vehicledata), SEEK_SET);
fwrite(&toyota, sizeof(struct vehicledata), 1, fptr);
printf("\n======================================================================\n");
printf("\nEnter car number (1 to 100, 0 to end input) \n");
printf("? ");
scanf("%d", &toyota.cnum);
}
}
fclose(fptr);
return 0;
}
/*program 2 reads the data from the file toyota.txt and find
the car that emanates the minimum noise at 200Hz*/
#include <stdio.h>
#include <stdlib.h>
struct vehicledata{
char vnum[100];
int cnum;
float f50;
float f100;
float f200;
float f400;
float f800;
};
char name[10];
float min;
int i, m;
int main()
{
FILE *fptr;
struct vehicledata toyota;
if ((fptr = fopen("toyota.txt","rb")) == NULL)//open and read data in the file
{
printf("Error! File fail opened!");
}
else
{
printf("This program can read and display the data from the toyota.txt\n and find car that have minimum noise in 200Hz\n\n");
printf("\nThe information in the toyota.txt are shown at below:\n");
printf("\n\t\t\t\tCar Noise Level(dB)\t\t\t");
printf("\n=======================================================================\n");
printf("%s\t\t%s\t%s\t%s\t%s\t%s\t\n","Vehicle Number","50Hz","100Hz","200Hz","400Hz","800Hz");
printf("=======================================================================\n");
char name[10];
float min=100;
while(!feof(fptr))
{
fread(&toyota, sizeof(struct vehicledata), 1, fptr);
if(toyota.f200 < min)
{
min=toyota.f200;
for(int i=0 ; i<10 ; i++)
{
name[i]=toyota.vnum[i];
}
}
if(toyota.cnum != 0)
{
printf("%s\t\t\t%.2f\t%.2f\t%.2f\t%.2f\t%.2f\n", toyota.vnum, toyota.f50, toyota.f100, toyota.f200, toyota.f400, toyota.f800);
}
}
printf("=======================================================================\n");
printf("\n\n+++++++++++++++++++++++++++++++++Result+++++++++++++++++++++++++++++++++\n");
printf("\nVehicle number of car with minimum noise in 200Hz is %s at %.2f dB\n", name, min);
}
fclose(fptr);
return 0;
}
The problem is in program 2. In the section below you assume that your fread will be OK since you are not att the EOF. This is not the case.
while(!feof(fptr))
{
fread(&toyota, sizeof(struct vehicledata), 1, fptr);
What happens is that you check for EOF in your loop and being at the very end of the file the last fread is indeed read one more time but fails. Since you don't check for it and fread did not have toyota overwritten (since the read failed) you have a duplicate that you print out. After that you now check for EOF and leave the loop.
A better loop would look like this:
while (fread(&toyota, sizeof(struct vehicledata), 1, fptr)) {
Since the documentation for fread states, "If an error occurs, or the end of the file is reached, the return value is a short item count (or zero).", in your case we are not really checking for errors and we are at EOF.
But if you want to figure out that the loop ended due to EOF or an error then "callers must use feof(3) and ferror(3) to determine which occurred.".

how to check variable validity and how to send array of structure to function?

I'm working in library system, I've a lot of things going on:(. In addBook function I'm trying to add book information into Array of structure. First I don't know how to set a statement to check all the validity of title, author, isbn and others. I tried to write a statement but it wont work so I removed it! and didn't call the functions since I don't know how to make them work! secondly I want to send the book information to a file so I can store them inside the file and sort alphabetically. whenever I try to send the array and check the txt file it print the address please help :( I'm trying to keep it simple as possible as I can
#include <stdio.h>
#include <stdlib.h>
#define MAX_ISBN 11
#define MIN_ISBN 9
#define MAX_YEAR 2021
#define MIN_YEAR 1500
#define MAX_DAY 31
#define MIN_DAY 1
#define MAX_MONTH 12
#define MIN_MONTH 1
#define MIN_ISBN 9
#define MAX_Title 80
#define MAX_Author 80
struct Book{
int ISBN[MAX_ISBN], Edition[500], Year[MAX_YEAR],DD[MAX_DAY], MM[MAX_MONTH];
char Title[MAX_Title];
char Author[MAX_Author];
};
/*Check_Title function will check user input if it's a valid title or not! */
int Check_Title(char *Title){
int valid_Title = 1;
int len = 0;
int i= 0;
len = strlen(Title);
for(i =0; i <len ; i++)
{
if( Title[i] == "##$%^&*()}{[ ]")
return 0;;
}
return 1;
}
/*Check_Author function will check user input if it's a valid Author name or not! */
int Check_Author(char *Author){
int valid_Name = 1;
int len = 0;
int i= 0;
len = strlen(Author);
for(i =0; i <len ; i++)
{
if( !(isalpha(Author[i])) && (Author[i] != ' '))
{
valid_Name = 0;
break;
}
}
return valid_Name;
}
int Check_Date(int *DD, int *MM,int *YYYY){
if(DD[MAX_DAY] > MAX_DAY || DD[MIN_DAY]< MIN_DAY)
return 0;
if(MM[MAX_MONTH] >31 || MM[MIN_DAY]<1)
return 0;
if(YYYY[MAX_YEAR]>MAX_YEAR || YYYY[MIN_YEAR]<MIN_YEAR)
return 0;
return 1; //if statement true return 1
}
int Check_ISBN(int *ISBN){
if(ISBN[MAX_ISBN] > MAX_ISBN || ISBN[MIN_ISBN] < MIN_ISBN);
return 0;
return 1; //if ISBN VALID
}
// This function is used to check file existence, every time if it's called
//the following functions is user choice to either add a book, delete, view, and view by year -> Switch cases
void addBook(){
system("cls"); //clearing black screen
int Title_Validity = 0, Name_Validity = 0, ISBN_Validity, Date_Validity = 0,n;
struct Book *insert = NULL;
FILE* ptr = fopen("stored.txt","w");
if (ptr == NULL){
printf("Error opening the file! \n");
exit(1);}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
printf("\n\t\t ========================================================================");
printf("\n\t\t ADD NEW BOOK ");
printf("\n\t\t ========================================================================");
printf("\n\n\t\t\tENTER YOUR DETAILS BELOW:");
printf("\n\t\t\t---------------------------------------------------------------------------\n");
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
printf("\t\tHow many Books would you like to insert? ");
scanf("%d", &n);
for(int i = 0; i<n; i++){
insert = (struct Book*)calloc(n,sizeof(struct Book));
//Inputing Title & Check Title validity
//do{
printf("\n\t\t\tBook Title : ");
fflush(stdin);
fgets(insert[i].Title, MAX_Title, stdin);
/*Title_Validity = Check_Title(&insert[MAX_Title].Title);
if(Title_Validity){
printf("\n\t\t *_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*__*_*_*_*_*__*_*_*_");
printf("\t\t\t\t\t\t \t\t Invalid Input ! please try again! \n\t\t\t and make sure to not use any digits or special characters! \n ");
printf("\n\t\t *_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*__*_*_*_*_*__*_*_*_*_");
}
}while(Title_Validity);*/
//Inputing Author
printf("\n\t\t\tBook Author : ");
fflush(stdin);
fgets(insert[i].Author, MAX_Author, stdin);
//Inputing ISBN
//do{
printf("\n\t\t\tBook ISBN : ");
scanf("%d", &insert[i].ISBN);
// fflush(stdin);
//fgets(insert[i].ISBN, MAX_ISBN, stdin);
/* ISBN_Validity = Check_ISBN(&insert[MAX_ISBN].ISBN);
if(ISBN_Validity == 0){
printf("\n\t\t *_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*__*_*_*_*_*__*_*_*_");
printf("\t\t\t\t\t\t \t\t Invalid Input ! please try again! \n\t\t\t and make sure to not to not accedes the range 9~11! \n ");
printf("\n\t\t *_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*__*_*_*_*_*__*_*_*_*_");
}
}while(ISBN_Validity!=0);*/
//Inputing Edition
printf("\n\t\t\tBook Edition (only digits acceptable) : ");
scanf("%d", &insert[i].Edition);
//Inputing Date
printf("\n\t\t\tBook Date [DD MM YYYY] : ");
scanf("%d%d%d", &insert[i].DD,&insert[i].MM,&insert[i].Year);
printf("\n\t\t ========================================================================");
printf("\n\t\t The book %s has been added to the library.", insert[i].Title );
printf("\n\t\t ========================================================================");
}
//
Sort_Save(n,&insert[x].Title,&insert[x].Author,&insert[x].ISBN,&insert[x].Edition,&insert[x].DD,&insert[x].MM,&insert[x].Year);
return;
}
void Sort_Save(int n,char Title[MAX_Title],char Author[MAX_Author], int ISBN[MAX_ISBN], int Edition[], int day[MAX_DAY], int month[MAX_MONTH], int year[MAX_YEAR]){
int i;
struct Book *st;
FILE* fptr = fopen("sorted.txt", "w");
if(fptr == NULL){
printf("Error opening file! \n");
exit(1);
}
for(i=0; i<n; i++){
fprintf(fptr,"%s %s %d %d %d %d %d",st[i].Title,st[i].Author,st[i],st[i].ISBN,st[i].Edition,st[i].DD,st[i].MM,st[i].Year);
fprintf(fptr,"\n");
}
printf("\n");
fclose(fptr);
}
Since you're asking the users how much books they want to add, you have to allocate the block of memory only once, best right after (before the loop) and certainly not again and again in the loop, where it gets initialized with '0' (zero, that's what calloc does).
And opening a file with the mode "w" truncates that file to zero length, i don't think that this is what you want. And why do you open it, when you do not access it, neither for reading nor for writing?
After scanning, you call the Sort_Save function with a bunch of useless parameters (where does the variable 'x' come from?). You should declare the function like this:
int sortSave(struct Book *books, size_t size)
and pass the allocated block (insert) with the specified size (n).
If you want to sort your library, then you should open the existing database for read first ("r"), then read all the stored values into an array, append the new data to that array, call 'qsort' (see man qsort), specify your compare function (where you specify by which parameter your library should be sorted), close the file, open it again in write mode ("w") and finally write all your (sorted) data into that file.
Do not to forget to flush and close the file, nor to free the allocated blocks of memory.
Edit:
As a hint, seperate code from design. First make sure your code works as expected, then add all the fancy stuff, best as a seperate function.

Block reading and writing using fread and fwrite in C

I am trying to read employee information from the user and enter it into a file using fwrite() function and later i want to print the data contents on the screen using fread() to read from file and then print it.
When i am inside the program, this process is working absolutely fine but after program is exited and i access the file where the information has been stored, i see unreadable characters but in the program they are printed as normal english characters and digits.
Here is my code:
#include<stdio.h>
struct emp{
int id;
char name[30];
double salary;
}S;
void main(){
char fname[60];
printf("Enter file name: ");
scanf("%s", fname);
FILE *fptr = fopen(fname, "a+"); // open file in append + mode, create if not found.
if(fptr == NULL){
printf("Some error occured !\n");
return;
}
int i, size;
printf("Enter the number of employees whose information is needed to be added to the file: ");
scanf("%d", &size);
// writing
for(i = 0 ; i < size ; i++){
printf("Employee %d:\n", i+1);
printf("Enter id: ");
scanf("%d", &S.id);
printf("Enter name: ");
while(getchar() != '\n'); // clear buffer
scanf("%s", S.name);
printf("Enter salary: ");
scanf("%lf", &S.salary);
fwrite(&S, sizeof(struct emp), 1, fptr);
printf("----------------------------------------\n");
}
rewind(fptr); // move pointer to first record in file
// reading
printf("File contents: \n");
printf("ID\t\tNAME\t\tSALARY\n");
while(fread(&S, sizeof(struct emp), 1, fptr) != 0){
printf("%d\t\t%s\t\t%lf\n", S.id, S.name, S.salary);
}
}
Here is the picture of what i am trying to expalin.
You are writing to the file the struct and not printing its contents separately. It works when you read it back, but when you open the file, it simply doesn't know what it is (you have int and char* and double in your struct.
If you want to visualize it on the file, you need to print each term of the struct individually, and read it back the same way, in order to see it on screen.

Run - Time Check Failure #2 in C File processing

Run-Time Check Failure #2 - Stack around the variable 'filename' was corrupted.
My code works whenever I try to process the first memory location.
I can process the .txt file correctly, and I can print it.
Nevertheless, when I ask for a second memory location, the program crashes.
I tried to increase the size of filename, and I am also closing the first file, so I am clueless. Any help is acceptable! Thank you!!
This is a photo of the output
This is my code:
#include <stdio.h>
#define SIZE 100 //100 entries (100lines on a file)
#define SENSORN 100
int main()
{
FILE *fptr;
char filename[1000];
char dummy1[1];//dummy character that help me to erase what is the buffer when using gets()
int numberOfSensors;
int time[SENSORN][SIZE];
float powerConsumption[SENSORN][SIZE];
int sensor_num;
int count1 = 0;
printf("Please enter the number of sensors: ");
scanf("%d", &numberOfSensors);
//Asking for the link
//numberOfSensors - 1 because for example, if we want only 2 sensors we need sensor0 and sensor1 only
for (sensor_num = 0; sensor_num <= (numberOfSensors - 1); sensor_num++)
{
printf("Please enter the file location for sensor %d\n", sensor_num);
gets(dummy1);//clearing the buffer
gets(filename);
fptr = fopen(filename, "r");
//if file cannot be opened, then display and error message
if (fptr == NULL)
{
printf("Error opening the file! %s \n", filename);
printf("Please restart the program \n");
return 0; //exit the program
}
else
{
//Loop that let us read and print all the file by storing each value to its respective array
while (!feof(fptr))
{
//storing all the values in their respective array
//sensor_num is the sensor number
//count1 is the line number we are reading from the file
fscanf(fptr, "%d %f", &time[sensor_num][count1], &powerConsumption[sensor_num][count1]);
//making sure we have all the values stored
//Note: do not comment the following line in order to check that all values are stored
fprintf(stdout, "%d %6.2f \n", time[sensor_num][count1], powerConsumption[sensor_num][count1]);
count1++;
}
}
//closing file
fclose(fptr);
}
}
}
As Martin James said char dummy1[1]; is an absolute no-no.
Use fgets() instead of gets(), so instead of
gets(dummy1);//clearing the buffer
gets(filename);`
try,
fgets( filename, sizeof(filename) , stdin );

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.

Resources