C reading values from a binary file and then print them - c

I have this code, and want that the program reads/loads the data that is on the file and them printed them, but this didn´t work.
I can´t write on the file, but can´t read it.
I want that when the program initialize, he already have loaded the info that is in the the binary file, so the user can use it, for example for searching people.
#include <stdio.h>
#include <stdlib.h>
#define MAX_PERSON 3
#define FILENAME "person.bin"
typedef struct {
int id;
char fname[20],lname[20];
}person;
typedef struct {
int counter;
person persons[MAX_PERSON];
}Persons;
int writeStruct(Persons *persons,char *file){
FILE *outfile;
outfile = fopen (file, "ab+");
if (outfile == NULL){
exit(EXIT_FAILURE);
}
printf("\nInsira a informações da pessoa \n");
printf("Código: ");
scanf("%d", &persons->persons[persons->counter].id);
printf("Primeiro Nome: ");
scanf("%s", persons->persons[persons->counter].fname);
printf("Último Nome: ");
scanf("%s", persons->persons[persons->counter].lname);
fwrite (&persons, sizeof(Persons), persons->counter, outfile);
if(fwrite != 0){
puts("Sucess on writing on file");
}else{
puts("Error on writing on file");}
fclose (outfile);
return persons->counter++;
}
void loadStruct(Persons *persons,char *file){
FILE *infile;
// Open person.bin for reading
infile = fopen(file, "rb+");
if (infile == NULL) {
fprintf(stderr, "\nError opening file\n");
exit(1);
}
// read file contents till end of file
fread(&persons, sizeof (Persons), persons->counter, infile);
// close file
fclose(infile);
}
void listPersons(Persons persons){
int i;
puts("Lista de pessoas");
puts("-----------------");
for(i=0;i < persons.counter; i++) {
printPerson(persons.persons[i]);
}
puts("-----------------");
}
void searchPeople(Persons persons) {
int number;
printf("Indique o código da pessoa que pretende procurar: ");
scanf("%d",&number);
number = searchPerson(persons,number);
if (number != -1) {
printPerson(persons.persons[number]);
} else {
puts(ERROR_PERSON_NOT_EXISTS);
}
}
int searchPerson(Persons persons,int number) {
int i;
for (i = 0; i < persons.counter; i++) {
if (persons.persons[i].id == number) {
return i;
}
}
return -1;
}
void printPerson(person person){
printf("%d - %s %s\n", person.id,person.fname, person.lname);
}
int main ()
{
int op;
Persons persons ={.counter = 0};
loadStruct(&persons,FILENAME);
do{
puts("PESSOAS - BASE DE DADOS");
puts("-----------------");
puts("2 - Inserir pessoa");
puts("3 - Listar pessoas");
puts("4 - Procurar pessoa");
puts("0 - Sair");
puts("-----------------");
printf("Nº Pessoas: %d/%d \n", persons.counter, MAX_PERSON);
printf("Opção:");
scanf("%d",&op);
printf("\n");
switch (op) {
case 0:
exit(0);
break;
case 2:
writeStruct(&persons,FILENAME);
break;
case 3:
listPersons(persons);
break;
case 4:
searchPeople(persons);
break;
default:
puts("Opção inválida!");
break;
}
}while(op!=0);
}

You're just writing one Persons structure to the file. You shouldn't use persons->counter as the number of items that you're writing or reading, as the array is entirely contained in the structure.
You also shouldn't open the file in append mode. Since you're writing the entire Persons structure, not a single person, you should open it in write mode and overwrite the whole file.
The first argument to fwrite() and fread() should be persons, not &persons, since you want to fill in the structure that it points to, not overwrite the pointer.
To make sure you don't write outside the array, you should check that persons->counter hasn't exceeded the size of the array.
int writeStruct(Persons *persons,char *file){
FILE *outfile;
if (persons->counter >= MAX_PERSON) {
puts("File is full\n");
return persons->counter;
}
outfile = fopen (file, "wb");
if (outfile == NULL){
exit(EXIT_FAILURE);
}
printf("\nInsira a informações da pessoa \n");
printf("Código: ");
scanf("%d", &persons->persons[persons->counter].id);
printf("Primeiro Nome: ");
scanf("%s", persons->persons[persons->counter].fname);
printf("Último Nome: ");
scanf("%s", persons->persons[persons->counter].lname);
fwrite (persons, sizeof(Persons), 1, outfile);
if(fwrite == 1){
puts("Success on writing on file\n");
}else{
puts("Error on writing on file\n");
}
fclose (outfile);
return persons->counter++;
}
void loadStruct(Persons *persons,char *file){
FILE *infile;
// Open person.bin for reading
infile = fopen(file, "rb");
if (infile == NULL) {
fprintf(stderr, "\nError opening file\n");
exit(1);
}
// read file contents till end of file
fread(persons, sizeof (Persons), 1, infile);
// close file
fclose(infile);
}

