C Funzione Push in uno Stack

Linguaggi di programmazione: php, perl, python, C, bash e tutti gli altri.
Avatar utente
mastone
Prode Principiante
Messaggi: 36
Iscrizione: mercoledì 29 ottobre 2014, 19:55
Desktop: LUBUNTU
Distribuzione: Ubuntu 14.04.1 LTS i686

C Funzione Push in uno Stack

Messaggio da mastone »

Continuo ad avere dubbi ed errori su una semplice funzione push in uno stack, sono parecchi mesi che non programmo in C.
Vi allego la mia funzione e i relativi errori che mi escono

Questo è l'header chiamato stack.h

Codice: Seleziona tutto

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


struct stackNode{
	char data;
	struct stackNode *nextPr;
};
typedef struct stackNode StackNode;
typedef StackNode *StackNodePtr;

int isOperator(char c);
int precedence(char operator1, char operator2);
void push(StackNodePtr *topPtr, char value);

Questa è la funzione push in c

Codice: Seleziona tutto

#include "stack.h"

void push(StackNodePtr *topPtr, char value)
{
	StackNodePtr *newNode; 
    newNode =(struct stackNode *)malloc(sizeof(struct stackNode));
    if( newNode != NULL ){
        newNode->data = value;
        newNode->nextPr = *topPtr;
        *topPtr = newNode;   
    }else
        printf( "***ERROR*** Non puoi allocare memoria per questo oggetto\n" );
} 
Gli errori che mi da sono:
[Error] request for member 'data' in something not a structure or union
[Error] request for member 'nextPr' in something not a structure or union
[Warning] assignment from incompatible pointer type [enabled by default]

Grazie ragazzi, devo rimettermi in corsa col C
Avatar utente
vbextreme
Entusiasta Emergente
Entusiasta Emergente
Messaggi: 1214
Iscrizione: domenica 12 gennaio 2014, 14:06
Desktop: lxde
Distribuzione: xubuntu 14.10

Re: C Funzione Push in uno Stack

Messaggio da vbextreme »

topptr deve essere un puntatore a puntatore.
Easy framework per il linguaggio C.
vbextreme hack your life
Avatar utente
mastone
Prode Principiante
Messaggi: 36
Iscrizione: mercoledì 29 ottobre 2014, 19:55
Desktop: LUBUNTU
Distribuzione: Ubuntu 14.04.1 LTS i686

Re: C Funzione Push in uno Stack

Messaggio da mastone »

topptr deve essere un puntatore a puntatore.
Grazie per avermi risposto, puoi spiegarmi perche deve essere un puntatore a puntatore?
Ho fatto come mi hai detto ma mi da sempre lo stesso errore sulle stesse righe
ti posto il tutto:
l'header

Codice: Seleziona tutto

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


struct stackNode{
	char data;
	struct stackNode *nextPr;
};
typedef struct stackNode StackNode;
typedef StackNode *StackNodePtr;

void push(StackNodePtr **topPtr, char value);
la funzione:

Codice: Seleziona tutto

void push(StackNodePtr **topPtr, char value)
{
	StackNodePtr *newNode; //variabile di tipo puntatore che punta allo stack
	newNode=(struct stackNode *)malloc(sizeof(struct stackNode));
    if( newNode != NULL ){
        newNode->data = value;
        newNode->nextPr = *topPtr;
        *topPtr = newNode;   
    }else
        printf( "***ERROR*** Non puoi allocare memoria per questo oggetto\n" );
} //push
e il main di prova:

Codice: Seleziona tutto

#include "stack.h"

main()
{
	char value;
	StackNodePtr *topPtr=NULL;
	
	printf("Stringa: ");
	scanf("%c",value);
	push(topPtr,value);
	
}
L'errore potrebbe essere la malloc nella funzione..?
Devo scriverla cosi:
newNode=(struct stackNode *)malloc(sizeof(struct stackNode));

oppure

newNode=malloc(sizeof(struct stackNode));
Avatar utente
vbextreme
Entusiasta Emergente
Entusiasta Emergente
Messaggi: 1214
Iscrizione: domenica 12 gennaio 2014, 14:06
Desktop: lxde
Distribuzione: xubuntu 14.10

Re: C Funzione Push in uno Stack

Messaggio da vbextreme »

questo

Codice: Seleziona tutto

StackNodePtr *newNode;
è sbagliato, sicuramente volevi scrivere cosi:

Codice: Seleziona tutto

StackNodePtr newNode;
ti ho detto di usare un doppio puntatore perchè altrimenti non riesci a modificare il puntatore al top dello stack.
Easy framework per il linguaggio C.
vbextreme hack your life
fabio massacci
Scoppiettante Seguace
Scoppiettante Seguace
Messaggi: 289
Iscrizione: mercoledì 11 giugno 2014, 14:12
Desktop: Lubuntu
Distribuzione: Ubuntu 20.04.3 LTS

Re: C Funzione Push in uno Stack

Messaggio da fabio massacci »

StackNodePtr denota già un puntatore così come lo hai definito nel typedef, quindi come dice vbextreme la correzione è:

Codice: Seleziona tutto

StackNodePtr newNode;


però riguardo al parametro andava bene la prima versione, insomma riassumendo il tutto, e con qualche correzione al main (sempre per via di StackNodePtr):

Codice: Seleziona tutto

