Returning structures from functions. C - c

I am new to C and programming as a whole. I am trying to create a simple file validation program that reads in records from a file and sorts valid from invalid records. I have managed to achieve this but have run into problems when trying to return the structs for use in the main program.
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#define MAX 20
typedef struct data{
int ref;
int serial;
char string[MAX+1];
}vaild,invalid;
int g = 1;
int e = 1;
void read(FILE *file);
void val(struct data* t);
void create_record(struct data* temp);
void create_error(struct data* temp);
void export_data(struct data* record, struct data* error);
int main(){
FILE *file = fopen("file.txt", "r");
if (file != NULL){
read (file);
I want to be able to call the structures 'valid and 'invalid' from here inside the main function. Like the commented out printf function below.
//printf("%i", valid[1].ref); <<<<<<<<<< I need to be able to play around with the structures from inside the main function!
}
return 0;
}
void read(FILE *file){
struct data* t = malloc(sizeof(struct data));
char buf[1000];
while(!feof(file)){
fgets(buf, sizeof buf, file);
sscanf(buf, "%d.%d.%s", &t->ref, &t->serial, t->string);
val(t);
}
}
void val (struct data* t){
if((t->ref < 30)){
struct data* valid = (struct data*) malloc(sizeof(struct data));
valid = (struct data*)realloc(valid, g * sizeof(struct data));
valid[g-1] = *t;
if (valid == NULL){
puts("Memory allocation error!");
exit(EXIT_FAILURE);
}
printf("\nGOOD:%i.%i.%s\n", valid[g-1].ref, valid[g-1].serial, valid[g-1].string);
g++;
}
else{
struct data* invalid = (struct data*) malloc(sizeof(struct data));
invalid = (struct data*)realloc(invalid, e * sizeof(struct data));
invalid[e-1] = *t;
if ( invalid == NULL){
puts("Memory allocation error!");
exit(EXIT_FAILURE);
}
printf("\nBAD:%i.%i.%s\n", invalid[e-1].ref, invalid[e-1].serial, invalid[e-1].string);
e++;
}
}
I cant seem to be able to call the structures from within main by using the return functions, I feel I must be doing something really simple wrong. Getting pretty frustrated.
The input file is like so:
04.06.hello
09.65.test
88.55.string
27.12.qwerty
11.53.ytrewq
92.02.ecco
Everything else is working fine and there are no compiler errors. I have changed all the return types to void to make it less messy, I think I must be using them wrong.