Related

How to create a simple function that given a word can delete the specific line that contain it in C

I'm trying to create a function that given a word in input can find and delete the line that contain it. I've done some research on internet and I wrote some code but when i launch the program only find the line but it doesn't delete the line and the old file (database.txt).
This is the function that deletes the line:
FILE *database, *database2;
char str[500];
int linea = 0, ctr = 0;
char ID[256];
database2 = fopen("database2.txt", "a");
fclose(database2);
database = fopen("database.txt", "r");
if(!database){
printf("Errore nell'apertura del file.\n");
getch();
return;
}
database2 = fopen("database2.txt", "r");
if(!database2){
printf("Errore nell'apertura del file 2.\n");
getch();
return;
}
printf("Inserisci l'ID del libro da eliminare:");
scanf("%s", &ID);
int x = FindLine(ID);
printf("%d", x);
while(!feof(database)){
strcpy(str, "\0");
fgets(str, 256, database);
if(!feof(database)){
ctr++;
if(ctr != x){
fprintf(database2, "%s", str);
}
}
}
fclose(database);
fclose(database2);
remove("database.txt");
rename("database2.txt", "database.txt");
getch();
This is the function that find the line:
FILE *fp;
int line_num = 1;
int find_result = 0;
char temp[512];
fp = fopen("database.txt", "r");
if(fp == NULL){
return(-1);
}
while(fgets(temp, 512, fp) != NULL) {
if((strstr(temp, str)) != NULL) {
return line_num;
find_result++;
}
line_num++;
}
if(find_result == 0) {
printf("\nSorry, couldn't find a match.\n");
}
if(fp) {
fclose(fp);
}
return(0);
Some can help me to find the error please.
Using feof() to check for end of file is incorrect, you should instead check the return value of fgets(). You can learn about this on this question: Why is “while ( !feof (file) )” always wrong? .
Here is a modified version:
#include <stdio.h>
#include <string.h>
int main() {
FILE *database, *database2;
char ID[256];
char str[512];
int linea, ctr;
printf("Inserisci l'ID del libro da eliminare:");
if (scanf("%255s", ID) != 1) {
printf("input error\n");
return 1;
}
database = fopen("database.txt", "r");
if (!database) {
printf("Errore nell'apertura del file database.txt.\n");
return 1;
}
ctr = linea = 0;
while (fgets(str, 512, database)) {
ctr++;
if (strstr(str, ID)) {
linea = ctr;
break;
}
}
if (linea == 0) {
printf("No matching line\n");
fclose(database);
return 1;
}
printf("linea: %d\n", linea);
database2 = fopen("database2.txt", "w");
if (!database2) {
printf("Errore nell'apertura del file database2.txt.\n");
fclose(database);
return 1;
}
rewind(database);
ctr = 0;
while (fgets(str, 512, database)) {
ctr++;
if (ctr != linea) {
fputs(str, database2);
}
}
fclose(database);
fclose(database2);
remove("database.txt");
rename("database2.txt", "database.txt");
return 0;
}

How to modifie a variable that its inside on a file on C?

