C - data not being added to the txt file - c

I'm supposed to be creating a small client managing program for a private clinic (before you ask, yes this is college work) but I seem to have found 2 bugs that don't allow me to progress on this.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct DATA {
int dia, mes, ano;
};
struct cliente {
char pnome[15];
char snome[15];
char telefone[10];
char bi[10];
float peso, altura;
struct DATA data;
};
int main () {
FILE *c, *tempo;
int op, i;
int stelemovel, sbi;
char filename[15];
struct cliente a;
printf("1 - procurar\n");
printf("2 - inserir novo\n");
printf("3 - gravar\n");
printf("4 - sair\n");
scanf("%d", &op);
switch(op) {
**(...)**
case 2 :
printf("novo cliente. Dados: \n");
tempo = fopen("temp.txt", "a"); //opens a file to store the data on so I can copy it later, this was an attempt to correct a bug I will explain ahead
printf("primeiro nome \n");
scanf("%s", &a.pnome); //scan the first name
fprintf(tempo, "%s", a.pnome); //print to tempo file
printf("segundo nome \n");
scanf("%s", &a.snome); //second name
fprintf(tempo, "%s", a.snome);// print
printf("peso\n"); //you get the picture so far
do{
scanf("%f", &a.peso);
} while (a.peso<1);
fprintf(tempo, "%.2f", a.peso);
printf("altura\n");
do{
scanf("%f", &a.altura);
} while (a.altura<1);
fprintf(tempo, "%.2f", a.altura);
printf("por favor insira data nascimento (dia mes ano)\n");
do {
printf("dia\n");
scanf("%d", &a.data.dia);
} while (a.data.dia<1 || a.data.dia>31);
fprintf(tempo, "%d", a.data.dia);
do {
printf("mes\n");
scanf("%d", &a.data.mes);
} while (a.data.mes<1 || a.data.mes>12);
fprintf(tempo, "%d", a.data.mes);
do {
printf("ano\n");
scanf("%d", &a.data.ano);
} while (a.data.ano<1);
fprintf(tempo, "%d", a.data.ano);
printf("numero telefone\n");
do {
scanf("%s", &a.telefone);
} while (strlen(a.telefone)!=9);
fprintf(tempo, "%d", a.telefone);
printf("numero BI\n");
do {
scanf("%s", &a.bi);
} while (strlen(a.bi)!=9);
fprintf(tempo, "%d", a.bi);
/* printf("%s, %s\n %.2f, %.2f\n %d, %d, %d\n %s, %s\n", a.pnome, a.snome, a.peso, a.altura, a.data.dia, a.data.mes, a.data.ano, a.telefone, a.bi); */
/*this was something I used to test out if the data was saving properly
which is EXCEPT for the a.telefone and the a.bi, they're being printed together for some reason
*/
return main();
case 3 :
printf("nome do ficheiro\n");
scanf("%s", &filename);
c = fopen(filename, "a");
printf("%s, %s\n %.2f, %.2f\n %d, %d, %d\n %s, %s\n", a.pnome, a.snome, a.peso, a.altura, a.data.dia, a.data.mes, a.data.ano, a.telefone, a.bi);
fprintf(c, "%s, %s\n %.2f, %.2f\n %d, %d, %d\n %s, %s\n", a.pnome, a.snome, a.peso, a.altura, a.data.dia, a.data.mes, a.data.ano, a.telefone, a.bi);
/*this part basically should copy all I scanned in case 2 and print it to a document but I can't seem to be able to write on the file. The file is created opened but there's never any content on it */
return main();
**(...)**
return 0;
}
This is the bug I get when printing, a.bi gets printed normally next though which basically tells me the problem is on a.telefone but I can't seem to see it.
I'm writing this here because I'm really out of ideas, slightly saturated too and as you can probably guess I'm not exactly a pro on files. Thanks in advance for any help being provided though.
I'm sure the solution is probably simple but I can't seem to see it at this point...
EDIT
Now if ya guys can help me on why I'm not able to print the stuff I scan to a file this matter can be considered closed.
EDIT 2
Ok seems like it's printing to a file but it's not separating the words through commas.

The reason your code is printing telephone and bi together is because you didn't leave enough space for the '\0' at the end of the string. Strings in C are null terminated. This also indicates your not sanitizing your inputs. Doing scanf("%s", str); is very dangerous and leads to buffer exploits. You should provide a width to it like scanf("%8s", str); or consider using something like fgets().

The telephone string:
char telefone[9];
Is too small to held the phone number you punched in plus the null tereminator of the string. Changing it to something larger as:
char telefone[16];
Will work. But the probllem here is that you don't make any check on the input data for buffer overflow.
Always check for max input.

char telefone[9];
This buffer can hold a string of up to 8 characters, plus terminating '\0' as the 9th element. You are experiencing buffer overflow by writing XXX XXX XXX to it. Enlarge the buffer to at least 10 characters and always check the returned value of scanf in each call:
char telefone[10];
if (scanf("%s", &a.telefone) != 0)
// handle error
Consider using fgets to avoid buffer overflow:
char buf[10];
fgets(buf, sizeof(buf), stdin);

a major problem with the posted code is repeatedly calling fopen() with the same variable on a file that is already open.
Suggest calling fclose() before every new recursion AND before exiting the program.

Related

fprintf function in code writes garbage data into .csv file

I'm trying to create a C program which collect's an applicant's information. When a user is prompted to enter their written subjects, the program writes rubbish data into the .csv file when they wrote one. And sometimes does the same when the number of subjects written is two.
I've tried to clear the buffer stream, but it's no use. Strangely, using different compliers like DevC++, Embarcadero DevC and VS Code produces different results.
Edit: I've also noticed the chances of the rubbish values being written into the file are lowered when the grades of the subjects is lower than the number of subjects written.
Attached below is the code. And an image of the output.
// C libraries.
#include <stdio.h> // Contains function prototypes for the standard input/output library functions, and information used by them.
#include <conio.h> // Contains function prototypes for the console input/output library functions.
#include <stdlib.h> // Contains function prototypes for conversions of numbers to text and text to numbers, memory allocation, random numbers and other utility functions.
#include <string.h> // Contains function prototypes for string-processing functions.
#include <time.h> // Contains function prototypes and types for manipulating the time and date.
#include <stdbool.h> // Contains macros defining bool, true and false, used for boolean variables.
struct Applicant
{
int applicationID;
int dateOfApplication;
char lastName[21];
char firstName[21];
char middleName[21];
char dateOfBirth[21];
int age;
char gender;
char address[100];
char phoneNumber[21];
char emailAddress[51];
char mobileNumber[21];
int numSubjectsWritten;
char csecSubjects[20][100];
char grades[20];
char programmeSelection[10];
};
struct Applicant getApplicantData()
{
struct Applicant applicant;
int i = 0;
int numSubjects;
// Asking for applicant input for various fields.
printf("| Personal |");
printf("\nEnter Last Name: ");
scanf(" %20s", &applicant.lastName);
fflush(stdin);
printf("\nEnter First Name: ");
scanf(" %20s", &applicant.firstName);
fflush(stdin);
printf("\nEnter Middle Name (If you don't have a middle name, leave this field blank.): ");
gets(applicant.middleName);
fflush(stdin);
/*
printf("\nEnter Date of Birth: ");
scanf(" %s", &applicant.dateOfBirth);
fflush(stdin);
printf("\nEnter Gender. 'M' for male, 'F' for female, (M|F): ");
scanf(" %c", &applicant.gender);
fflush(stdin);
printf("\n\n| Contact Information |");
printf("\nEnter Address: ");
gets(applicant.address);
fflush(stdin);
printf("\nEnter Phone Number: ");
gets(applicant.phoneNumber);
fflush(stdin);
printf("\nEnter Email Address: ");
gets(applicant.emailAddress);
fflush(stdin);
printf("\nEnter Mobile Number: ");
gets(applicant.mobileNumber);
fflush(stdin);
*/
printf("\n\n| Education |");
printf("\nEnter Number of Subjects Written: ");
scanf("%d", &applicant.numSubjectsWritten);
fflush(stdin);
while (i < applicant.numSubjectsWritten)
{
printf("\nEnter the subject: ");
gets(applicant.csecSubjects[i]);
fflush(stdin);
printf("\nEnter the grade for that subject: ");
scanf(" %c", &applicant.grades[i]);
fflush(stdin);
i++;
}
return applicant;
}
int main(void)
{
FILE *file = fopen("Data.csv", "a+");
int i, j;
if (!file)
{
printf("\nError! Can not open data file.\nPlease contact the Program Addmission Manager as soon as possible with the error message.");
exit(1);
}
else
{
struct Applicant applicant = getApplicantData();
//fprintf(file, "%s:%s:%s:%s:%c:%s:%s:%s:%s", applicant.lastName, applicant.firstName, applicant.middleName, applicant.dateOfBirth, applicant.gender, applicant.address, applicant.phoneNumber, applicant.emailAddress, applicant.mobileNumber);
fprintf(file, "%s:%s:%s:", applicant.lastName, applicant.firstName, applicant.middleName);
for (i = 0; applicant.csecSubjects[i][0] != '\0'; i++)
{
fprintf(file, " %s", applicant.csecSubjects[i]);
fflush(stdout);
fflush(stdin);
fflush(file);
fprintf(file, " ( %c):", applicant.grades[i]);
fflush(stdout);
fflush(stdin);
fflush(file);
}
}
return 0;
}
First problems I see:
Remove the & from all instances where you scanf a string
Don't use gets, or mix scanf and fgets
Don't fflush(stdin)
Instead of scanf, consider using a custom-made input method with condition checking and anything you need. I will give an example.
#define BUFFER_SIZE 512
void input(char* buffer){
memset(buffer, 0, BUFFER_SIZE); // Initializing the buffer.
fgets(buffer, BUFFER_SIZE, stdin);
strtok(buffer,"\n");
}
How to take input using that?
void main(){
int username[BUFFER_SIZE];
input(username);
}
A way to write a structure to a file is shown below.
void Structure_Print(Applicant* applicant, FILE* stream, int no_of_applicant){
if(no_of_applicant==0){
fprintf(stdout, "No applicant yet.\n");
return;
}
fprintf(stream, "%s:%s:%s:", applicant.lastName, applicant.firstName, applicant.middleName);
for (i = 0; applicant.csecSubjects[i][0] != '\0'; i++)
{
fprintf(stream, " %s:", applicant.csecSubjects[i]);
fprintf(stream, " %c:", applicant.grades[i]);
}
return;
}
Also, I noticed how you tried to make it readable while saving it in subject(grade) format. I recommend you to not do that. Your .csv file is just for database. Nobody is going to read it. So just store the data by comma or any character separator. It will make it easier to extract data later.

How can I clear the input buffer without using rewind function? [duplicate]

I am not able to flush stdin here, is there a way to flush it? If not then how to make getchar() to take a character as input from user, instead of a "\n" left by scanf() in the input buffer??
#include "stdio.h"
#include "stdlib.h"
int main(int argc,char*argv[]) {
FILE *fp;
char another='y';
struct emp {
char name[40];
int age;
float bs;
};
struct emp e;
if(argc!=2) {
printf("please write 1 target file name\n");
}
fp=fopen(argv[1],"wb");
if(fp==NULL) {
puts("cannot open file");
exit(1);
}
while(another=='y') {
printf("\nEnter name,age and basic salary");
scanf("%s %d %f",e.name,&e.age,&e.bs);
fwrite(&e,sizeof(e),1,fp);
printf("Add another record (Y/N)");
fflush(stdin);
another=getchar();
}
fclose(fp);
return 0;
}
EDIT: updated code, still not working properly
#include "stdio.h"
#include "stdlib.h"
int main(int argc,char*argv[]) {
FILE *fp;
char another='y';
struct emp {
char name[40];
int age;
float bs;
};
struct emp e;
unsigned int const BUF_SIZE = 1024;
char buf[BUF_SIZE];
if(argc!=2) {
printf("please write 1 target file name\n");
}
fp=fopen(argv[1],"wb");
if(fp==NULL) {
puts("cannot open file");
exit(1);
}
while(another=='y') {
printf("\nEnter name,age and basic salary : ");
fgets(buf, BUF_SIZE, stdin);
sscanf(buf, "%s %d %f", e.name, &e.age, &e.bs);
fwrite(&e,sizeof(e),1,fp);
printf("Add another record (Y/N)");
another=getchar();
}
fclose(fp);
return 0;
}
Output:
dev#dev-laptop:~/Documents/c++_prac/google_int_prac$ ./a.out emp.dat
Enter name,age and basic salary : deovrat 45 23
Add another record (Y/N)y
Enter name,age and basic salary : Add another record (Y/N)y
Enter name,age and basic salary : Add another record (Y/N)
fflush(stdin) is undefined behaviour(a). Instead, make scanf "eat" the newline:
scanf("%s %d %f\n", e.name, &e.age, &e.bs);
Everyone else makes a good point about scanf being a bad choice. Instead, you should use fgets and sscanf:
const unsigned int BUF_SIZE = 1024;
char buf[BUF_SIZE];
fgets(buf, BUF_SIZE, stdin);
sscanf(buf, "%s %d %f", e.name, &e.age, &e.bs);
(a) See, for example, C11 7.21.5.2 The fflush function:
int fflush(FILE *stream) - If stream points to an output stream or an update stream in which the most recent operation was not input, the fflush function causes any unwritten data for that stream to be delivered to the host environment to be written to the file; otherwise, the behavior is undefined.
Update: You need to add another getchar() at the end of your loop to consume the '\n' that follows the Y/N. I don't think this is the best way to go, but it will make your code work as it stands now.
while(another=='y') {
printf("\nEnter name,age and basic salary : ");
fgets(buf, BUF_SIZE, stdin);
sscanf(buf, "%s %d %f", e.name, &e.age, &e.bs);
fwrite(&e,sizeof(e),1,fp);
printf("Add another record (Y/N)");
another=getchar();
getchar();
}
I would suggest reading the data you want to parse (up to and including the '\n') into a buffer and then parse it out using sscanf(). This way you consume the newline and you can perform other sanity checks on the data.
Use this instead of getchar():
char another[BUF_SIZE] = "y";
while( 'y' == another[0] )
{
printf( "\nEnter name,age and basic salary : " );
fgets( buf, BUF_SIZE, stdin );
sscanf( buf, "%s %d %f", e.name, &e.age, &e.bs );
fwrite( &e, sizeof(e) , 1, fp );
printf( "Add another record (Y/N)" );
fgets( another, BUF_SIZE, stdin );
}
It's not a good practice to use fflush( stdin ) as it has undefined behavior. Generally, functions like scanf() leaves trailing newlines in stdin. So, it is better to use functions that are "cleaner" than scanf(). You can replace your scanf() with a combination of fgets() and sscanf() and you can do away with fflush( stdin ).
I would recommend the fgets()+sscanf() approach that a lot of other people have suggested. You could also use scanf("%*c"); before the call to getchar(). That will essentially eat a character.
If you are doing this under windows, you can use winapi to flush input buffer before your getch().
#include <windows.h>
hStdin = GetStdHandle(STD_INPUT_HANDLE);
FlushConsoleInputBuffer(hStdin);
-or-
#include <windows.h>
FlushConsoleInputBuffer(GetStdHandle(STD_INPUT_HANDLE));
As others already pointed out, you should not write a struct to a file. Instead, try to write the data in a formatted manner. This way your text file can be parsed line-by-line by finding the last and second-to-last delimiters, for example semicolons. Keep in mind that certain characters like '-' or '.' may occur in the stringified float field.
int write_data(FILE *fh, struct emp *e) {
if(fh == NULL || e == NULL)
return -1;
fprintf(fh, "%s;%d;%f", e->name, e->age, e->bs);
return 0;
}
The other thing is how everybody keeps recommending the same scanf family of functions, but nobody ever checks whether the return value is equal to the number of fields to be read. I think that is a bad idea, effectively asking for trouble. Even with the strtol/strtod way you need error checking:
int parse_int(char *buf, long *result) {
if(buf == NULL || result == NULL)
return -1;
errno = 0;
*result = strtoul(buf, NULL, 0);
if(errno != 0) {
perror("strtoul");
return -1;
}
return 0;
}
the two code examples above return silently which is fine if you plan to call them using existing objects all the time; consider printing an error message, though, and illustrate in your documentation that people should check the return values when using your functions.
stdin is not something flushable, you can flush only output streams. I.e. you don't need to call flush on stdin at all.

fscanf() cannot read without using '&' to the int data type [duplicate]

This question already has answers here:
When should I use ampersand with scanf()
(3 answers)
Closed 2 years ago.
I am having problem with a specific part of the code which I cant find any answer to yet. Here the fscanf() was not able to read the value of file until I added an '&' sign before add.age variable in this section. I got the problem solved but still cant figure out how it works. I mean why do I need to provide address of an integer data type and not of any string. Can any one explain please?
while(fscanf(fp, "%s %d %s", add.name, &add.age, add.dept)!=EOF)
{
printf("%s\t\t %d\t\t %s\n", add.name, add.age, add.dept);
}
This is the full code that I wrote for reference if you want
#include<stdio.h>
#include<stdlib.h>
void add_user(void);
void see(void);
void see_all(void);
struct student
{
char name[50];
char dept[50];
int age;
}add, check;
int main()
{
int choice;
printf("1. Add \n2. See \n3. See All \nEnter choice:");
scanf("%d", &choice);
switch(choice)
{
case 1:add_user();
break;
case 2:see();
break;
case 3:see_all();
break;
default:printf("Wrong Input");
}
}
void add_user()
{
FILE *fp;
printf("Enter name : ");
fflush(stdin);
gets(add.name);
printf("Enter age : ");
scanf("%d", &add.age);
printf("Enter department : ");
fflush(stdin);
gets(add.dept);
fp=fopen("Creating a file with multiple records and reading it.txt", "a+");
if(fp==NULL)
{
printf("file pointer is null");
exit(0);
}
fprintf(fp, "%s %d %s\n", add.name, add.age, add.dept);
fclose(fp);
main();
}
void see()
{
}
void see_all()
{
FILE *fp;
fp=fopen("Creating a file with multiple records and reading it.txt", "r");
if(fp==NULL)
{
printf("file pointer is null");
exit(0);
}
printf("Name\t\t Age\t\t Department\n");
while(fscanf(fp, "%s %d %s", add.name, &add.age, add.dept)!=EOF)
{
printf("%s\t\t %d\t\t %s\n", add.name, add.age, add.dept);
}
fclose(fp);
}
A "string" in C (in your case a character array) already decays to a pointer indicating the address in memory of the first character. There's no such mechanism for a single int, and as a result you need to explicitly pass an address that holds an int to scanf, which is done by prefixing a variable or lvalue expression with &. scanf needs pointers so that it can write the data it scanned into memory you control and can use.
fscanf (and other scanf variants) take pointers so they can assign the read values to them. In the case of strings, you already have a char * (read: char pointer), so you don't need and additional &).

How to read a specific line from binary file into a structure C

Essentially, I printed to a binary file using fseek() and fwrite(). However, I want to read the contents from a specific line into a structure. I also used fseek() and fread() to obtain the contents. I prompted the user to enter a code. From what I have learnt, I would use the value obtained from the user to use in the fseek function to get the specific line to start read from. Apparently, the fseek to read the contents does not work, I am getting gibberish essentially when it is displayed on the screen. Assistance is greatly appreciated.
#include <conio.h>
#include <stdio.h>
typedef struct registered
{
int compcode;
char compname[20];
int pinID;
int custID;
char IDtype[15];
int compID;
}REGISTERED;
void AddUpdate(REGISTERED info);
void SellPetrol();
void main(){
REGISTERED info = {0, "Apple", 0, 0, "passport", 0};
REGISTERED list;
AddUpdate(info);
SellPetrol();
}
void AddUpdate(REGISTERED info){
int choice;
FILE *registryfile = NULL;
registryfile = fopen("Sales.dat", "ab");
if (registryfile == NULL){
perror("Error: ");
}
else{
do{
printf("Company Code: ");
scanf("%d", &info.compcode);
printf("Company Name: ");
scanf("%s", &info.compname);
printf("Pin: ");
scanf("%d", &info.pinID);
printf("Customer ID: ");
scanf("%d", &info.custID);
printf("ID type: ");
scanf("%s", &info.IDtype);
printf("Company ID: ");
scanf("%d", &info.compID);
fseek(registryfile, (info.compcode - 1) * sizeof(REGISTERED), SEEK_SET);
fwrite(&info, sizeof(REGISTERED), 1, registryfile);
printf("Enter choice: ");
scanf("%d", &choice);
}while(choice == 1);
}
printf("\tCompany Code: %d\t\n", info.compcode);
printf("\tCustomer ID: %d\t\n", info.custID);
fclose(registryfile);
}
void SellPetrol(){
int code = 0, PIN;
REGISTERED list;
FILE *registryfile = NULL;
registryfile = fopen("Sales.dat", "rb");
if (registryfile == NULL){
perror("Error: ");
}
else{
printf("Please enter the company code: ");
scanf("%d", &code);
// printf("Please enter the PIN: ");
// scanf("%d", &PIN);
rewind(registryfile);
fseek(registryfile, (code - 1) * sizeof(REGISTERED), SEEK_SET);
fread(&list, sizeof(REGISTERED), 1, registryfile); //reads data into list
fflush(stdin);
printf("Company Code: %d\n", list.compcode);
printf("Company Name: %s\n", list.compname);
printf("Pin: %d\n", list.pinID);
printf("Customer ID: %d\n", list.custID);
printf("ID Type: %s\n", list.IDtype);
printf("Company ID: %d\n", list.compID);
}
fclose(registryfile);
}
It seems whichever method you're using to learn C is causing troubles, as the mistakes you seem to be making are common. I suggest reading a book, such as K&R2E... Do the exercises as you stumble across them; don't move on until you've completed them, and ask questions about them if necessary.
Don't fflush(stdin). fflush doesn't do what you think it does.
Check return values for functions such as fopen, scanf, fseek, fread, even fwrite. You'll probably find that your fread or scanf is returning a value indicating failure, hence the gibberish you speak of.
Be aware that C uses pass-by-value semantics ONLY. The source of at least one error in your code is a misunderstanding regarding these semantics. Namely, AddUpdate has no way to modify the variable declared within main, as it recieves a copy of that variable; at this point it seems void AddUpdate(REGISTERED info) should be void AddUpdate(void) and info should be declared within AddUpdate.
scanf("%s", &info.compname); probably doesn't do what you think it does. The %s directive tells scanf to read (metalinguistically speaking) a word (that is, a whitespace-delimitered token), not a line (a newline delimitered token), of user input. You probably want int x = scanf("%19[^\n]", info.compname); or better yet, char *x = fgets(info.compname, sizeof info.compname, stdin);...
void main() is unportable, and so is #include <conio.h>. You probably want int main(void) and ... you don't appear to be using any functions from <conio.h>, so you probably don't want anything in place of that. In C99, a main function that has no return statement will implicitly return 0; without a warning issued.

Debug assertion failed C - Not deleting

I'm writing a program that allows users to add a question that has 4 answers, right answer, date, author and level of complexity, also the program has functions for reading all the questions and deleting a question. When I choose the option add a question and i insert all of the characteristics the message box for the error appears it also doesn't allow me to delete or see the `.
questions. i need help.
Why is the following code not allowing me to delete a question?
void edit()
{
char filename[2];
int y;
int q,ft,s,t, fr,d,a,l,tr,n,da;
FILE *f, *f1;
f=fopen("pff.txt","r");
if (f==NULL)
{
perror ("Error!");
}
fscanf(f,"%d",&y);
printf(" " );
gets(question.name);
n=sizeof(question.name);
printf("Name : ");
gets(question.name);
q=sizeof(question.name);
printf("Answer 1: ");
gets(question.first);
ft=sizeof(question.first);
printf("Answer 2: ");
gets(question.second);
s=sizeof(question.second);
printf("Answer 3: ");
gets(question.third);
t=sizeof(question.third);
printf("Answer 4: ");
gets(question.fourth);
fr=sizeof(question.fourth);
printf("Right answer (1-4): ");
scanf("%d",&question.tr);
printf(" ");
gets(question.date);
da=sizeof(question.date);
printf("Date: ");
gets(question.date);
d=sizeof(question.date);
printf(" Author: ");
gets(question.author);
t=sizeof(question.author);
printf("Level (0-2): ");
scanf("%d",&question.level);
fclose (f);
sprintf(filename, "%d.bin", y+1);
puts (filename); f=fopen(filename,"wb");
fwrite(&q,sizeof(int),1,f);
fwrite(question.name,sizeof(question.name),1,f);
fwrite(&ft,sizeof(int),1,f);
fwrite(question.first,sizeof(question.first),1,f);
fwrite(&s,sizeof(int),1,f);
fwrite(question.second,sizeof(question.second),1,f);
fwrite(&t,sizeof(int),1,f);
fwrite(question.third,sizeof(question.third),1,f);
fwrite(&fr,sizeof(int),1,f);
fwrite(question.fourth,sizeof(question.fourth),1,f);
fwrite (&question.tr, sizeof (int),1,f);
fwrite(&d,sizeof(int),1,f);
fwrite(question.date, sizeof(question.date),1,f);
fwrite(&a,sizeof(int),1,f);
fwrite(question.author,sizeof(question.author),1,f);
fwrite(question.level,sizeof(int),1,f);
fclose(f);
f=fopen("pff.txt","w");
fprintf(f,"%d",y+1);
fclose(f);
}
The buffer filename is too short to store the name of file. It should be at least 16-character long if int is 32-bit long.
Not knowing the actual definition, the line fwrite(question.level,sizeof(int),1,f); seems wrong because the address of question.level is passed to scanf with use of %d specifier, and I guess its type is int. You should include proper header and enable compiler warnings.
You shouldn't pass NULL, which may be returned from fopen, to fscanf.
You shouldn't use gets from the standard library, which has an unavoidable risk of buffer overrun, and is deprecated in C99 and removed in C11.
Try this (the problem that gets is used isn't resolved here):
void edit()
{
char filename[32]; /* allocate enough buffer */
int y;
int q,ft,s,t, fr,d,a,l,tr,n,da;
FILE *f, *f1;
f=fopen("pff.txt","r");
if (f==NULL)
{
perror ("Error!");
return; /* avoid using NULL as file pointer */
}
fscanf(f,"%d",&y);
printf(" " );
gets(question.name);
n=sizeof(question.name);
printf("Name : ");
gets(question.name);
q=sizeof(question.name);
printf("Answer 1: ");
gets(question.first);
ft=sizeof(question.first);
printf("Answer 2: ");
gets(question.second);
s=sizeof(question.second);
printf("Answer 3: ");
gets(question.third);
t=sizeof(question.third);
printf("Answer 4: ");
gets(question.fourth);
fr=sizeof(question.fourth);
printf("Right answer (1-4): ");
scanf("%d",&question.tr); /* warning: don't place newline character after the number to be read here, or what is read to question.date may become not what is wanted */
printf(" ");
gets(question.date);
da=sizeof(question.date);
printf("Date: ");
gets(question.date);
d=sizeof(question.date);
printf(" Author: ");
gets(question.author);
t=sizeof(question.author);
printf("Level (0-2): ");
scanf("%d",&question.level);
fclose (f);
sprintf(filename, "%d.bin", y+1);
puts (filename);
f=fopen(filename,"wb");
if (f == NULL) return; /* add error check */
fwrite(&q,sizeof(int),1,f);
fwrite(question.name,sizeof(question.name),1,f);
fwrite(&ft,sizeof(int),1,f);
fwrite(question.first,sizeof(question.first),1,f);
fwrite(&s,sizeof(int),1,f);
fwrite(question.second,sizeof(question.second),1,f);
fwrite(&t,sizeof(int),1,f);
fwrite(question.third,sizeof(question.third),1,f);
fwrite(&fr,sizeof(int),1,f);
fwrite(question.fourth,sizeof(question.fourth),1,f);
fwrite (&question.tr, sizeof (int),1,f);
fwrite(&d,sizeof(int),1,f);
fwrite(question.date, sizeof(question.date),1,f);
fwrite(&a,sizeof(int),1,f);
fwrite(question.author,sizeof(question.author),1,f);
fwrite(&question.level,sizeof(int),1,f); /* add & before question.level */
fclose(f);
f=fopen("pff.txt","w");
if (f != NULL) { /* add error check */
fprintf(f,"%d",y+1);
fclose(f);
}
}

Resources