fread and fwrite in C - c

I'm trying to make a program that creates and reads a binary file, which contains "struct elements"; can you please tell me what I did wrong?
I got errors telling me that "s" is not a pointer in function fread()... so I declared ELEM *s; instead of ELEM s;
#include <stdio.h>
#include <stdlib.h>
typedef struct element{
char name[80];
int p;
}ELEM;
void create()
{
FILE *f;
int d=0;
char c;
ELEM *s;
f=fopen("file.bin","wb");
do{
printf("Add elements to file?: (y/n)");
fflush(stdin);
scanf("%c",&c);
if (c=='y')
{
printf("Name=");
gets((*s).name);
printf("P=");
scanf("%d",(*s).p);
fwrite(s,sizeof(ELEM),1,f);
}
} while(d==0);
fclose(f);
}
void show()
{
FILE *f;
ELEM *s;
f=fopen("file.bin","rb");
while(feof(f)!=NULL)
{
fread(s,sizeof(ELEM),1,f);
puts((*s).name);
printf("\t%d\n",(*s).p);
}
fclose(f);
}
void add()
{
FILE *f;
int d=0;
char c;
ELEM *s;
f=fopen("file.bin","ab");
do{
printf("Add elements to file?: (y/n)");
fflush(stdin);
scanf("%c",&c);
if (c=='y')
{
printf("Name=");
gets((*s).name);
printf("P=");
scanf("%d",(*s).p);
fwrite(s,sizeof(ELEM),1,f);
}
} while(d==0);
fclose(f);
}
/*void function()
{
}*/
int main()
{
int k=0,r;
do{
printf("1 - create file\n2 - add elements to fil\n3 - show elements\n4 - put unique elements in another file\n5 - exit program\n");
scanf("%d",&r);
switch(r)
{
case 1 : create(); break;
case 2 : add(); break;
case 3 : show(); break;
case 4 : printf("Function not defined!\n"); break;
case 5 : k=1; break;
default : printf("Command unrecognized!\n");
}
} while(k==0);
return 0;
}

You declared a pointer but assigned no memory to it. You should revert to a normal variable:
ELEM s;
/* ... */
fwrite(&s,sizeof(ELEM),1,f);
^
Alternatively, in your current code you should do this:
ELEM *s = calloc(1, sizeof *s);

The first parameter passed to fwrite should be an address, and the variable whose address you pass must have enough memory to hold the number of objects you plan to read.
So there are two ways:
Creating Variable on Stack:
You allocate the variable on stack and pass its address to fwrite
ELEM s;
fwrite(&s,sizeof(ELEM),1,f);
or
Dynamic Memory allocation:
ELEM *s;
Should be allocated an memory equivalent to hold no of objects of type ELEM that you want to read.
ELEM *s = malloc(sizeof *s);
In this case remember to free the memory once done with your use:
free(s);

You are not allocating the pointer s in your create function. You probably want something like
s = malloc(sizeof(*s));
memset (s, 0, sizeof(*s));
etc.
And you really should learn to compiler with gcc -Wall -g and to use the gdb debugger.
Also, take time to read a good book about programming in C.

Well, your problems is in the scanf. scanf should get a pointer, so change (*s).p to &(*s).p (or even &s->p)

You should have allocated the pointer to struct ELEM
Assuming this is C:
ELEM *s = malloc(sizeof(ELEM));
If it is C++ just add a cast in front
ELEM *s = (ELEM*) malloc(sizeof(ELEM));

Related

Simple stack program not accepting input and crashing

