Repository 32bit  Forum
Repository 64bit  Wiki

[C] Struct incomplete: un mistero.

Forum dedicato alla programmazione.

Moderatore: Staff

Regole del forum
1) Citare in modo preciso il linguaggio di programmazione usato.
2) Se possibile portare un esempio del risultato atteso.
3) Leggere attentamente le risposte ricevute.
4) Scrivere i messaggi con il colore di default, evitare altri colori.
5) Scrivere in Italiano o in Inglese, se possibile grammaticalmente corretto, evitate stili di scrittura poco chiari, quindi nessuna abbreviazione tipo telegramma o scrittura stile SMS o CHAT.
6) Appena registrati è consigliato presentarsi nel forum dedicato.

La non osservanza delle regole porta a provvedimenti di vari tipo da parte dello staff, in particolare la non osservanza della regola 5 porta alla cancellazione del post e alla segnalazione dell'utente. In caso di recidività l'utente rischia il ban temporaneo.

[C] Struct incomplete: un mistero.

Messaggioda Blallo » sab giu 21, 2014 22:43

Premetto che si tratta solo di una richiesta di spiegazioni, il programma per fortuna funziona perfettamente.

Ho un dubbio che mi attanaglia la mente sulle struct incomplete.
Praticamente ho creato un ADT FIFO costituito da oggetti Item, anch'essi astratti.
(Item è composto da una stringa e un intero).

Non capisco come si faccia a risolvere un problema di "tipo incompleto".
Nel file item.c c'è questo pezzo di codice suggeritomi da un amico:
Codice: Seleziona tutto
 i = (Item) malloc (sizeof(*i));

che io in precedenza avevo scritto come
Codice: Seleziona tutto
 i = (Item *) malloc (sizeof(Item));

Nella mia versione mi dava come errore "incomplete type error", che con la prima versione non si presenta.
Il punto è che... non capisco il senso della malloc di cui sopra.
Anche perché nella fifo questa malloc
Codice: Seleziona tutto
 queue = (Queue *) malloc (sizeof(Queue));

funziona egregiamente.
Il mio amico non è stato in grado di farmi capire niente, probabilmente ha solo copincollato da qualche sorgente.
Qualcuno sa darmi una spiegazione? :)

Allego sotto i listati.
Grazie in anticipo!

item.h
Codice: Seleziona tutto
#ifndef ITEM_H_INCLUDED
#define ITEM_H_INCLUDED

#define MAXBUF 100
#define MAXSTRING 20

#define FAILURE 0
#define SUCCESS 1

typedef struct ItemStruct *Item;

Item ItemGet();
void printItem (Item item, FILE *fp);

#endif // ITEM_H_INCLUDED

item.c
Codice: Seleziona tutto
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "item.h"


struct ItemStruct
{
    char word[MAXSTRING];
    int number;
};

Item ItemGet()
{
    Item i;
    char buf[MAXBUF];

    i = (Item) malloc (sizeof(*i));
    if (i == NULL)
    {
        fprintf ( stderr, "Error: insufficient memory for new element.\n");
        return NULL;
    }

    fgets(buf, MAXBUF, stdin);
    sscanf(buf, "%s %d", i->word, &i->number);

    return i;
}


void printItem (Item item, FILE *fp)
{
    fprintf(fp, "%s %d\n", item->word, item->number);
}


fifo.h
Codice: Seleziona tutto
#ifndef FIFO_H_INCLUDED
#define FIFO_H_INCLUDED

#include "item.h"

typedef struct QueueStruct Queue;

Queue *QueueInit(int size);
int QueueEmpty(Queue *queue);
void QueuePut(Queue *queue, Item item);
Item QueuePush(Queue *queue);

void QueuePrint(Queue *queue, FILE *fp);
void QueueFree(Queue *queue);

#endif // FIFO_H_INCLUDED

fifo.c
Codice: Seleziona tutto
#include <stdio.h>
#include <stdlib.h>
#include "fifo.h"