Found your problem
void val (struct data* t){
if((t->ref < 30)){
struct data* valid = (struct data*) malloc(sizeof(struct data));
valid = (struct data*)realloc(valid, g * sizeof(struct data));
valid[g-1] = *t;
if (valid == NULL){
puts("Memory allocation error!");
exit(EXIT_FAILURE);
}
printf("\nGOOD:%i.%i.%s\n", valid[g-1].ref, valid[g-1].serial, valid[g-1].string);
g++;
}
else{
struct data* invalid = (struct data*) malloc(sizeof(struct data));
invalid = (struct data*)realloc(invalid, e * sizeof(struct data));
invalid[e-1] = *t;
if ( invalid == NULL){
puts("Memory allocation error!");
exit(EXIT_FAILURE);
}
printf("\nBAD:%i.%i.%s\n", invalid[e-1].ref, invalid[e-1].serial, invalid[e-1].string);
e++;
}
}
In above code when you define valid and invalid inside If and else if , scope of these variables are inside those if conditions. So you will get "valid not defined" error.
Try this
struct data* val(struct data* t){
if((t->ref < 30)){
struct data* valid_file = (struct data*) malloc(sizeof(struct data));
valid_file = (struct data*)realloc(valid_file, g * sizeof(struct data));
valid_file[g-1] = *t;
if (valid_file == NULL){
puts("Memory allocation error!");
exit(EXIT_FAILURE);
}
printf("\nGOOD:%i.%i.%s\n", valid_file[g-1].ref, valid_file[g-1].serial, valid_file[g-1].string);
g++;
return valid_file;
}
// Will come when result is invalid
struct data* invalid_file = (struct data*) malloc(sizeof(struct data));
invalid_file = (struct data*)realloc(invalid_file, e * sizeof(struct data));
invalid_file[e-1] = *t;
if ( invalid_file == NULL){
puts("Memory allocation error!");
exit(EXIT_FAILURE);
}
printf("\nBAD:%i.%i.%s\n", invalid_file[e-1].ref, invalid_file[e-1].serial, invalid_file[e-1].string);
e++;
return invalid_file;
}
Note - Changed valid and invalid to different variable names to separate struct name definitions.
Complete working example :)
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#define MAX 20
typedef struct data{
int ref;
int serial;
char string[MAX+1];
}vaild,invalid;
int g = 1;
int e = 1;
struct data* read(FILE *file);
struct data* val(struct data* t);
void create_record(struct data* temp);
void create_error(struct data* temp);
void export_data(struct data* record, struct data* error);
int main(){
FILE *file = fopen("file.txt", "r");
if (file != NULL){
struct data* answ=read (file);
printf("%i \n", answ->ref);
}
return 0;
}
struct data* read(FILE *file){
struct data* t = malloc(sizeof(struct data));
char buf[1000];
while(!feof(file)){
fgets(buf, sizeof buf, file);
sscanf(buf, "%d.%d.%s", &t->ref, &t->serial, t->string);
val(t);
}
return t;
}
struct data* val(struct data* t){
if((t->ref < 30)){
struct data* valid_file = (struct data*) malloc(sizeof(struct data));
valid_file = (struct data*)realloc(valid_file, g * sizeof(struct data));
valid_file[g-1] = *t;
if (valid_file == NULL){
puts("Memory allocation error!");
exit(EXIT_FAILURE);
}
printf("\nGOOD:%i.%i.%s\n", valid_file[g-1].ref, valid_file[g-1].serial, valid_file[g-1].string);
g++;
return valid_file;
}
// Will come when result is invalid
struct data* invalid_file = (struct data*) malloc(sizeof(struct data));
invalid_file = (struct data*)realloc(invalid_file, e * sizeof(struct data));
invalid_file[e-1] = *t;
if ( invalid_file == NULL){
puts("Memory allocation error!");
exit(EXIT_FAILURE);
}
printf("\nBAD:%i.%i.%s\n", invalid_file[e-1].ref, invalid_file[e-1].serial, invalid_file[e-1].string);
e++;
return invalid_file;
}

Returning a struct in C is acceptable when the struct is small. Otherwise you'd be better off using pointers.
The snippet below is a simple example that shows you how to return a struct.
Same rules apply as returning any other data type (e.g., int, double, ...), return types need to match and the function needs to have a return statement.
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int x;
int y;
} Point;
Point init_point(Point p, int x, int y) {
p.x = x;
p.y = y;
return p;
}
void main() {
Point p1, p2;
printf("%d, %d\n", p1.x, p1.y);
printf("%d, %d\n", p2.x, p2.y);
p1 = init_point(p1, 55, 10);
printf("%d, %d\n", p1.x, p1.y);
printf("%d, %d\n", p2.x, p2.y);
p2 = init_point(p2, 10000, 190);
printf("%d, %d\n", p1.x, p1.y);
printf("%d, %d\n", p2.x, p2.y);
}
The result is :
-1080464084, -1080464264
1, -1080464092
55, 10
1, -1080464092
55, 10
10000, 190

Related

Loading binary file to unknown struct type