I am learning stacks right now and I decided to try to make a little program involving the stack from Magic the Gathering rules, which also follows a LIFO order.
The user asked whether they would like to
play a spell (push)
resolve a spell (pop) or
exit.
Now the tricky part is that I am trying to allow the elements of the stack to be multiple words each. This has been causing A LOT of problems.
I can input a word and print it outside the while(1) loop but if I put it inside everything goes haywire. Any ideas?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 100
typedef struct {
char item[SIZE];
int top;
} stack;
void init(stack*);
void push(stack*, char[]);
char pop(stack*);
void init(stack* st) {
st->top = -1;
}
void push(stack* st, char* value) {
if (st->top == SIZE - 1) {
printf("STACK OVERFLOW\n");
return;
}
st->top++;
strcpy(st->item[st->top], value);
}
char pop(stack* st) {
if (st->top == -1) {
printf("STACK UNDERFLOW\n");
return -1;
}
char value;
strcpy(value, st->item[st->top]);
st->top--;
return value;
}
int main() {
stack st1, st2;
int choice;
char val[20];
init(&st1);
init(&st2);
printf("You have priority. What would you like to do?\n\n");
printf("1. Cast a spell\n2. Resolve the next spell\n3. Pass priority\n\n");
while (1) {
scanf("%d", &choice);
switch (choice) {
case 1:
printf("What is the spell?\n\n");
scanf("%[^\n]s", val);
printf("%s", val);
push(&st1, val);
case 2:
strcpy(val, pop(&st1));
printf("%s resolves.\n\n", val);
case 3:
exit(0);
}
}
return 0;
}
The reason you would be getting errors is that because of the type conversions.
char pop(stack* st) {
if (st->top == -1) {
printf("STACK UNDERFLOW\n");
return -1;
}
char value;
strcpy(value, st->item[st->top]);
st->top--;
return value;
}
The first thing, you don't need to pass the address when dealing with the arrays. The another thing is that you are trying to copy a whole string into a single character variable. So, there are so much type conversion problems in your code.
I suggest you to make the functions of void data type and provide the functionality within the block of the function. Just call the pop function with top value as an argument, and print the string within the function that you are popping.
Stack is a zero order data structure so it doesn't require inputs for popping purpose.

Why am I getting garbage value after displaying the data

I am getting garbage value when I display the records.
I have to create a database of students in C using array of structures and without pointers.
Is there any other way of doing this?
How to use array of structures?
#include <stdio.h>
struct student {
char first_name[10],last_name[10];
int roll;
char address[20];
float marks;
};
void accept(struct student);
void display(struct student);
void main() {
struct student S[10];
int n, i;
printf("Enter the number of records to enter : ");
scanf("%d", &n);
for (i = 0; i < n; i++) {
accept(S[i]);
}
for (i = 0; i < n; i++) {
display(S[i]);
}
}
void accept(struct student S) {
scanf("%s", S.first_name);
scanf("%s", S.last_name);
scanf("%d", &S.roll);
scanf("%s", S.address);
scanf("%f", &S.marks);
}
void display(struct student S) {
printf("\n%s", S.first_name);
printf("\n%s", S.last_name);
printf("\n%d", S.roll);
printf("\n%s", S.address);
}
Everything in C is pass-by-value. Which means you are modifying variable copy in stack frame, while real variable passed as parameter remains untouched.
You have to pass an pointer to variable which you want to modify in function.
// Function declaration
void accept(struct student *);
// Call
accept(&S[i]);
// Usage in function via dereference operator
scanf("%s",S->first_name);
If you would like to enter unknown amount of records, you should use VLA (since c99) or dynamically allocate structures.
VLA
scanf("%d",&n);
struct student S[n];
Dynamic callocation
scanf("%d",&n);
struct student * S = malloc(sizeof(struct student) * n);
Because in your case, if user input more that 9 records you are touching outside of bounds, which has undefined behavior.
There are multiple issues in your code:
The standard prototype for main without arguments is int main(void)
You should allocate the array dynamically with calloc.
you should pass structure pointers to the accept and display functions instead of passing structures by value. Passing the destination structure by value is incorrect as the accept function cannot modify the structure in the main function, which remains uninitialized and causes garbage to be displayed. Note that it is actually undefined behavior to access uninitialized data so the program could behave in even worse ways.
You should provide scanf() with the maximum number of arguments to store into character arrays to avoid potential buffer overflows.
you should verify the return values of scanf() to avoid undefined behavior on invalid input.
you could use the %[^\n] scan set to allow embedded spaces in the address field.
Here is a modified version:
#include <stdio.h>
#include <stdlib.h>
struct student {
char first_name[10], last_name[10];
int roll;
char address[20];
float marks;
};
void accept(struct student *sp);
void display(const struct student *sp);
int main(void) {
struct student *S;
int n, i, j;
printf("Enter the number of records to enter : ");
if (scanf("%d", &n) != 1)
return 1;
S = calloc(sizeof(*S), n);
if (S == NULL) {
return 1;
}
for (i = 0; i < n; i++) {
accept(&S[i]);
}
for (i = 0; i < n; i++) {
display(&S[i]);
}
free(S);
return 0;
}
void accept(struct student *sp) {
if (scanf("%9s%9s&d %19[^\n]%f",
sp->first_name, sp->last_name, &sp->roll,
sp->address, &sp->marks) != 5) {
printf("missing input\n");
exit(1);
}
}
void display(const struct student *sp) {
printf("%s\n", sp->first_name);
printf("%s\n", sp->last_name);
printf("%d\n", sp->roll);
printf("%s\n", sp->address);
printf("%f\n", sp->marks);
printf("\n");
}