struct QueueStruct
{
    Item *q;
    int N;
    int head;
    int tail;
};

/*
 * QueueInit (int size)
 *
 * Create a queue of size [Size+1].
 *
 */
Queue *QueueInit(int size)
{
    Queue *queue;

    queue = (Queue *) malloc (sizeof(Queue));
    if (queue == NULL)
    {
        fprintf ( stderr, "Error: insufficient memory for new element.\n");
        return NULL;
    }

    queue->q = (Item *) malloc (sizeof(Item) * (size+1));
    if(queue == NULL)
    {
        fprintf ( stderr, "Error: insufficient memory for new queue.\n");
        free(queue);
        return NULL;
    }
    queue->N = size+1;
    queue->head = queue->N;
    queue->tail = 0;

    return queue;
}

/*
 * QueueEmpty()
 *
 * Checks if the queue is Empty.
 *
 */
int QueueEmpty(Queue *queue)
{
    return queue->head % queue->N == queue->tail;
}

void QueuePut(Queue *queue, Item item)
{
    if ( (queue->tail + 1) != queue->head)
    {
        queue->q[queue->tail++] = item;
        queue->tail = queue->tail % queue->N;
    }
    else
        fprintf(stdout, "Full queue! Data not inserted.\n");
}

Item QueuePush(Queue *queue)
{
    queue->head = queue->head % queue->N;
    return queue->q[queue->head++];
}

void QueuePrint(Queue *queue, FILE *fp)
{
    int i;

    for(i=queue->head % queue->N; i !=queue->tail; i++)
        printItem (queue->q[i], fp);
}

void QueueFree(Queue *queue)
{
    int i;

    for(i=queue->head % queue->N; i !=queue->tail; i++)
        free(queue->q[i]);
    free(queue->q);
    free(queue);
}
Io sono il detective Arsenio Magret, e porto sempre la camicia TATUATA!
Avatar utente
Blallo
Packager
Packager
 
Messaggi: 3244
Iscritto il: ven ott 12, 2007 10:37
Località: Torino / Torremaggiore (FG)
Nome Cognome: Savino Liguori
Slackware: 14.1 / 12.2
Kernel: 3.12.2-ck
Desktop: Openbox

Re: [C] Struct incomplete: un mistero.

Messaggioda targzeta » sab giu 21, 2014 23:34