I have a problem reading from binary file and casting it to a unknown type of struct...
Should I really avoid having the save/load functions inside my
Linked List code?
Is it because the GCC compiler I'm using stacks
the struct with more data to conveniently store in memory, and since
when loading the function doesn't know about this "offsets"?
I'm writing a generic linked list in C, and it is intended to be a header file, so I can just use it anywhere. Since it's going to be a generic type list, the header will not know about the type of data on the list (I'm looking at mixed types, so structs). For saving data, I just pass the address of the data, and the length of it, extracted from sizeof(struct). The reading is the same concept, using fread(container, sizeof(struct), 1, FILE), which is passed by the calling program, again extracting se size using sizeof(struct). But in practice, it does not work...
#ifndef LINKEDLIST_H_INCLUDED
#define LINKEDLIST_H_INCLUDED
#include <string.h>
typedef struct tagNode{
void *data;
struct tagNode *next_Node;
} Node;
typedef struct tagLinkedList{
Node *Head;
int Size;
} LinkedList;
int LinkedList_New(LinkedList *llist){
llist->Head = NULL;
llist->Size = 0;
return 1;
}
int LinkedList_Insert(LinkedList *llist, int index, void *Data, size_t s_Data){
int cur_index = 0;
if(index > llist->Size || index < 0)
index = 0;
Node *newNode = malloc(sizeof(Node));
newNode->data = malloc(s_Data);
if(newNode == NULL){return 0;}
if(newNode->data == NULL){return 0;}
newNode->data = Data;
Node *currentNode = llist->Head;
Node *lastNode = llist->Head;
if(index == 0){
newNode->next_Node = llist->Head;
llist->Head = newNode;
}else{
while(llist->Head->next_Node != NULL && cur_index != index){
if(cur_index == index){
newNode->next_Node = currentNode;
lastNode->next_Node = newNode;
}else{
lastNode = currentNode;
currentNode = currentNode->next_Node;
cur_index++;
}
}
}
llist->Size += 1;
}
int LinkedList_Save(char *Path, LinkedList *llist, size_t sData){
FILE *fp;
fp = fopen(Path, "w");
if(fp == NULL){return -1;}
Node *currentNode;
currentNode = llist->Head;
while(currentNode != NULL){
fwrite(currentNode->data, sData, 1, fp);
currentNode = currentNode->next_Node;
}
fclose(fp);
return 1;
}
int LinkedList_Load(char *Path, LinkedList *llist, size_t sData){
FILE *fp;
fp = fopen(Path, "r");
if(fp == NULL){fclose(fp);return -1;}
while(!feof(fp)){
void *Data = malloc(sData);
if(Data == NULL){fclose(fp);return -1;}
fread(Data, sData, 1, fp);
LinkedList_Insert(llist, 0, Data, sData);
}
fclose(fp);
return 1;
}
#endif // LINKEDLIST_H_INCLUDED
And my currently testing subject:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "../LinkedList.h"
typedef struct{
int a;
char b[5];
} tempo;
int main(){
tempo teste = {5, "oito"};
LinkedList lista;
LinkedList_New(&lista);
LinkedList_Insert(&lista, 0, &teste, sizeof(tempo));
LinkedList_Save("data.txt", &lista, sizeof(tempo));
printf("%s", ((tempo*)lista.Head->data)->b);
LinkedList ls2;
LinkedList_New(&ls2);
LinkedList_Load("data.txt", &ls2, sizeof(tempo));
printf("%s", ((tempo*)ls2.Head->data)->b);
return 1;
}
The first printf shows me the b variable in the struct, which means the list is working like its supposed to.
But the second printf, if used to show the a variable(int), I get a random number(something like 8712382), and if used to show the b variable, I get just "L"
you have a problem in your LinkedList_load function. update it to the following
int LinkedList_Load(char *Path, LinkedList *llist, size_t sData){
FILE *fp;
fp = fopen(Path, "rb");
if(fp == NULL){fclose(fp);return -1;}
fseek(fp,0L,SEEK_SET);
while(!feof(fp)){
void *Data = malloc(sData);
if(Data == NULL){fclose(fp);return -1;}
int readed=fread(Data, sData, 1, fp);
if(readed==0){return -1;}
/*you were displaying the last reading that contains
*nothing, the previous check solves the problem.
*/
printf("readed %d items: \n",readed);
LinkedList_Insert(llist, 0, Data, sData);
}
fclose(fp);
}

C - pointer to array of pointers

i have to store the pointers of a data structure.
So, i need an array of pointer.
I created a simple example, but i receive a segmentation fault.
Why i cannot do
buf->data[i] = pkt ??
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#define MAX_SIZE 500000
#define MAX_CHAR 1024
char *string = "HelloHelloHello";
struct pkt {
char *buf;
int seq;
};
struct buffer {
int a;
int b;
struct pkt **data;
};
struct buffer *new_buffer() {
struct buffer *new;
new = malloc(sizeof(struct buffer) * MAX_SIZE);
if (new == NULL) {
perror("malloc(buffer)");
exit(EXIT_FAILURE);
}
struct pkt *data;
data = malloc(sizeof(struct pkt) * MAX_SIZE);
if (data == NULL) {
perror("malloc(data)");
exit(EXIT_FAILURE);
}
new->data = &data;
new->a = 0;
new->b = 0;
return new;
}
struct pkt *new_pkt(char *data, int seq) {
struct pkt *pkt;
pkt = malloc(sizeof(struct pkt));
if (pkt == NULL) {
perror("malloc(pkt)");
exit(EXIT_FAILURE);
}
pkt->buf = malloc(sizeof(char) * MAX_CHAR);
if (pkt->buf == NULL) {
perror("malloc(pkt->buf)");
exit(EXIT_FAILURE);
}
strncpy(pkt->buf, data, MAX_CHAR);
pkt->seq = seq;
return pkt;
}
void add_pkt(struct pkt *pkt, struct buffer *buf, int i) {
buf->data[i] = pkt; //segmentation fault
}
int main() {
struct buffer *my_buffer = new_buffer();
struct pkt *pkt;
int i;
for(i=0; i<MAX_SIZE; ++i) {
pkt = new_pkt(string, i);
add_pkt(pkt, my_buffer, i);
printf("[%d]", i);
}
return 0;
}
change
struct pkt *data;
data = malloc(sizeof(struct pkt) * MAX_SIZE);
if (data == NULL) {
perror("malloc(data)");
exit(EXIT_FAILURE);
}
new->data = &data;
to
new->data = malloc(sizeof(struct pkt*) * MAX_SIZE);
if (new->data == NULL) {
perror("malloc(new->data)");
exit(EXIT_FAILURE);
}
struct pkt *data; is a local variable, saving its address and using it after the scope ends, is undefined behaviour. Also you want a memory area where you can save some struct pkt*s and not struct pkts.
Since you are not freeing anything, you have a big memory leak.

Read/write linked nodes from binary file

I have a problem reading a binary file which contains linked nodes.
This is the code:
lib1.c
struct my_stack_node {
void *data;
struct my_stack_node *next;
};
struct my_stack {
int size;
struct my_stack_node *first;
};
int my_stack_write(struct my_stack *stack, char *filename){
int count = 0;
struct my_stack_node *aux;
FILE *file = fopen(filename, "wb");
if(stack->first != NULL){
aux = stack->first;
count++;
while(aux->next != NULL){
fwrite(&aux ,sizeof(aux), 1, file);
aux = aux->next;
count++;
}
}
fwrite(&stack, sizeof(stack), 1, file); //Escriure stack
fclose(file);
return count;
}
struct my_stack *my_stack_read(char *filename){
struct my_stack *stackRead;
struct my_stack_node *stackNode;
FILE *file = fopen(filename, "rb");
if(!file){
puts("Impossible obrir el fitxer");
return NULL;
}else{
int primerInici = 0;
while(!feof(file)){
if(primerInici == 0){
stackRead = (struct my_stack*) malloc(sizeof(struct my_stack));
fread(stackRead, sizeof(stackRead), 1, file);
primerInici = 1;
}else{
//Crear nou node i llegir-lo del fitxer
stackNode = (struct my_stack_node*) malloc(sizeof(struct my_stack_node));
fread(stackNode, sizeof(stackNode), 1, file);
//Afegir node a la pila
stackNode->next = stackRead->first;
stackRead->first = stackNode;
}
}
fclose(file);
return stackRead;
}
}
main.c
struct my_data {
int val;
char name[60];
};
int main() {
struct my_stack *s, *t, *u;
struct my_data *data, *data1, *data2;
//...more code
u = my_stack_read("/tmp/my_stack.data");
if (! u) {
puts("Error in my_stack_read (u)");
exit(1);
}
if (my_stack_len(s) != my_stack_len(u)) {
puts("Stacks s and u don't have the same len");
exit(1);
}
// Test we can free the data and compare stacks s and u
while((data1 = my_stack_pop(s))) {
data2 = my_stack_pop(u);
if (! data2 || data1->val != data2->val || my_strcmp(data1->name, data2->name)) {
printf("Data in s and u are not the same: %d <> %d\n", data1->val, data2->val);
exit(1);
}
free(data1);
free(data2);
}
//...more code
puts("All tests passed");
return 0;
}
The result of the execution is:
Stack len: 100
Data in s and u are not the same: 22145808 <> 22134800
The correct result should be:
All tests passed
Here lies the problem (inside my_stack_write) :
aux = stack->first;
count++;
while(aux->next != NULL){
fwrite(&aux ,sizeof(aux), 1, file);
aux = aux->next;
count++;
}
You are writting the pointer aux. Not the struct which is being pointed by aux. Neither the data pointed by data, which is the important part.
So. Imagine you have something like this :
my_stack { first=0x100 }
at memoryPosition 0x100 we have : my_stack_node { data=0x200; next=0x300 }
at memoryPosition 0x300 we have : my_stack_node { data=0x500; next=0x600 }
at memoryPosition 0x600 we have : my_stack_node { data=0x700; next=NULL }
For that structure your program is writting : 0x100, 0x300
You are writting the memory addresses of the nodes making up your linked list. And you are missing the last node, which is a different kind of error.
But that is useless. Next time you run your program your nodes may be in different memory addresses so there is no point in saving them. It is dynamic memory, it may reside at different places each time you run your program.
What you should be writting instead is the data your linked list is listing.
This same mistake is repeated in pretty much the whole program.
How to properly write the data contained in the linked list :
void writeStack(struct my_stack *stack, const char *filename)
{
struct my_stack_node *aux;
FILE *file = fopen(filename, "wb");
if ( file==NULL )
{
fprintf( stderr, "Could not open %s for writting.\n", filename );
exit(1);
}
if (stack != NULL)
{
aux = stack->first;
while(aux != NULL)
{
// aux->data is of type void*
// Assuming that aux->data contains a struct my_data
// Most likely it would be better to redefine data as having
// type struct my_data*
fwrite(aux->data ,sizeof(struct my_data), 1, file);
aux = aux->next;
}
}
fclose(file);
}
Here we traverse all the nodes in the list.
And for each we write the data in them contained.
Notice how fwrite( aux->data, writes the data pointed at by aux->data, which is correct.
While fwrite( &aux, would write the memory address contained at aux, which is unlikely to be correct.
And fwrite( &aux->data, would write the memory address contained at aux->data, which is also unlikely to be correct.
It is up to you to add code for counting and to write the reading function.
You only read and write the stack itself, not the payload of its nodes, which is stored voa a void * pointer.
The nodes themselves carry no meaningful information. Or information that is meaningful across sessions, rather: The data and next pointers are valid only in the session that writes the data.
Your stack is essentially a linear data structure. Instead of storing the nodes, store the stack data as array of data members. When you read them in, construct a list with freshly allocated nodes and the read data fields.
Your stack uses void * pointers to allow for various data types. You must therefore find a way to tell the read and write methods how the data should be written or read.
You could provide a callback function where you pass the opened file. Such callbacks could deal with complex data structures as payload, if needed.
Edit: The code below shows an example of how to serialise a stack with custom functions for reading and writng. The symmetric callbacks should write the data to the file and read the data. The read function can allocate memory, which is owned by the stack. The user must make sure to free it.
The callbacks can return a negative number to indicate an error. The stack to read need not be empty. Read data ist just pushed to the stack.
#include <stdlib.h>
#include <stdio.h>
#define die(...) exit((printf(__VA_ARGS__), putchar('\n'), 1));
typedef struct Stack Stack;
typedef struct SNode SNode;
struct SNode {
void *data;
SNode *next;
};
struct Stack {
SNode *head;
};
/*
* Core stack functions
*/
void stack_push(Stack *st, void *data)
{
SNode *sn = malloc(sizeof(*sn));
sn->data = data;
sn->next = st->head;
st->head = sn;
}
void *stack_pop(Stack *st)
{
void *data;
SNode *sn;
if (st->head == NULL) die("Undeflow");
sn = st->head;
data = sn->data;
st->head = sn->next;
free(sn);
return data;
}
int stack_empty(const Stack *st)
{
return (st->head == NULL);
}
/*
* Stack write function with custom callback
*/
int stack_write(const Stack *st, const char *filename,
int (*func)(FILE *f, const void *data))
{
const SNode *sn = st->head;
size_t count = 0;
FILE *f = fopen(filename, "wb");
if (f == NULL) return -1;
fwrite(&count, 1, sizeof(count), f);
while (sn) {
if (func(f, sn->data) < 0) {
fclose(f);
return -1;
}
count++;
sn = sn->next;
}
fseek(f, SEEK_SET, 0);
fwrite(&count, 1, sizeof(count), f);
fclose(f);
return count;
}
/*
* Stack read function with custom callback
*/
int stack_read(Stack *st, const char *filename,
int (*func)(FILE *f, void **data))
{
size_t count = 0;
size_t i;
FILE *f = fopen(filename, "rb");
if (f == NULL) return -1;
fread(&count, 1, sizeof(count), f);
for (i = 0; i < count; i++) {
void *p;
if (func(f, &p) < 0) {
fclose(f);
return -1;
}
stack_push(st, p);
}
fclose(f);
return count;
}
/*
* Custom data struct with read/write functions
*/
struct my_data {
int val;
char name[60];
};
int my_data_write(FILE *f, const void *data)
{
if (fwrite(data, sizeof(struct my_data), 1, f) < 1) return -1;
return 0;
}
int my_data_read(FILE *f, void **data)
{
*data = malloc(sizeof(struct my_data));
if (*data == NULL) return -1;
if (fread(*data, sizeof(struct my_data), 1, f) < 1) {
free(data);
return -1;
}
return 0;
}
/*
* Example client code
*/
int main()
{
Stack s = {NULL};
Stack t = {NULL};
struct my_data aa = {23, "Alice Atkinson"};
struct my_data bb = {37, "Bob Bates"};
struct my_data cc = {28, "Carol Clark"};
stack_push(&s, &aa);
stack_push(&s, &bb);
stack_push(&s, &cc);
stack_write(&s, "kk", my_data_write);
while (s.head) stack_pop(&s);
stack_read(&t, "kk", my_data_read);
while (t.head) {
struct my_data *p = stack_pop(&t);
printf("%4d '%s'\n", p->val, p->name);
free(p);
}
return 0;
}

Using realloc in dynamic structure array

I am trying to use realloc to dynamically create instances of a struct, filling it with data from a temporary structure as I go. The program crashes when it reaches the line to malloc a pointer of the structure a second time but I am not sure how I should structure this function. I have the following code:
#define MAX_STRING 50
struct data {
int ref;
int port;
char data[MAX_STRING+1];
}valid, invalid;
void read_file(FILE *file);
void validate(struct data* temp);
int g = 0;
int main(){
char inputfile[100];
FILE *file = fopen("file.txt" , "r");
if (file != NULL){
read_file (file);
}
else{
// Some code here..
}
return 0;
}
void read_file(FILE *file){
struct data* temp = malloc(sizeof(struct data));
char buf[1024];
while(!feof(file)){
fgets(buf, sizeof buf, file))
sscanf(buffer, "%d.%d.%s", &temp->ref, &temp->port, &temp->data);
validate(temp);
g++;
}
}
void validate(struct data* temp){
if((some condition) && (some condition))
{
create_valid(temp);
}
if((some condition) && (some condition))
{
create_invalid(temp);
}
}
I am unsure of how to structure the following function:
int create_vaild(struct data* temp){
struct data* valid = malloc(sizeof(struct data)); <<<<<<<<< Line that crashes
valid = realloc(valid, g * sizeof(struct data));
valid[g] = *temp;
if (valid[g] == NULL){
//error.
};
printf("\n%i:%i:%s\n", (valid+g)->ref, (valid+g)->port, (valid+g)->data);
return 0;
}
I see one potential problem:
You have g set to 0 i.e.
int g =0;
You are not incrementing it before the call to create_valid(). You are using this value to allocate memory inside that functions:
valid = realloc(valid, g * sizeof(struct data));
So now g is 0.
Later in the next line you dereference this pointer
valid[g] = *temp;
This is some memory which you have not allocated as realloc() didn't allocate memory for you becasue you passed 0 to it.Hence the crash.

Creating a list from ".bin" file in C

My goal is to create a list from "menu.bin". This is the func:
pitem recupera_menu(pitem p){
pitem novo,aux;
FILE *f;
f=fopen("menu.bin","rb");
if(f == NULL)
printf("Erro ao caregar o ficheiro 'menu.bin' \n");
novo = (struct item*)malloc(sizeof(item));
if(novo == NULL)
return p;
novo->prox=NULL;
while((fread(novo,sizeof(item),1,f))!=NULL){
if(p==NULL){
p=novo;
aux=p;
}
else{
aux->prox=novo;
aux=aux->prox;
}
printf("%s\n OLE\n",aux->id);
}
fclose(f);
system("pause");
return p;
}
this is my struct:
typedef struct item item, *pitem;
struct item{
char id[5];
int ing[10];
float qtd[10];
pitem prox;
};
For some reason the result of the file isn't the one that should be(it doesn't read the document strait).Maybe someone could help me.
EDIT:
well it does run, and prints the "ole" line.The problem is that the file .bin has been completed with the following struct type:
struct item{
char id[5];
int ing[10];
float qtd[10];}
and when i do malloc, i allocate memory to the folowing struct type:
struct item{
char id[5];
int ing[10];
float qtd[10];
pitem prox;
};
struct item{
char id[5];
int ing[10];
float qtd[10];
};
struct list{
struct list *next;
struct item payload;
};
Allocate:
struct list *p;
p = malloc (sizeof *p);
read from file:
ret = fread(&p->payload, sizeof p->payload, 1, fp);
Extra: sanitize the loop:
int recupera_menu(struct list **pp){
int ret,cnt;
FILE *fp;
fp = fopen("menu.bin","rb");
if (!fp) {
fprintf(stderr, "Erro ao caregar o ficheiro 'menu.bin' \n");
return 0;
}
for (cnt=0; ;cnt++) {
*pp = malloc(sizeof **pp);
if( !*pp ) break;
(*pp)->next = NULL;
ret = fread(&(*pp)->payload, sizeof &(*pp)->payload, 1, fp);
if (ret < 1) break;
pp = &(*pp)->next;
}
free (*pp);
*pp = NULL;
fclose(fp);
return cnt
}

Resources