Dynamic Alocation in c not working

I'm getting exit(1)(if there's some error in the allocation) every time i try to run the case 1. And i have no ideia why, can i get some help ?
#include <stdio.h>
#include <stdlib.h>
typedef struct hospede{ //guest
int numreg; //register num
char nome[80];
int acompanhante; //n of ppl
int dias; //time to stay
estado tabela;
}hospede;
typedef struct quarto{ //room
int num; //num do quarto
char categoria; //[S] ou [F]
char status; //[L] ou [O]
estado stats;
}quarto;
void alocaHospede(hospede **hosp, int tam);
void alocaQuartos(quarto **quar, int tam);
void geraQuartos(quarto *quar);
void checkIn(hospede *hosp, int tam);
int main()
{
hospede *hpd = NULL;
quarto *qrt = NULL;
quarto quart;
int qtd = 0;
char op;
int x;
qrt = &quart;
geraQuartos(qrt);
do{
printf("\n1-CheckIn\n>");
scanf("%i", &x);
fflush(stdin);
switch(x){
case 1:
alocaHospede(&hpd, qtd+1);
checkIn(hpd, qtd);
}
printf("\nDeseja continuar? \n");
scanf("%c", &op);
fflush(stdin);
}while(op!='n' && op!='N');
return 0;
}
void checkIn(hospede *hosp, int tam){
printf("\nwork\n");
}//checkIn
void alocaHospede(hospede **hosp, int tam){
*hosp = (hospede*)realloc(*hosp, tam*sizeof(hospede));
if(*hosp == NULL)
exit(1);
}//aloca hospede
void alocaQuartos(quarto **quar, int tam){
if((*quar = (quarto *) realloc(*quar, tam * sizeof(quarto)))== NULL)
exit(1);
}//alocaQuartos
void geraQuartos(quarto *quar){
int i;
for(i=0;i<15;i++,quar++){
(*quar).num = i+1;
}
}//geraQuartos
OBS:
I Removed some structures and unions that aren't being used yet to make the code shorter, also i'll do the allocation to the rooms as well, i think it's the same problem.
The for loop in geraQuartos is treating its argument as a pointer to an array of 15 quartos structures. But it's a pointer to just one structure, so it's writing outside the bounds of the object. This is causing undefined behavior, and in this case it's overwriting hpd so it's not NULL. This then causes realloc to fail because the first argument isn't NULL or a pointer that was previously returned by malloc.
Change the declaration of quart to:
quarto quart[15];
and then do:
geraQuartos(quart);
geraQuartos(qrt) causes stack overflow since quart is only 1-entry-lengthed but you writes 1st ~ 15th entries inside the function.
Anything strange could happen on stack overflow.

Program with array of structs crashes