I'm new in coding, tecnically i started this year to code and i need a lot of practise. Whatever, i tried to modify a variable that is in a file but the browser or CPU didnt found it. When i run the code, it can write the variables and pass it to the file and read it, but it cant modifie a variable that is inside on the file. I tried to use a while and an if but my knowledge couldnt go so far than these.
The problem is on the Delete function, it can read the file or archive but it couldnt reach the "end of file" because apparently it doesnt exist. The code principally read a punch of number and stop when you enter -1 on the scanf. The it read all the number (include -1 twice) and then it modifie the last number converting to a zero. The problem is that the last function repeated infinitely
#include<stdio.h>
void Create(FILE *p){
p=fopen("c:Example", "rb");
if(!p){
p=fopen("c:Example", "wb");
printf("El texto fue creado \n");
} else {
printf("El texto ya existe \n");
}
}
void Add(FILE *p){
int a;
p=fopen("c:Example", "ab");
if(p==NULL){
printf("El texto no se encontro \n");
} else {
scanf("%d", &a);
while(a!=-1){
fwrite(&a, sizeof(int), 1, p);
scanf("%d", &a);
}
fwrite(&a, sizeof(int), 1, p);
}
fclose(p);
}
void Read(FILE *p){
int a;
p=fopen("c:Example", "rb");
if(p==NULL){
printf("El texto no existe \n");
} else {
fread(&a, sizeof(int), 1, p);
printf("%d \n", a);
while(a!=-1){
fread(&a, sizeof(int), 1, p);
printf("%d \n", a);
}
}
fclose(p);
}
void Delete(FILE *p){
int a;
p=fopen("c:Example", "wb");
if(p==NULL){
printf("El texto no existe \n");
} else {
fread(&a, sizeof(int), 1, p);
printf("(1)\n");
while(a!=-1){
fread(&a, sizeof(int), 1, p);
printf("(2)\n");
}
a=0;
printf("(3)\n");
}
fclose(p);
}
int main(){
FILE *p;
Create(p);
printf("\n");
Add(p);
printf("\n");
Read(p);
printf("\n");
Delete(p);
printf("\n");
Read(p);
printf("\n");
return 0;
}
A solution to the problem could be reading the numbers and generate a new file with the last number, which is -1, replaced by 0. Then delete the old file and rename temporary file as the older one. I wrote a solution that works trying to not change much code of yours. I suggest you to better undestand how fread() and fwrite() functions work. After scanf function, I use getchar() function to remove new line, caused when you hit enter, from the buffer. Try also to keep your code clean with spaces and indent.
#include <stdio.h>
#include <stdlib.h>
void Create (FILE *p)
{
if((p = fopen ("c:Example", "wb")) == NULL) // Check if file opening doesn't fail
{
printf ("Can't open file\n");
exit (-1);
}
printf ("File exists\n");
fclose (p); //Close file pointer
}
void Add(FILE *p)
{
int a = 0; // Initialize variable
p = fopen("c:Example", "ab");
if (p == NULL) // File opening failed
{
printf("El texto no se encontro \n");
exit (-1); // Program has to terminate
}
else
{
while(a != -1)
{
printf ("Please insert number\n"); //Tell user what to do
scanf ("%d", &a);
getchar();
fwrite(&a, sizeof(int), 1, p);
}
}
fclose(p);
}
void Read(FILE *p)
{
int a = 0; // Initialize variable
p = fopen("c:Example", "rb");
if(p == NULL) // Error opening file
{
printf("El texto no existe \n");
exit (-1); // Program has to termimate
}
else
{
while(a != -1)
{
fread(&a, sizeof(int), 1, p);
printf("I've read %d\n", a);
}
}
fclose(p);
}
void Delete(FILE *p)
{
int a = 0;
p = fopen("c:Example", "r"); //Open for read
if(p == NULL) // Can't open file
{
printf("El texto no existe \n");
exit (-1); //Exit the program
}
else
{
FILE *temp;
if ((temp = fopen ("temp", "ab")) == NULL) //Create a temp file in append mode
{
printf ("Error creating temp file\n");
fclose (p);
exit (-1);
}
while (a != -1)
{
fread(&a, sizeof(int), 1, p);
if (a != -1)
{
fwrite (&a, sizeof(int), 1, temp); // write to temp only if is not -1
}
}
a = 0;
fwrite (&a, sizeof (int), 1, temp); //Write 0 to last position
fclose (temp);
fclose (p);
remove ("c:Example"); //Remove old file
rename ("temp", "c:Example"); //Rename new file
}
}
void Read_new (FILE * p)
{
int a = -1 // Initialize a as -1;
p = fopen ("c:Example", "rb");
while (a != 0)
{
fread (&a, sizeof (int), 1, p);
printf ("I've read %d\n", a);
}
fclose (p);
}
int main()
{
FILE *p;
Create(p);
Add(p);
Read(p);
Delete(p);
Read_new(p);
return 0;
}

fread can't read an object from file

