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
}
Related
I wrote a function to delete and extract an Item from a list following the usual algorithm for extraction, but while it scans the list it deletes all the items before the searched element.
I am probably missing some pointer being dereferenced but I can't really see where...
Thank you in advance for the help.
Here's the full code.
//DATA STRUCTURE
typedef struct{//EQUIPMENT
int inUse;
object **arrEquip;
}equip;
typedef struct{//PG
char code[MAXL];
char name[MAXL];
char class[MAXL];
equip equip_t;
stats stats_t;
}pg;
typedef struct nodePg theNodePg, *link;
struct nodePg{ //NODE
pg pg_t;
link next;
};
typedef struct{//LIST WRAPPER
link head;
link tail;
int nPg;
}tabPg;
int main(){
tabPg tabPg_t;
tabInv tabInv_t;
int choice;
tabPg_t.head = NULL;
tabPg_t.nPg = 0;
do{
printMenu(&choice);
runSelectedFun(&tabPg_t, &tabInv_t, choice);
}while(choice != 0);
return 0;
}
void runSelectedFun(tabPg *tabPg_t, tabInv *tabInv_t, int choice){
//[...]
pgExtraction(&tabPg_t->head);
//[...]
}
void pgExtraction(link *head){//eliminarlo dalla lista effettivamente
char toBeDeleted[MAXL];
theNodePg deleted;
int flag = 0;
printf("\nInserisci il codice del personaggio da eliminare");
scanf("%s", toBeDeleted);
deleted = extraction(head, toBeDeleted, &flag);
if(flag == 1){
printf("\nPersonaggio %s eliminato con successo!", deleted.pg_t.code);
}
else printf("\nIl codice inserito non ha corrispondenze all'interno della lista PG!\n");
}
theNodePg extraction(link *head, char *code, int *flag){
link *xp,t;
theNodePg deletedPg = {0};
for (xp = head; xp != NULL; xp = &(*xp)->next) {
if (strcmp((*xp)->pg_t.code, code) == 0) {
t = (*xp);
*xp = (*xp)->next;//eliminazione
deletedPg = *t;
free(t);
*flag = 1;
break;
}
}
return deletedPg;
}
I have a list of products of several categories in the file "Magazzino.txt" here below:
A451XX (codice prodotto)
CAT001 (codice categoria)
PASTA CONF. 1KG
100
99.0
A451XY (codice prodotto)
CAT002 (codice categoria)
MAGLIA LANA
25
6.70
A452XX (codice prodotto)
CAT001 (codice categoria)
SUGO
33
9.99
First I have to read the file and copy all products in a list with the following structure:
typedef struct {
char codP[C];
char codC[C];
char descr[D];
int num;
float costo;
} tipoBaseLista;
typedef struct nodoLista{
tipoBaseLista info;
struct nodoLista *next;
}prodotto;
typedef prodotto *listaP;
I need to copy this list of products in a list of categories such that each category has a sublist with all product that belong to the specific category. The structure of this list of list is:
typedef struct nodoCat{
char codC[C];
struct nodoCat *next;
listaP nodoP; //puntatore al sottonodo prodotto
}categoria;
typedef categoria *listaC;
This is the full code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#define C 8
#define D 64
typedef struct {
char codP[C];
char codC[C];
char descr[D];
int num;
float costo;
} tipoBaseLista;
typedef struct nodoLista{
tipoBaseLista info;
struct nodoLista *next;
}prodotto;
typedef prodotto *listaP;
typedef struct nodoCat{
char codC[C];
struct nodoCat *next;
listaP nodoP;
}categoria;
typedef categoria *listaC;
int carica_lista(char fName[], listaP *l);
void inserimentoProd(listaP *l, tipoBaseLista p);
listaC trovaCategoria(listaC lc, char categoria[]);
void inserimentoSottolista(listaC lc, tipoBaseLista p, listaP *l);
int main() {
char filename[] = "Magazzino.txt";
listaP lista = NULL;
listaC listaCat = NULL;
tipoBaseLista prodotto;
printf("\nNumero prodotti caricati: %d\n", carica_lista(filename, &lista));
if(lista == NULL){
printf("\nLa lista dei prodotti è vuota!\n");
}
while(lista != NULL){
prodotto = lista->info;
if(listaCat == NULL){
listaCat = malloc(sizeof(categoria));
strcpy(listaCat->codC, prodotto.codC);
listaCat->next = NULL;
inserimentoSottolista(listaCat, prodotto, &lista);
}
else{
listaCat = trovaCategoria(listaCat, prodotto.codC);
if(listaCat != NULL){
inserimentoSottolista(listaCat, prodotto, &lista);
}
else{
listaCat = listaCat->next;
inserimentoSottolista(listaCat, prodotto, &lista);
}
}
lista = lista->next;
}
return 0;
system("PAUSE");
}
//read from file
int carica_lista(char fName[], listaP *l) {
tipoBaseLista prodotto;
int n = 0;
char buf[D] = {0};
char scarto[30];
FILE *f;
f = fopen(fName, "r");
if (f == NULL) {
printf("Non e' possibile aprire il file\n");
exit(1);
}
while (!feof(f)) {
fgets(buf, sizeof(buf), f);
sscanf(buf, "%s%s", prodotto.codP, scarto);
fgets(buf, sizeof(buf), f);
sscanf(buf, "%s%s", prodotto.codC, scarto);
fgets(buf, sizeof(buf), f);
strcpy(prodotto.descr, buf);
fgets(buf, sizeof(buf), f);
sscanf(buf, "%d", &prodotto.num);
fgets(buf, sizeof(buf), f);
sscanf(buf, "%f", &prodotto.costo);
inserimentoProd(l, prodotto);
n++;
}
fclose(f);
return n;
system("PAUSE");
}
//to insert product in the list
void inserimentoProd(listaP *l, tipoBaseLista p){
listaP pCorrente = NULL;
listaP pNodo;
listaP pPrec;
pNodo = malloc(sizeof(prodotto));
pNodo->info = p;
pNodo->next = NULL;
if (*l == NULL){
*l = pNodo;
}
else if(strcmp(p.codP, (*l)->info.codP) < 0){
pNodo->next = *l;
*l = pNodo;
(*l)->next = pNodo;
}
else{
pCorrente = *l;
while (pCorrente->next != NULL && strcmp(p.codP, pCorrente->info.codP) > 0){
pPrec = pCorrente;
pCorrente = pCorrente->next;
}
if(strcmp(p.codP, pCorrente->info.codP) < 0){
pNodo->next = pCorrente;
pPrec->next = pNodo;
}
else if(pCorrente->next == NULL) {
pCorrente->next = pNodo;
}
}
}
//To find the category node under which we insert the sublist
listaC trovaCategoria(listaC lc, char categoria[]){
listaC pCorrente = lc;
while(pCorrente != NULL){
if(strcmp(pCorrente->codC, categoria) == 0){
printf("\nCategoria già presente.\n");
return pCorrente;
}
pCorrente = pCorrente->next;
}
return(NULL);
}
//to insert the product in the head of sublist
void inserimentoSottolista(listaC lc, tipoBaseLista p, listaP *l){
printf("\nInserimento nella sottolista\n");
listaP prodotto = malloc(sizeof(struct nodoLista));
prodotto->info = p;
prodotto->next = *l;
*l = prodotto;
lc->nodoP = prodotto;
printf("\nInserimento effettuato\n");
}
There must be some problem in the "inserimentoSottolista" that cause the crash of the program. What could it be?
The problem is here, inside inserimentoSottolista:
listaP prodotto = malloc(sizeof(prodotto));
You need sizeof(prodotto) to be the size of the struct that was declared earlier, i.e. sizeof(struct nodoLista). But you have used the same name for the name of the variable being initialized. In this case, the prodotto in sizeof(prodotto) isn't the struct, but is the variable. So sizeof(prodotto) ends up being the same as sizeof(listaP), which is just the size of a pointer. It's too small, so you aren't allocating enough memory.
You can fix it by changing the variable name so that it doesn't mask the type name, or by using sizeof(struct nodoLista).
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;
}
I'm trying to fill a gtk tree store from a linked list but i get the segmentation fault (core dumped) problem here is my code File to struct is a linked list filled a struct to a professor and a next the professor is defined by a name matiere password pseudo...etc
store = gtk_list_store_new (NUM_COLUMNNS,G_TYPE_INT,G_TYPE_STRING,G_TYPE_STRING,G_TYPE_STRING,G_TYPE_STRING,G_TYPE_INT);
File_to_struct *p=head;
/* add data to the list store */
while(p!=NULL)
{
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter,
COLUMNN_ID,p->professeur.ID,
COLUMNN_NOM,p->professeur.nom,
COLUMNN_MATIERE,p->professeur.matiere,
COLUMNN_PSEUD,p->professeur.pseudo,
COLUMNN_PASS,p->professeur.password,
COLUMNN_VALIDE,p->professeur.valide,
-1);
p=p->suivant;
}
FILE fichier=fopen("professeur.txt","r");
Prof professeur;
File_to_struct *tete=(File_to_struct)malloc(sizeof(File_to_struct));
tete=NULL;
rewind(fichier);
while((!feof(fichier)))
{
fscanf(fichier,"\n%s %s %s %s %d %d\n",professeur.nom,professeur.matiere,professeur.pseudo,professeur.password, &professeur.valide,&professeur.ID);
tete=inserer(tete,professeur); }
typedef struct prof{
int ID;
int valide;
char nom[40];
char matiere[40];
char password[40];
char pseudo[40]; }Prof;
typedef struct file_to_struct{
Prof professeur;
struct file_to_struct *suivant; }File_to_struct;
You have problems when filling the list, this is an example of how to do it correctly
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
typedef struct Prof
{
int ID;
int valide;
char nom[40];
char matiere[40];
char password[40];
char pseudo[40];
} Prof;
typedef struct File_to_struct
{
Prof professeur;
struct File_to_struct *suivant;
} File_to_struct;
File_to_struct *
inserer(File_to_struct *Debut, Prof profs)
{
File_to_struct *nv;
File_to_struct *actuel;
nv = malloc(sizeof(File_to_struct));
if (nv == NULL)
return Debut;
nv->suivant = NULL;
nv->professeur = profs;
actuel = Debut;
if (Debut == NULL)
Debut = nv;
else
{
while (actuel->suivant != NULL)
actuel = actuel->suivant;
actuel->suivant = nv;
}
return Debut;
}
char **
splitString(const char *const text, const char *const delimiter, int *count)
{
char *copy;
char *pointer;
char *token;
char *saveptr;
char **list;
if ((text == NULL) || (count == NULL) || (delimiter == NULL))
return NULL;
copy = strdup(text);
*count = 0;
pointer = copy;
list = NULL;
while ((token = strtok_r(pointer, delimiter, &saveptr)) != NULL)
{
void *auxiliary;
auxiliary = realloc(list, (1 + *count) * sizeof(char *));
if (auxiliary == NULL)
{
while (*count >= 0)
{
free(list[*count]);
*count -= 1;
}
free(copy);
free(list);
return NULL;
}
list = auxiliary;
list[*count] = strdup(token);
*count += 1;
pointer = NULL;
}
free(copy);
return list;
}
Prof
extractProfesseur(const char *const line)
{
char **list;
int count;
Prof prof;
memset(&prof, 0, sizeof(prof));
list = splitString(line, " ", &count);
if (count < 6)
{
while (--count >= 0)
free(list[count]);
free(list);
return prof;
}
prof.ID = strtol(list[4], NULL, 10);
prof.valide = strtol(list[5], NULL, 10);
strncpy(prof.nom, list[0], 39);
strncpy(prof.matiere, list[1], 39);
strncpy(prof.pseudo, list[2], 39);
strncpy(prof.password, list[3], 39);
while (--count >= 0)
free(list[count]);
free(list);
return prof;
}
int
main()
{
FILE *fichier;
File_to_struct *tete;
File_to_struct *actuel;
char line[256];
fichier = fopen("professeur.txt","r");
if (fichier == NULL)
return -1; /* n'pouvez pas de ouvrir le fichier */
tete = NULL;
rewind(fichier);
while (fgets(line, sizeof(line), fichier) != NULL)
{
Prof professeur;
professeur = extractProfesseur(line);
tete = inserer(tete, professeur);
}
actuel = tete;
while (actuel != NULL)
{
Prof prof;
File_to_struct *previous;
prof = actuel->professeur;
previous = actuel;
actuel = actuel->suivant;
printf("%s %s %s %s %d %d\n", prof.nom, prof.matiere,
prof.pseudo, prof.password, prof.valide, prof.ID);
free(previous);
}
fclose(fichier);
return 0;
}
im currently making a project for a college work and while doing it i came across that error and i have no clue what is causing it.
The line it points to is : if ((*compara)(ptr->dados, valor))
The Function :
void * pesquisar(PNO cabeca, int (*compara)(), void* valor) {
PNO ptr;
for (ptr = cabeca; ptr; ptr = ptr->prox);
if ((*compara)(ptr->dados, valor))
return ptr->dados;
return NULL;
}
The Structs
struct no{
struct no*prox;
struct no*ant;
void *dados;
};
typedef struct no NO;
typedef NO*PNO;
typedef NO**PPNO;
struct cliente{
int ID_cliente;
char nome[60];
char morada[255];
int contribuinte;
struct cliente * prox;
};
typedef struct cliente CLIENTE;
typedef CLIENTE*PCLIENTE;
CLIENTE *cabCliente, *cauCliente;
The Main :
PNO Cliente = NULL, Fatura = NULL;
PCLIENTE pesquisa;
char n;
void * Dados;
int opcao;
char nome[60];
case 3:
printf("Insira o Nome: ");
fgets(nome, 60, stdin);
nome[strlen(nome) - 1] = '\0';
pesquisa = pesquisar(Cliente, cmpNomeCliente, nome);
if (pesquisa) printf("Nome é: %s", nome);
else printf("Aluno inexistente");
getch();
break;
for (ptr = cabeca; ptr; ptr = ptr->prox);
if ((*compara)(ptr->dados, valor))
In this sequence of code, ptr in the second line will always be NULL because the for loop runs until the ptr expression is false and due to the ; after the for, the loop has no body.