I have an array with multiple structs. When i ask the user to enter data the first time everything works but when i ask again for the next position in the array the program crashes. If this method doesn't work souldn't the program crash in the beginning? Is something wrong with malloc?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct student {
char name[50];
int semester;
};
struct prof {
char name[50];
char course[50];
};
struct student_or_prof {
int flag;
int size;
int head;
union {
struct student student;
struct prof prof;
}
}exp1;
struct student_or_prof *stack;
void init(int n)
{
stack = malloc(n);
}
int push(struct student_or_prof **pinx,int *head,int n)
{
char name[50];
printf("\nn= %d\n",n);
printf("\nhead= %d\n",*head);
if(*head==n)
{
printf("Stack is full.\n");
return 1;
}
char x;
printf("Student or Professor? [s/p] ");
getchar() != '\n';
scanf("%c",&x);
if(x=='s')
{
getchar() != '\n';
pinx[*head]->flag = 0;
printf("\n\nGive student's name: ");
fgets(pinx[*head]->student.name,sizeof(pinx[*head]->student.name),stdin);
printf("\nGive student's semester: ");
scanf("%d",&(pinx[*head]->student.semester));
printf("\nName = %s\tSemester = %d",pinx[*head]->student.name,pinx[*head]->student.semester);
}
else if(x=='p')
{
getchar() != '\n';
pinx[*head]->flag = 1;
printf("\n\nGive professor's name: ");
fgets(pinx[*head]->prof.name,sizeof(pinx[*head]->prof.name),stdin);
printf("\nGive course: ");
fgets(pinx[*head]->prof.course,sizeof(pinx[*head]->prof.course),stdin);
printf("\nName = %s\tCourse = %s\n",pinx[*head]->prof.name,pinx[*head]->prof.course);
}
(*head)++;
printf("\nhead= %d\n",*head);
}
int main()
{
int n,i;
printf("Give size: ");
scanf("%d",&n);
init(n);
for(i=0;i<n;i++)
push(&stack,&exp1.head,n);
return 0;
}
You need to malloc the structure not n
malloc(sizeof(struct student_or_prof)*n)
EDIT:
And your code crashes again because pinx is a double pointer, so this operation is not valid:
pinx[*head]->flag = 0;
this is equivalent to:
*(pinx + *head)->flag = 0;
Since you are not changing what stack points to, you are better off using a single pointer instead of a double pointer.
So instead you should change your push API:
int push(struct student_or_prof *pinx,int *head,int n)
and call it like:
push(stack,&exp1.head,n);
malloc allocates the given number of bytes.
You have to multiply n with the size of your struct, to allocate enough memory.
pinx does not point to an array, so pinx[*head] is going to access invalid memory unless *head is zero.
I think you meant (*pinx)[*head] , which accesses the N-th element of the array you allocated via malloc. For example (*pinx)[*head].prof.name etc.
BTW, your head number doesn't seem to be used at all, except for exp1.head, maybe it'd be better to remove head from the struct, and just have a single variable head?

dynamic array of structs in C