L'errore parte dalla typedef. Quella corretta è:
Codice: Seleziona tutto
typedef struct QueueStruct Queue;
mentre in item hai (nota l'* di troppo):
Codice: Seleziona tutto
typedef struct ItemStruct *Item;
Tutto segue in cascata (a me le typedef non piacciono molto).

Emanuele
Linux Registered User #454438
Se pensi di essere troppo piccolo per fare la differenza, prova a dormire con una zanzara -- Dalai Lama
20/04/2013 - Io volevo Rodotà
Avatar utente
targzeta
Iper Master
Iper Master
 
Messaggi: 6195
Iscritto il: gio nov 03, 2005 14:05
Località: Carpignano Sal. (LE) <-> Pisa
Nome Cognome: Emanuele Tomasi
Slackware: current
Kernel: latest stable
Desktop: IceWM

Re: [C] Struct incomplete: un mistero.

Messaggioda Blallo » dom giu 22, 2014 3:15

Stesso errore.
Nel momento in cui la alloco nella fifo:
Codice: Seleziona tutto
queue->q = (Item *) malloc (sizeof(Item) * (size+1));

mi sputa fuori questo:
Codice: Seleziona tutto
error: invalid application of 'sizeof' to incomplete type 'Item'
Io sono il detective Arsenio Magret, e porto sempre la camicia TATUATA!
Avatar utente
Blallo
Packager
Packager
 
Messaggi: 3244
Iscritto il: ven ott 12, 2007 10:37
Località: Torino / Torremaggiore (FG)
Nome Cognome: Savino Liguori
Slackware: 14.1 / 12.2
Kernel: 3.12.2-ck
Desktop: Openbox

Re: [C] Struct incomplete: un mistero.

Messaggioda targzeta » dom giu 22, 2014 10:03

Quello è normale. Hai definito la struttura in item.c ma in fifo.c hai incluso item.h. Devi fare qualcosa tipo:

item.h
Codice: Seleziona tutto
#ifndef ITEM_H_INCLUDED
#define ITEM_H_INCLUDED

#define MAXBUF 100
#define MAXSTRING 20

#define FAILURE 0
#define SUCCESS 1

typedef struct ItemStruct
{
  char word[MAXSTRING];
  int number;
} Item;

Item *ItemGet();
void printItem (Item *item, FILE *fp);

#endif // ITEM_H_INCLUDED
Emanuele
Linux Registered User #454438
Se pensi di essere troppo piccolo per fare la differenza, prova a dormire con una zanzara -- Dalai Lama
20/04/2013 - Io volevo Rodotà
Avatar utente
targzeta
Iper Master
Iper Master
 
Messaggi: 6195
Iscritto il: gio nov 03, 2005 14:05
Località: Carpignano Sal. (LE) <-> Pisa
Nome Cognome: Emanuele Tomasi
Slackware: current
Kernel: latest stable
Desktop: IceWM

Re: [C] Struct incomplete: un mistero.

Messaggioda Blallo » dom giu 22, 2014 11:39

Però io volevo provare a fare qualcosa di questo tipo.
http://ejrh.wordpress.com/2011/04/29/en ... tion-in-c/
(Alla sezione Data Hiding)
Volevo, insomma, provare ad incapsulare la struttura, per dirla alla Java. :)
Io sono il detective Arsenio Magret, e porto sempre la camicia TATUATA!
Avatar utente
Blallo
Packager
Packager
 
Messaggi: 3244
Iscritto il: ven ott 12, 2007 10:37
Località: Torino / Torremaggiore (FG)
Nome Cognome: Savino Liguori
Slackware: 14.1 / 12.2
Kernel: 3.12.2-ck
Desktop: Openbox

Re: [C] Struct incomplete: un mistero.

Messaggioda targzeta » dom giu 22, 2014 14:52

Potevi dirlo prima.

Quello che fa lui è corretto, però allora tu non puoi mai riferire a Item direttamente fuori dal file item.c, devi:
  • usare sempre un puntatore;
  • usare solo i metodi dichiarati dentro item.h;
In particolare per allocare la coda devi fare:
Codice: Seleziona tutto
 queue->q = (Item **) malloc(sizeof(Item *) * size);
(quidi q nella QueueStruct diventa Item **q. Una volta allocato queue->q però devi anche allocare i vari oggetti Item (q->[0], q->[1], ...) usando la ItemGet().

Poi ritorni sempre e solo oggetti (Item *) e se vuoi manipolarne il contenuto devi aggiungere funzioni a item.{c,h} tipo:
Codice: Seleziona tutto
void setWord(Item *, char*);
setNumber(Item*, int);
char *GetWord(Item *);
int GetNumber(Item *);


Il punto è che solo il file item.c può accedere alla struttura Item correttamente, perché solo lui sa com'è fatta. Questa è la programmazione ad oggetti in C che a me piace molto,
Emanuele
Linux Registered User #454438
Se pensi di essere troppo piccolo per fare la differenza, prova a dormire con una zanzara -- Dalai Lama
20/04/2013 - Io volevo Rodotà
Avatar utente
targzeta
Iper Master
Iper Master
 
Messaggi: 6195
Iscritto il: gio nov 03, 2005 14:05
Località: Carpignano Sal. (LE) <-> Pisa
Nome Cognome: Emanuele Tomasi
Slackware: current
Kernel: latest stable
Desktop: IceWM


Torna a Programmazione

Chi c’è in linea

Visitano il forum: Nessuno e 2 ospiti