Task is to read a map from a file and then display it. The binary file begins with 2 floats and continues with objects of this format:
struct Node {
float height;
int terrainType;
float visitsCount;
struct Node *next;
}Node;
And the function doing the reading:
void showMapTerrain(struct Node Node)
{
FILE *fp;
if ((fp = fopen("map.bin", "rb")) == NULL) {
puts("Unable to open file.");
exit(7);
}
float mapLenght, alt;
if (fread(&mapLenght, sizeof(float), 1, fp) != 1) {
puts("Unable to read from file.");
exit(18);
}
if (fread(&alt, sizeof(float), 1, fp) != 1) {
puts("Unable to read from file.");
exit(20);
}
/*Idea with this is to get the 2 floats out of the way so I can start reading the objects with a single fread.*/
char *mapTerrain = (char *)calloc(mapLenght, sizeof(char));
while (1) {
if (fread(&Node, sizeof(struct Node), 1, fp) != 1) {
//But this bit right here fails, it reads 0 objects.
printf("fread: %d\n", fread(&Node, sizeof(struct Node), 1, fp));
puts("Unable to read from file.");
exit(30);
}
*mapTerrain = Node.terrainType;
}
puts("Terrain type map: ");
while (*mapTerrain) {
printf("[%c]", *mapTerrain);
}
free(mapTerrain);
}
The 2 floats are only in the beginning, so they're outside the loop, that reads objects. I'm pretty sure the syntax for the fread is correct, it's unclear to me what the problem is.
Also, it's not required to make a linked list in this function, we're creating an array of numbers (ranging 1-4, hence char*) and then displaying it.
Edit: the function doing the writing:
void addToFile(struct Node Node)
{
FILE *fp;
float mapLenght, alt;
if ((fp = fopen("map.bin", "rb")) == NULL) {
if ((fp = fopen("map.bin", "wb")) == NULL) {
//2 fopens to check if the file exists. If it doesn't, the user has to input the //2 floats in the beginning. Otherwise we skip straight to adding objects in the //file
puts("Unable to open the file.");
exit(7);
}
puts("How long is the map?");
scanf("%f", &mapLenght);
if (fwrite(&mapLenght, sizeof(float), 1, fp) != 1) {
puts("Unable to write to file.");
exit(6);
}
puts("What's the map's altitude?");
scanf("%f", &alt);
if (fwrite(&alt, sizeof(float), 1, fp) != 1) {
puts("Unable to write to file.");
}
fclose(fp);
}
else {
fclose(fp);
}
if ((fp = fopen("map.bin", "ab")) == NULL){
puts("Unable to open file for further writing.");
exit(7);
}
int c = 0;
while (1) {
puts("Inputting data for individual square meters of the map:");
printf("How high is square meter %d?", ++c);
puts("('-1' to stop.)");
scanf("%f", &Node.height);
if (Node.height == -1) {
system("cls");
puts("You've decided to stop adding data.");
break;
}
printf("What's the terrain type of square meter %d?\n", c);
puts("Values allowed: ");
puts("0 - flora");
puts("1 - waste");
puts("2 - water");
puts("3 - road");
puts("4 - building");
Node.terrainType = 7;
while (1) {
scanf("%d", &Node.terrainType);
if (Node.terrainType < 0 || Node.terrainType>4) {
puts("Invalid data.");
}
else {
break;
}
}
printf("What's the daily visit count for square meter %d?", c);
scanf("%f", &Node.visitsCount);
if (fwrite(&Node, sizeof(Node), 1, fp) != 1) {
//Unlike the other function, everything here works properly, even this fwrite
puts("Error writing data to file.");
exit(6);
}
}
}
My apologies, but I made a very dumb mistake. fread was reading objects just fine, it returned 0 when it got to EOF. I assumed it returned 0 on the first iteration. Fix is bellow:
int *mapTerrain = (int *)calloc(mapLenght, sizeof(int));
int i = 0;
while (1) {
if (fread(&Node, sizeof(struct Node), 1, fp) != 1) {
break;
}
mapTerrain[i] = Node.terrainType;
i++;
}
puts("Map by terrain type: ");
int n;
for (n = 0; n < i; n++) {
printf("[%d]", mapTerrain[n]);
}
puts("");
free(mapTerrain);

Console app menu not working in C