I am trying to learn about structs, pointers, and dynamic arrays in C. I don't understand how to create a dynamic array of structs using pointers. My code doesn't work, and I don't know what's wrong with it. I have seen several examples of dynamic arrays, but non with structs. Any help would be appreciated. Please give some explanation, not just code snippets as I do want to understand not just solve this problem.
#include<stdio.h>
#include<stdlib.h>
#include <string.h>
struct *struct_array;
int i,m,n,p;
struct data
{
char inputA[20];
char inputB[20];
};
struct data get_data()
{
struct data thisdata;
printf("Please enter input A\n");
scanf("%s", thisdata.inputA);
printf("Please enter input B\n");
scanf("%s", thisdata.inputB);
return thisdata;
}
void Output(struct data struct_array, int n)
{
int index = 0;
for(i = 0; i<n ;i++)
{
printf("%s ", struct_array[i].inputA);
printf("%s ", struct_array[i].inputB);
}
}
void resizeArray(int n)
{
struct_array = (int*)realloc(n*sizeof(int));
}
void mainMenu()
{
printf("Please select from the following options:\n");
printf("1: Add new students to database\n");
printf("2: Display current student database contents\n");
printf("3: exit the program\n");
scanf("%d", &p);
if(p == 1)
{
printf("Please enter the number of students to register:\n");
scanf("%d", &n);
resizeArray(n);
for(i = n; i<n ;i++)
{
struct_array[i] = get_data();
}
}
else if(p == 2)
{
Output(struct_array, n);
}
else
{
free(struct_array);
exit(0);
}
}
int main()
{
struct_array = (int*)realloc(2*sizeof(int));
mainMenu();
}
You have several errors in your source code:
struct *struct_array; (l. 5)
What does it mean? Did you want to write struct data *struct_array?
printf("%s ", struct_array[i].inputA); (l.32 & l. 33)
The argument struct_array masks the global declaration, and it is not an array. Why did you add this argument?
struct_array = (int *)realloc(n * sizeof(int)); (l. 39)
You have forgotten an argument. Did you want to use malloc instead? Besides, the cast is not necessary (and incorrect!).
Unless you are using an hosted environnment and C99/C11, you should return a value from main.
Your variable index is not used. Why did you declare it?
for(i = n; i < n; i++) (l. 53)
You won't have any iteration here...
The following code works as expected.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* TODO: Avoid global variables. */
struct data *struct_array;
struct data {
char inputA[20];
char inputB[20];
};
/*
* TODO: Try to avoid passing your structure (40 bytes + padding)
* without pointer.
*/
struct data get_data(void)
{
struct data thisdata;
printf("Please enter input A\n");
/* TODO: Avoid using `scanf` for human inputs. */
scanf("%s", thisdata.inputA);
printf("Please enter input B\n");
scanf("%s", thisdata.inputB);
return thisdata;
}
void Output(size_t n)
{
size_t i;
for (i = 0; i < n; i++) {
printf("%s ", struct_array[i].inputA);
printf("%s ", struct_array[i].inputB);
}
}
void resizeArray(size_t n)
{
/* TODO: Handle reallocations errors. */
struct_array = realloc(struct_array, n * sizeof *struct_array);
}
void mainMenu(void)
{
size_t i, n;
int p;
/* TODO: Use a loop ? */
printf("Please select from the following options:\n");
printf("1: Add new students to database\n");
printf("2: Display current student database contents\n");
printf("3: exit the program\n");
scanf("%d", &p);
switch (p) {
case 1:
printf("Please enter the number of students to register:\n");
scanf("%u", &n);
resizeArray(n);
for (i = 0; i < n; i++)
struct_array[i] = get_data();
break;
case 2:
Output(n);
break;
}
}
int main(void)
{
struct_array = malloc(2 * sizeof(int));
mainMenu();
free(struct_array);
return 0;
}
Your definition
struct *struct_array;
is erroneous. You must use the name of your type, the data.
struct data *struct_array;
This way you can allocate the array
struct_array = malloc(MaxNumElements * sizeof(struct data));
and later you should free the memory
free(struct_array);
EDIT: Type definition must occur before the var declaration.
struct data ....
struct data* your_variable;
P.S. If you do not want to type struct keyword each time you use the data type, use the typedef:
typedef struct data_s
{
char inputA[20];
char inputB[20];
} data;
Do you know how to use typedef?
I would suggest it, makes your code easier to understand and you won't have to be typing the word struct a thousand times. Also you could treat the new type similar to the primitive types (ints, chars, etc), just don't forget to use the dot (.) to access the individual fields you might want.
You could type for instance:
typedef struct{
char inputA[20];
char inputB[20];
} data;
Now you could declare variables like this:
data data_variable;
data *pointer_to_data;
And to you could allocate memory as follows:
pointer_to_data = (data*) malloc(sizeof(data)* N);
where N is the amount of struct data you want to allocate. Same works for realloc.
struct_array = (int*)realloc(2*sizeof(int));
By the above statement you are trying to assign address of an int to a pointer of type struct data.
You need to use:
struct_array = (struct data*)realloc(2*sizeof(struct data));

Resources