Facing problem to write in file using fputs() [duplicate] - c

This question already has answers here:
scanf() leaves the newline character in the buffer
(7 answers)
fgets doesn't work after scanf [duplicate]
(7 answers)
Closed last month.
#include <stdio.h>
int main(){
FILE *fp;
char name[25];
int i;
float cgpa;
fp = fopen("FileExercise.txt", "w");
if(fp==NULL) printf("File doesn't exist.\n");
else{
printf("File has opened.\n");
for(i=0; i<5; i++){
printf("Enter roll-%d student name: ", i+1);
gets(name);
fputs(name, fp);
fprintf(fp, "\t%d", i+1);
printf("Enter students cgpa: ");
scanf("%f", &cgpa);
fprintf(fp, "\t%0.2f", cgpa);
fprintf(fp, "\n");
}
printf("File has written successfully.\n");
}
return 0;
}
I was trying to to make a file of students. That includes students name, roll & cgpa. For the 1st students it was working. But from the second student I can't take student name as input also can't write student name in file. Now, What should I do?

Related

How to write inputs into a binary file and read it in c?

Recently I am working on a beginner projects. But I was stuck for days without knowing how to update a file. Then I found I can do it with binary files, so I started using binary files instead of normal files. But now when I write into binary files it works (I assume), but when I read from it, it gives me segmentation fault (core dumped).
Here is my structs
struct date{ // structure for dates
int mm, dd, yyyy;
};
struct {
char *initials, *name, *email, *acc_type; // unchangeable values
char id_num[11], occupation[25], address[100]; // changeable values
int phone, acc_num, balance;
struct date birth_day; // structure for birth day
} new_acc;
Here is my writing function...
void create_new(void)
{
// Allocating memory for each member in struct
new_acc.name = (char *) malloc(sizeof(new_acc.name));
new_acc.initials = (char *) malloc(sizeof(new_acc.initials));
new_acc.email = (char *) malloc(sizeof(new_acc.email));
new_acc.acc_type = (char *) malloc(sizeof(new_acc.acc_type));
system("clear");
puts("Answer the questions to make a account");
time_t l; // To generate a number
srand((unsigned) time(&l)); // Generating a random number to account number
new_acc.acc_num = l; // Assign l value to acc_num var in struct
printf("Enter your full name: ");
scanf(" %100[^\n]", new_acc.name); // scan for name, 100 characters, and also accepting spaces
printf("Enter your name with initials: ");
scanf(" %100[^\n]", new_acc.initials);
printf("Enter your birthday (mm/dd/yyyy): ");
scanf(" %d %d %d", &new_acc.birth_day.mm, &new_acc.birth_day.dd, &new_acc.birth_day.yyyy)
printf("Enter your address: ");
scanf(" %100[^\n]", new_acc.address);
printf("Enter your phone number: ");
scanf(" %10d", &new_acc.phone);
printf("Enter your id number: ");
scanf(" %10[0-9a-zA-Z]", new_acc.id_num);
printf("Enter your occupation: ");
scanf(" %50[^\n]", new_acc.occupation);
printf("Enter your email address:");
scanf(" %s", new_acc.email);
printf("Enter the account type:\n");
printf("\t#Saving\n\tFixed (1 year)\n\tFixed (2 year)\n\tFixed (3 year)\n");
scanf(" %20s", new_acc.acc_type);
printf("Enter amount to deposite: $");
scanf(" %d", &new_acc.balance);
FILE *fp;
fp = fopen("employees", "a"); // Opening file in append mode
if (fp == NULL) // If file couldn't open
puts("Cannot open a file...");
// Here, I also used while loop, but I don't know how to break it so I used for loop
for (int i = 0; i <= 12; ++i) // Looping 12 times
fwrite(&new_acc, sizeof(new_acc), 1, fp); // writting to file
fclose(fp); // Closing file
// freeing memory after use
free(new_acc.name);
free(new_acc.initials);
free(new_acc.email);
free(new_acc.acc_type);
int out;
printf("Successfully created a account!\nYour account number is %d\n", new_acc.acc_num);
printf("Press 1 to exit, and 0 to go to main menu...");
scanf("%d", &out);
switch (out){
case 1:
exit(0);
break;
case 0:
menu();
break;
}
}
And here my reading coding snippet also
FILE *fp;
fp = fopen("employees", "r");
if (fp == NULL)
puts("Cannot open a file...");
for (int i = 0; i <= 12; ++i)
fread(&new_acc, sizeof(new_acc), 1, fp);
fclose(fp);
printf("%d\n", new_acc.acc_num); // It only prints acc_num
// After that it gives me segmentation fault
printf("%s\n", new_acc.name);
printf("%s\n", new_acc.initials);
printf("%s\n", new_acc.birth_day);
printf("%s\n", new_acc.address);
printf("%d\n", new_acc.phone);
printf("%s\n", new_acc.id_num);
printf("%s\n", new_acc.occupation);
printf("%s\n", new_acc.email);
printf("%s\n", new_acc.acc_type);
printf("%d\n", new_acc.balance);
All I don't sure correct is writing and reading bin file...
I was wrong at writing into bin file and also reading from it.
First of all I need to thank to #lulle.
As he mentioned in comments I changed char* in struct into char arrays.
char initials[80], name[250], email[100], acc_type[25];
And I also change file mode. I use ab to writing snippet. And rb in reading snippet.
And I changed my writing snippet.
Here I looped over 12 times, this wrote every record 12 time. Sad ah?
This happened because I used just address of struct &new_acc in fwrite. If you use just address of a struct in fwrite`` or fread``` it will write your whole struct. That's what happened to me. I wrote the whole struct 12 time.
for (int i = 0; i <= 12; ++i) // Looping 12 times
fwrite(&new_acc, sizeof(new_acc), 1, fp); // writting to file
So instead of looping I changed it into this
fwrite(&new_acc, sizeof(new_acc), 1, fp); \\ This line will write whole struct
But if you want to use members of struct instead of a whole struct, you are free to use a loop. Here is a example. This example is same as above one. But remember to use i or any variable that you used in for loop when writing to file. Instead of i, if you used member name, It will also write 12 times (or as far as you are looping...)
for (int i = 0; i <= 12; ++i) // Looping 12 times
fwrite(&new_acc.[i], sizeof(new_acc.[i]), 1, fp); // writting to file
And the same thing happened to reading part (I guess...).
So I changed the code snippet like below
FILE *fp;
fp = fopen("employees", "rb");
if (fp == NULL)
puts("Cannot open a file...");
int i = 0;
while(fread(&new_acc, sizeof(new_acc), 1, fp) != 0){ /* use fread one time */
printf("%d\n", new_acc.acc_num);
printf("%s\n", new_acc.name);
printf("%s\n", new_acc.initials);
printf("%s\n", new_acc.birth_day);
printf("%s\n", new_acc.address);
printf("%d\n", new_acc.phone);
printf("%s\n", new_acc.id_num);
printf("%s\n", new_acc.occupation);
printf("%s\n", new_acc.email);
printf("%s\n", new_acc.acc_type);
printf("%d\n", new_acc.balance);
++i;
}
fclose(fp);

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 &).

Problem with scanf/gets in C file handling [duplicate]

This question already has answers here:
scanf() leaves the newline character in the buffer
(7 answers)
Closed 2 years ago.
Whenever I run this code, final scanf function to get 'email' input does not execute and I get 'Updated successfully!' message directly! I tried using gets() instead of scanf and I'm getting the same problem. Can someone please explain the problem to me?
The Image of the Output
#include <stdio.h>
#include <stdlib.h>
typedef struct Directory
{
char name[20], email[20];
long int phone;
}Directory;
void add()
{
Directory d;
FILE *file;
file = fopen("phonebook.bin", "ab");
if(!file)
printf("Failed to open file!");
else
{
printf("Enter the name: ");
scanf("%[^\n]", &d.name);
printf("Enter the Phone Number: ");
scanf("%ld", &d.phone);
printf("Enter the e-mail ID: ");
scanf("%[^\n]", &d.email);
if(fwrite(&d, sizeof(Directory), 1, file))
printf("Updated successfully!");
else
printf("Something went wrong, Please try again!");
}
fclose(file);
}
int main()
{
add();
}
There are multiple problems in your code.
Correct format for char array is '%s'. I really don't know what is '%[^\n]'.
You get memory corruption for sending the address of the char array in scanf(). The name of the array is actually a const pointer to the start of the array.
For example :
char a[10]; // a is somewhat equivalent to &a[0].
In your example scanf() needs an address for its second argument and the name of the array already is an address; an address to the first element of the array.
Your code should look like this:
void add()
{
Directory d;
FILE* file;
file = fopen("phonebook.bin", "ab");
if (!file)
printf("Failed to open file!");
else
{
printf("Enter the name: ");
scanf("%s", d.name); // ---> notice the %s format and the missing &
printf("Enter the Phone Number: ");
scanf("%ld", &d.phone);
printf("Enter the e-mail ID: ");
scanf("%s", d.email); // ---> same here
if (fwrite(&d, sizeof(Directory), 1, file))
printf("Updated successfully!");
else
printf("Something went wrong, Please try again!");
}
fclose(file);
}
By doing &d.email in scanf you will crash or get undefined behavior.
Please put in some effort in research before posting.

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.

Why is the last string in the file is printed twice on the screen while retrieving the data? [duplicate]

This question already has answers here:
Why is “while( !feof(file) )” always wrong?
(5 answers)
Closed 7 years ago.
I have written the following C code to write five names to a text file and print the same on the monitor. While reading the data from the file, the last string is printed twice on the screen..But why..
#include<stdio.h>
#include<conio.h>
void main()
{
FILE *fp1, *fp2, *fp3;
char name[10];
int n,c;
clrscr();
printf("How many names..\n");
scanf("%d", &n);
fp1 = fopen("source.txt", "w");
while( n > 0 )
{
fflush(stdin);
printf("Enter the name\n");
gets(name);
fprintf(fp1,"%s\n", name);
n--;
}
fclose(fp1);
fp1 = fopen("source.txt", "r");
printf(" You entered the following names\n");
while( !feof(fp1) )
{
fscanf(fp1, "%s", name);
printf("%s\t", name);
}
getch();
}
Because you didn't read manual for feof.
The C version feof didn't automatically return true when you are at the end of file. It will return true after you attempt reading something only to find no more data to read.
Other language's "feof" may be a little easier to use. For example, Perl's eof will return 1 if the next read on FILEHANDLE will return end of file ...

Resources