#include <stdio.h>
    #include <stdlib.h>
    #include <string.h>


    struct stackNode{
       char data;
       struct stackNode *nextPr;
    };
    typedef struct stackNode StackNode;
    typedef StackNode *StackNodePtr;

    void push(StackNodePtr *topPtr, char value);


    void push( StackNodePtr* topPtr, char value )
    {
       StackNodePtr newNode; //variabile di tipo puntatore che punta allo stack
       newNode=(struct stackNode *)malloc(sizeof(struct stackNode));
        if( newNode != NULL ){
            newNode->data = value;
            newNode->nextPr = *topPtr;
            *topPtr = newNode;
        }else
            printf( "***ERROR*** Non puoi allocare memoria per questo oggetto\n" );
    } //push


    int main()
    {
       char value;
       StackNodePtr topPtr=NULL;

       printf("Stringa: ");

       scanf( "%c", &value );
       push(&topPtr,value);

        printf( "ho ricevuto: %c\n", topPtr->data );

        return 0;
    }
Avatar utente
mastone
Prode Principiante
Messaggi: 36
Iscrizione: mercoledì 29 ottobre 2014, 19:55
Desktop: LUBUNTU
Distribuzione: Ubuntu 14.04.1 LTS i686

Re: C Funzione Push in uno Stack

Messaggio da mastone »

Grazie raga, però sia nella push che nella pop utilizzo puntatori a puntatori e nella chiamata passo per riferimento ( & ), ma in realtà non ho capito chiaramente il perchè, mentre ad esempio per restituire il valore in cima alla pila senza estrarlo dalla pila, utilizzo una funzione dove utilizzo solo il puntatore della cima della pila e non il puntatore a puntatore e la chiamata la faccio non per riferimento.

Dopotutto vi allego i warning che mi escono se vado a compilare da terminale

Il codice è questo:

Codice: Seleziona tutto

#include <stdio.h>
    #include <stdlib.h>
    #include <string.h>


    struct stackNode{
       char data;
       struct stackNode *nextPr;
    };
    typedef struct stackNode StackNode;
    typedef StackNode *StackNodePtr;

    void push(StackNodePtr *topPtr, char value);
void push( StackNodePtr* topPtr, char value )
    {
       StackNodePtr newNode; //variabile di tipo puntatore che punta allo stack
       newNode=(struct stackNode *)malloc(sizeof(struct stackNode));
        if( newNode != NULL ){
            newNode->data = value;
            newNode->nextPr = *topPtr;
            *topPtr = newNode;
        }else
            printf( "***ERROR*** Non puoi allocare memoria per questo oggetto\n" );
    } //push
int main()
    {
       char value;
       StackNodePtr topPtr=NULL;

       printf("Stringa: ");

       scanf( "%c", &value );
       push(&topPtr,value);

        printf( "ho ricevuto: %c\n", topPtr->data );

        return 0;
    }
Allegati
Immagine-min.jpg
fabio massacci
Scoppiettante Seguace
Scoppiettante Seguace
Messaggi: 289
Iscrizione: mercoledì 11 giugno 2014, 14:12
Desktop: Lubuntu
Distribuzione: Ubuntu 20.04.3 LTS

Re: C Funzione Push in uno Stack

Messaggio da fabio massacci »

scusa ma nel tuo ultimo post dalla figura sembra che tu sia andato a compilare qualcosa d'altro rispetto al codice che alleghi, infatti il codice messo su di un file lo compilo senza problemi...

per quel che riguarda i puntatori credo che tu abbia un po' di confusione forse generato dalle typedef che sono solo un modo per rinominare le i tipi in modo più comodo(a volte...): ti ripeto che così come lo hai dichiarato StackNodePtr è già un tipo puntato, quindi quando nel main dichiari la variabile topPtr quella è già un puntatore, quindi per passarlo ad esempio alla funzione push devi deferenziarlo ulteriormente una volta ancora attraverso l'operatore '&'.
Per essere più chiaro, le seguenti dichiarazione sono del tutto equivalenti:

Codice: Seleziona tutto

//così
StackNodePtr topPtr=NULL;

//oppure così
StackNode* topPtr=NULL;

//oppure così
struct stackNode* topPtr=NULL;
anche queste dichiarazioni di funzioni sono equivalenti:

Codice: Seleziona tutto

//così
void push(StackNodePtr* topPtr, char value);

//oppure così
void push(StackNode** topPtr, char value);

//oppure così
void push(struct stackNode** topPtr, char value);
mentre ad esempio per restituire il valore in cima alla pila senza estrarlo dalla pila, utilizzo una funzione dove utilizzo solo il puntatore della cima della pila e non il puntatore a puntatore e la chiamata la faccio non per riferimento
se vuoi fare un cambiamento ad un puntatore (ad esempio mediante una push) devi passarlo alla funzione tramite un altro puntatore perchè il puntatore più esterno (cioè l'ultima deferenziazione tramite & che si vede nel main) viene copiato all'interno della funzione, la copia viene usata e poi viene distrutta mentre il contenuto(cioè il primo puntatore) invece no ed è quello che vai a modificare nella push e che poi riprendi al suo esterno.
Sinceramente non so come spiegartelo più semplicemente a parole, magari con qualche grafico viene meglio ma non ho tempo adesso
Scrivi risposta

Ritorna a “Programmazione”

Chi c’è in linea

Visualizzano questa sezione: 0 utenti iscritti e 3 ospiti