I am creating this change function. void cha(struct cont x);, It will ask for the lname then check if its in the file. After that, It will edit.Asks for the lname and fname again. It works but it writes at the bottom of the file.
struct cont
{
char lname[20];
char fname[20];
}s;
void cha(struct cont x)
{
FILE *fp;
char lname[20];
int flag=0;
fp=fopen("database.dat","a+");
if(fp==NULL)
{
printf("file error");
}
else
{
printf("\nenter lname: ");
gets(lname);
while(fscanf(fp,"%s %s",x.lname,x.fname)==2)
{
if(strcmp(lname,x.lname)==0)
{
printf("enter lname: ");
gets(x.lname);
printf("enter fname: ");
gets(x.fname);
fseek(fp,-sizeof(x),SEEK_CUR);
fprintf(fp,"%s %s\n",x.lname,x.fname);
flag=1;
break;
}
}
if(flag==1)
{
printf("success!");
}
else
{
printf("data not found.");
}
}
fclose(fp);
}
fp=fopen("database.dat","r");
You have opened the file in read mode and you are trying to write to the file
fprintf(fp,"%s %s\n",x.lname,x.fname);
Use a+ to open the file in append mode.
gets() is no more a standard and use fgets() which takes care of buffer overflow.
Man says:
a+
Open for reading and appending (writing at end of file). The file is
created if it does not exist. The initial file position for reading is
at the beginning of the file, but output is always appended to the end
of the file.
Just write it to another file
FILE *newFile = fopen("newDatabase.dat","w");
if(strcmp(lname,x.lname)==0)
{
//scan data to tmp var
fprintf(newFile ,"%s %s\n",x2.lname,x2.fname);
}
else
{
//write original var
fprintf(newFile ,"%s %s\n",x.lname,x.fname);
}
you can then change the name of the new file to overwrite the old one if its important
Related
This question already has answers here:
gets() does not work
(3 answers)
Why is gets() not consuming a full line of input?
(7 answers)
Closed 1 year ago.
I am trying to read students data (name, department, roll, sgpa, cgpa), I used fgets function to read name and department, but it skips to the department and can't read name.
here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
char name[100];
char department[50];
int roll;
float sgpa[12];
float cgpa;
} Student;
void add(FILE *fp);
void modify(FILE *fp);
void display(FILE *fp);
FILE * del(FILE * fp);
int main(int argc, char **argv) {
int option;
FILE *fp;
fp = fopen("db.txt", "rb+");
if (fp == NULL) {
fp = fopen("db.txt", "wb+");
if (fp == NULL) {
printf("Can't open the database");
return 0;
}
}
printf("\t1. Add Student");
printf("\n\t2. Modify Student");
printf("\n\t3. Show All Student");
printf("\n\t4. Remove Student");
printf("\n\tEnter Your Option :--> ");
scanf("%d",&option);
switch(option)
{
case 1:
add(fp);
break;
case 2:
// modify(fp);
break;
case 3:
// display(fp);
break;
case 4:
// fp = del(fp);
break;
default:
printf("Unkonw option\n");
}
return 0;
}
void add(FILE *fp) {
Student std;
int i;
float cgpa;
fseek(fp,0,SEEK_END);
printf("\n\tEnter Full Name of Student: ");
fflush(stdin);
fgets(std.name,100,stdin);
std.name[strlen(std.name)-1]='\0';
printf("\n\tEnter Depertment Name: ");
fflush(stdin);
fgets(std.department,50,stdin);
std.department[strlen(std.department)-1]='\0';
printf("\n\tEnter Roll number: ");
scanf("%d",&std.roll);
printf("\n\tEnter SGPA for 12 semesters\n");
for(i=0,cgpa=0; i<12; i++)
{
scanf("%f",&std.sgpa[i]);
cgpa+=std.sgpa[i];
}
cgpa/=12.0;
std.cgpa=cgpa;
fwrite(&std,sizeof(std),1,fp);
}
Is there a way of limiting scanf in C?
I did this, if you're having that many problems with string input giving an eye on my other answer might help you
Here's a more specific answer to your problem on message you place what you wanna print before the input and StringInput you place the array you're using to hold the message
I hope this works since you also use a array for it
also i see this:
fp = fopen("db.txt", "rb+");
if (fp == NULL) {
fp = fopen("db.txt", "wb+");
if (fp == NULL) {
printf("Can't open the database");
return 0;
}
}
which may not be what you want because if it fails because of a sudden glitch by using wb+ you will overwrite it
“r+” – Searches file. Opens the file for both reading and writing. If opened successfully, fopen() loads it into memory and sets up a pointer which points to the first character in it. Returns NULL, if unable to open the file.
“w+” – Searches file. If the file exists, its contents are overwritten. If the file doesn’t exist, a new file is created. Returns NULL, if unable to open the file.
FUNCAUX_MAX_STRING is a macro and you define it like so:
#define FUNCAUX_MAX_STRING 100
This makes it so that the number or elements is 100 and you can easily change every number thats using the macro by simply changing the value once
void readString(char message[FUNCAUX_MAX_STRING], char StringInput[FUNCAUX_MAX_STRING], int maxChars)
{
int sizeString;
do // Repete leitura caso sejam obtidas strings vazias
{
printf("%s", message);
fgets(StringInput, maxChars, stdin);
sizeString = strlen(StringInput);
if (sizeString == 1)
{
printf("Nao foram introduzidos caracteres!!! . apenas carregou no ENTER \n\n");
}
}
while (sizeString == 1);
if(StringInput[sizeString-1] != '\n')
{
cleanBufferStdin();
}
else
{
StringInput[sizeString-1] = '\0';
}
}
void cleanBufferStdin(void)
{
char chr;
do
{
chr = getchar();
}
while (chr != '\n' && chr != EOF);
}
The code is supposed to overwrite or clear the file when Yes is entered, but it still does so when No or anything else is entered.
void createCanteenFoodFile()
{
FILE* fp;
int i,t=0;
char ans;
struct food foodie={0,"","",0,0.0,0.0,0.0,0.0};
if ((fp = fopen("food", "wb"))==NULL)
{
printf("Cannot open file \n");
}
else
{
printf("Are you sure you want to create a new file?\nThis will overwrite any previous data\n\n");
printf("Type Yes or No\n");
scanf("%c",&ans);
if(ans=='Y' or ans=='y')
{
for (i=0;i<=100;i++)
{
fwrite(&foodie,sizeof(struct food),1,fp);//food file created
}
printf("\n------------------------------------------------------------\n");
printf("\t\t FILE CREATED\t\t\n");
printf("------------------------------------------------------------\n");
fflush(stdin);
}
else if(ans=='N' or ans=='n')
{
printf("Option denied\n");
fflush(stdin);
}
else
{
printf("\t\t ERROR - Invalid option\n");
fflush(stdin);
}
fclose(fp);
}
}
Opening a file with the "wb" flags will remove all previous content of the file, regardless of if you ever write to it. To solve your issue you would have to move your call to fopen till after you got confirmation that the file should be deleted.
I'm writing a code for a simple phone book. Everything works fine except that after successfully deleting an entry using my delete function my append function cant seem to write entries to the file anymore. unless I delete the database.data file that I'm using to store the entries.
NOTE:
the character array file="database.data"
delete function:
void deletee()
{
int tode,count;
char ch;
printc();
count=1;
FILE *filepointer,*filepointer2;
filepointer=fopen(file,"r+");
filepointer2=fopen("datatemp.data","w+");
if(filepointer==NULL)
{
printf("ERROR ERROR!");
}
printf("Enter line number of the line to be deleted: \n");
scanf("%d",&tode);
while (ch!=EOF)
{
ch=getc(filepointer);
if(ch=='\n')
{
count++;
}
if(count!=tode)
{
fprintf(filepointer2,"%c",ch);
}
}
fclose(filepointer);
fclose(filepointer2);
remove(file);
rename("datatemp.data",file);
printf("Content successfully deleted!!");
}
heres the function for append:
void append(struct entry *ptr)
{
FILE *filepointer;
filepointer=fopen(file,"a+");
fflush(stdin); //This block is asking for the inputs to be placed into the file
printf("Enter FName: ");
scanf("%s",&ptr->fn);
printf("\nEnter LName: ");
scanf("%s",&ptr->ln);
printf("\nEnter MName: ");
scanf("%s",&ptr->mn);
printf("\nEnter BD: ");
scanf("%s",&ptr->bd);
printf("\nEnter CNum: ");
scanf("%s",&ptr->cn);
if(filepointer==NULL)
{
printf("The file does not exist.\n");
return;
}
system("cls");
fprintf(filepointer,"%15s%15s%15s%9s%11s\n",ptr->fn,ptr->ln,ptr->mn,ptr->bd,ptr->cn);
fclose(filepointer);
printf("Entries successfully written!\n");
}
struct entry
{
char fn[15];
char ln[15];
char mn[15];
char bd[9];
char cn[11];
}p;
if you want more details please do tell me.
UPDATE-
I narrowed down the problem to the while loop in the delete function my append function seems to work after using delete if the contents in the while loop were written like this:
while (ch!=EOF)
{
ch=getc(filepointer);
if(count!=tode)
{
fprintf(filepointer2,"%c",ch);
if(ch=='\n')
{
count++;
}
}
}
But if the while loop were written in this way it would delete all the entries following the specified line. whereas in my previous code for the while loop in the deletee function it only deletes that specific line, but as stated the problem of the append function not being able to write to the file will persist until I delete the file "database.data" manually.
Solved the problem turns out that the append function was able to write entries into the file the only problem is my print function couldnt print out the new entries due to the delete function leaving garbage after being executed. revised the code so that no garbage would be written after deleting.
void deletee()
{
int tode,count;
char ch,sc;
printc();
count=1;
FILE *filepointer,*filepointer2;
filepointer=fopen(file,"r+");
filepointer2=fopen("datatemp.data","w+");
if(filepointer==NULL)
{
printf("ERROR ERROR!");
}
printf("Enter line number of the line to be deleted: \n");
scanf("%d",&tode);
while (ch!=EOF)
{
ch=getc(filepointer);
if(count!=tode)
{
if(ch==EOF)
{
break;
}
fprintf(filepointer2,"%c",ch);
}
if(ch=='\n')
{
count++;
}
}
fclose(filepointer);
fclose(filepointer2);
swap();
remove("datatemp.data");
printf("Content successfully deleted!!");
}
I'm having a little trouble with the code below and I can not for the life of me figure out what went wrong and why it is displaying what it does, any help or assistance would be most appreciated. It is supposed to allow 5 lines of text to be entered and display those 5 lines onscreen, however it only allows 4 lines to be entered, and 4 are displayed. Please help!
#include <stdio.h>
int main()
{
char string[100];
char filename[20];
int n=0;
FILE *fp;
printf(" Enter the name of file to open ");
scanf("%s",filename);
fp =fopen(filename,"wr");
if(fp==NULL)
{
printf("unable to open File");
}
for(n=1;n<6;n++)
{
printf("\nEnter line %d:",n+1);
gets(string);
fputs(string,fp);
fputs("\n",fp);
}
fclose(fp); /*close the file*/
fp =fopen(filename,"r");
if(fp==NULL)
{
printf("unable to open File");
}
for(n=1;n<6;n++)
{
fgets(string,100,fp);
printf("%s",string);
}
fclose(fp); // close after reading.
return 0;
}
The problem is that scanf("%s", filename); doesn't consume the newline after the filename. So your first call to gets() reads this newline as an empty line.
Add:
gets(string);
after that line to use up the rest of the line before you start reading input lines.
Here is the modified code. Added gets instead of scanf and added return 0; if file is not opened.
#include <stdio.h>
int main()
{
char string[100];
char filename[20];
int n=0;
FILE *fp;
printf(" Enter the name of file to open ");
gets(filename);
fp =fopen(filename,"wr");
if(fp==NULL)
{
printf("unable to open File");
return 0; // do not proceed
}
for(n=1;n<6;n++)
{
printf("\nEnter line %d:",n);
gets(string);
fputs(string,fp);
fputs("\n",fp);
}
fclose(fp); /*close the file*/
fp =fopen(filename,"r");
if(fp==NULL)
{
printf("unable to open File");
return 0; // do not proceed
}
for(n=1;n<6;n++)
{
fgets(string,100,fp);
printf("%s",string);
}
fclose(fp); // close after reading.
return 0;
}
replace scanf("%s",filename) with gets(filename)
To get rid of the newline in the buffer right after your call to scanf, you can simply add getchar();:
scanf("%s", filename);
getchar();
But do adjust your for loops to start at 0, since you add 1 to n i.e:
for(n=0;n<6;n++)
^
After making those changes I was able to input 6 lines and then print all of them out.
As you've noticed, buffered input can be pesky if you don't deal with it properly as it can be inserted in your subsequent input calls. Don't be tempted to flush the stdin.
Here are some recommended alternatives on how to deal with this.
I am working on a program to write user input to a file and then search for a specific record in the file and output it to the screen.
I tried using fgets and also fputs, but I haven't been successful. Here's what I have so far.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
main ()
{
FILE *fileptr;
char id [30];
char name [47];
char amt[50];
fileptr = fopen("C:\\Users\\Andrea\\Documents\\Tester.txt", "w");
if (fileptr == NULL) {
printf("File couldn't be opened\n\a\a");
fclose(fileptr);
exit(0);
}
printf("Enter name: \n");
fscanf(fileptr, "%c", name);
fputs(name, fileptr);
fclose(fileptr);
printf("File write was successful\n");
return 0;
}
Use:
fscanf(stdin, "%s", name);
But better still, use scanf instead, as kol mentioned. This is because scanf() is designed to read the user response from the screen while fscanf() is for scanning from any input streams (which are usually files).
And the statement should be reading from the screen (stdin), not from the file (which was opened as "write" only).
Use scanf to read user input, and fprintf to write it to the file. Then use fscanf to read from the file, and printf to display what you have read. See cplusplus.com for the details and sample code.
EDIT:
Here is an example (please run the executable from the command line):
#include <stdio.h>
#include <string.h>
int main()
{
FILE *file;
int i;
char firstName[32];
char lastName[32];
int found = 0;
// Open the file for writing
file = fopen("records.txt", "wt");
if (!file)
{
printf("File could not be opened\n\a\a");
getchar();
return -1;
}
// Read and save data
for (i = 0; i < 3; ++i)
{
// Read data
printf("Record #%d\n", i + 1);
printf("Enter first name: "); scanf("%s", firstName);
printf("Enter last name: "); scanf("%s", lastName);
printf("\n");
// Save data
fprintf(file, "%s\t%s\n", firstName, lastName);
}
// Close the file
fclose(file);
// Open the file for reading
file = fopen("records.txt", "rt");
if (!file)
{
printf("File could not be opened\n\a\a");
return -1;
}
// Load and display data
i = 0;
while(!feof(file) && !found)
{
++i;
fscanf(file, "%s\t%s", firstName, lastName);
if (strcmp(firstName, "John") == 0 && strcmp(lastName, "Doe") == 0)
{
printf("Record found (#%d): %s %s\n", i, firstName, lastName);
found = 1;
}
}
if (!found)
printf("Record could not be found");
// Close the file
fclose(file);
return 0;
}