guys! So I have an assignment to create a structure that includes variables based on what information I need to store and to bring out a menu that calls different functions and does different things. The problems is that for some reason my createFile function is not working at all and I've been looking for errors for 2 days and I simply cannot spot where this is coming from.
Ignore the changeStud funcion as I'm still working on it. I simply want to create my file when I enter the name for it and then chose the nnumber of the function. (in my case > enter filename> enter 1> it just loops the menu function and it should create a file)
#define _CRT_SECURE_NO_WARNINGS
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Student {
char ime[50];
char fn[10];
int ocfiz, ocmat, ocpro;
};
char filename[20];
FILE *fd;
Student ps;
void createFile() {
fd = fopen(filename, "wb");
fclose(fd);
printf("File created!\n");
}
void readStud(Student *s) {
printf("Enter data for new student");
getchar();
printf("Enter student name:");
gets_s(s->ime);
printf("\nEnter FN:");
scanf_s("%s", s->fn);
printf("\nEnter marks for Maths, Programming, Physics");
scanf_s("%d %d %d", &s->ocmat, &s->ocpro, &s->ocfiz);
getchar();
}
void addStud() {
fd = fopen(filename, "a+b");
char c;
do {
readStud(&ps);
fwrite(&ps, sizeof(ps), 1, fd);
printf("More Students? (y/n) : ");
c = getchar(); getchar();
} while (c == 'y');
fclose(fd);
}
void writeAllStud() {
fd = fopen(filename, "rb");
printf("students in file\n");
fread(&ps, sizeof(ps), 1, fd);
while (!feof(fd)) {
printf("%s fn: %s ocmat: %d ocpro: %d ocfiz: %d", ps.ime, ps.fn, ps.ocmat, ps.ocpro, ps.ocfiz);
fread(&ps, sizeof(ps), 1, fd);
}
fclose(fd);
}/*
void changeStud() {
char fn2[50];
printf("enter FN:");
gets_s(fn2);
fd = fopen(filename, "r+b");
fread(&ps, sizeof(ps), 1, fd);
while (!feof(fd)) {
if (strcmp(ps.fn, fn2)==0) {
fseek(fd, -(long) sizeof(ps), SEEK_CUR);
fwrite(&ps, sizeof(ps, 1, fd));
break;
}
}
}*/
void Avg() {
}
void exportData() {
FILE *txt;
txt = fopen("students.txt", "wt");
fd = fopen(filename, "rb");
fread(&ps, sizeof(ps), 1, fd);
while (!feof(fd)) {
fprintf(txt, "%s %s marks fiz%d mat%d prog%d\n", ps.fn, ps.ime, ps.ocfiz, ps.ocmat, ps.ocpro);
fread(&ps, sizeof(ps), 1, fd);
}
fclose(fd);
fclose(txt);
printf("students have been written to a text file.\n");
}
void main() {
printf("Enter file name:");
gets_s(filename);
int c;
do {
printf("\nMenu:\n");
printf("0 Exit\n");
printf("1 Create file\n");
printf("2 Add new student data\n");
printf("3 Change data from FN\n");
printf("4 AVG marks for maths, programming, physics\n");
printf("5 export all AVG marks to .txt file\n");
scanf("%d", &c);
switch (c) {
case 1: createFile; break;
case 2: addStud; break;
//case 3: changeStud; break;
case 4: Avg; break;
case 5: exportData; break;
}
} while (c != 0);
}
i think you should use your struct variable like this:
struct Student {
char ime[50];
char fn[10];
int ocfiz, ocmat, ocpro;
}ps;
or use
struct Student ps;
instead of just student ps,or you can decleare it in main function..And passing a struct in a functin is
void readStud( struct Student *s)() {
//your code...
}

C - Read/write int variable in .txt

I'm starting to learn C, and currently programming a little text-based lottery-like game. But I need a way to store the value in the end of the game, so it can be kept for the next plays. I made a simpler code below that represents what I need. Please help.
#include <stdio.h>
int main() {
//TODO get "int saved" from save.txt
printf("Value saved: %d\n", saved);
printf("Add: ");
int add;
scanf("%d", &add);
int new = saved+add;
printf("New value: %d\n", new);
//TODO save "int new" to save.txt
}
save.txt:
100
Try this
FILE *file;
int saved;
int add;
file = fopen("saved.txt", "r");
if (file == NULL)
{
fprintf(stderr, "error opening `saved.txt'\n");
return -1;
}
if (fscanf(file, "%d", &saved) != 1)
{
fprintf(stderr, "file `saved.txt' corrupted\n");
fclose(file);
return -1;
}
fprintf(stdout, "please input an integer > ");
if (scanf("%d", &add) != 1)
{
fprintf(stderr, "invalid input\n");
fclose(file);
return -1;
}
fclose(file);
file = fopen("saved.txt", "w");
if (file != NULL)
{
fprintf(file, "%d\n", saved + add);
fclose(file);
}

Resources