Block reading and writing using fread and fwrite in C - 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.

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

How to count number of line from binary file for C programming

typedef struct {
int ID;
char name[30];
char position[20];
char department[20];
char password[10];
int contactnumber;
int age;
char emailaddress[30];
}admin;
admin info;
void registration() {
int count=1001,y;
FILE* Admin;
Admin = fopen("Admin_info.bin", "ab");
if (Admin == NULL) {
printf("Unable to open file");
}
printf("\tPlease insert your informantion below\n");
printf("\tID: ");
scanf("%d", &info.ID);
printf("\n\tName: ");
scanf("%s", &info.name);
printf("\tPosition: ");
rewind(stdin);
scanf("%s", &info.position);
printf("\tDepartment: ");
scanf("%s", &info.department);
printf("\tPassword: ");
scanf("%s", &info.password);
printf("\tContact Number: ");
scanf("%s", &info.contactnumber);
printf("\tAge: ");
scanf("%d", &info.age);
printf("\tEmail Address: ");
scanf("%s", &info.emailaddress);
fwrite(&info, sizeof(admin), 1, Admin);
}
*I wanted to auto generate the ID. Therefore, I need to read the number of line from binary file and add by 1 and I don't know how to read the number of line. Please someone help me
You should've mentioned that it's about the file you are writing to. And there are no actual lines, since you are writing binary data to it.
You could first open the file in rb mode, fseek with 0, SEEK_END, ftell to get the file size in bytes, close it again, then divide the file size by sizeof(admin) to get your ID. Then apply your code.
EDIT after comment by chux:
It is not necessary to first open the file in rb mode and close it, as I had suggested. It is sufficient to leave it open in ab mode as done in your code and just add the fseek and ftell. Depending on the system, even the fseek is not required, but this seems not to be guaranteed by the standard.
I just found a very much related question here: Problems getting ftell() in binary append

Reading integer to a text file in C (integer is present in a structure)

I have declared a structure that has both integer and string type variables. I am able to scan the data and print it without issues. But when I try to write the structure to the file it only reads the strings and I don't understand why.
Here's the structure:
struct employee_details
{
char name[45];
int id;
char designation[30];
long long int phone_number;
char address[75];
}employee;
Here's the function used to get structure input:
void get_employee_details()
{
printf("\nName: ");
scanf("%s", employee.name);
printf("ID: ");
scanf("%d", &employee.id);
printf("Designation: ");
scanf("%s", employee.designation);
printf("Phone Number: ");
scanf("%lld", &employee.phone_number);
printf("Address: ");
scanf("%s", employee.address);
}
Here's the function to write this data in the file:
void add_employee(int is_first_record, int to_append)
{
FILE* p_wfile;
if (to_append == 0)
{
if (is_first_record == 1)
p_wfile = fopen("Record.txt", "w");
else
p_wfile = fopen("Record.txt", "a");
}
else
p_wfile = fopen("Record.txt", "a");
if (p_wfile == NULL)
{
printf("Can't open file.");
exit(1);
}
printf("\nADD EMPLOYEE's DETAILS\n");
get_employee_details();
fwrite(&employee, sizeof(struct employee_details), 1, p_wfile);
if (fwrite == 0)
printf("Error writing to file!\n");
fclose(p_wfile);
}
I have a loop in main() to repeat the writing process until the user wants to but no matter how many structures I input, only the characters get written.
What should I do? Is it somehow related to me using scanf() instead of the better functions?
I guess you are trying to read the file using a text editor.
Issue is with fwrite:
"fwrite" will write the numbers without converting it to ASCII or utf-8 chars hence numbers won't be found when opened via file editor. Instead, you will find a characters equivalent of the numbers stored. Try reading the file using "fread" you will get the actual values back into the "employee_details" structure.
Incase you want to read the data via file editor: use fprint
Try something Like:
fprintf(p_wfile , "%s %d\n", employee.name, employee.id);

File read write not working with multiple datatypes

I have a program in C language in which I want to store multiple dataype values in a file and read the same from the file. The following code writes data into file but stores the data in unreadable form. Also when I fetch that data, I get garbage values.
I am using Codeblocks 17.x
#include <stdio.h>
#include <stdlib.h>
struct student
{
char name[100];
int maths, hindi;
char gend;
};
int main()
{
struct student num[3];
struct student num1;
int i;
FILE *fptr;
if ((fptr = fopen("studlist.txt","w")) == NULL){
printf("Error! opening file");
exit(1);
}
for(i=0; i<=2; i++)
{
printf("Enter your name: ");
gets(num[i].name);
printf("Enter Marks in Maths: ");
scanf("%d", &num[i].maths);
printf("Enter Marks in Hindi: ");
scanf("%d", &num[i].hindi);
printf("Enter Gender (M/F) ");
fflush(stdin);
num[i].gend=getchar();
fflush(stdin);
fputs("Student ", fptr);
putw(i, fptr);
fwrite(&num[i], sizeof(struct student), 1, fptr);
fputs("\n",fptr);
}
fclose(fptr);
if ((fptr = fopen("studlist.txt","r")) == NULL){
printf("Error! opening file");
exit(1);
}
for(i=0; i<=2; i++)
{
printf("Student %d: ",i);
fread(&num1, sizeof(struct student), 1, fptr);
printf("%s | Maths: %d\tHindi: %d\tGender: %c\n", num1.name, num1.maths, num1.hindi, num1.gend);
}
fclose(fptr);
return 0;
}
Data stored in the file:
Data shown as a result of read operation:
Also, I am not able to implement the search and update code. For example, if I want to update the marks of Jenny, I am not able to do it.
Please help.
The problem is that your writing and reading are asymmetrical.
You write each student record like this:
fputs("Student ", fptr); /**/
putw(i, fptr); /**/
fwrite(&num[i], sizeof(struct student), 1, fptr);
fputs("\n",fptr); /**/
and then you read each student record like this:
fread(&num1, sizeof(struct student), 1, fptr);
Just get rid of the extra writes (the lines I marked with asterisks) and it should work.

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

Resources