Procedure tramite passaggio per indirizzo

di il
9 risposte

Procedure tramite passaggio per indirizzo

Salve, sto avendo qualche difficoltà nel rendere funzionante un programma che ho provato a scrivere, come esercizio per l'immagazzinare dati in struct, array tramite procedure che agiscono per passaggio indirizzo con i puntatori in C.
Ho creato, per vedere se tutto viene immagazzinato in maniera corretta, prima una procedura che immagazzini i valori e poi una che li stampi.
Però quando arrivo a quella che li stampa niente più quadra.
La cosa strana è che mettendo le stesse istruzioni della procedura per la lettura nella procedura per l'immagazzinamento, le istruzioni funzionano, quindi sembra come se i valori dei puntatori dei parametri formali non vengano effettivamente passati ai parametri attuali tramite indirizzo, e tra parametri attuali e formali, scanf ecc sono un po' confuso a questo punto.
Grazie.

/* Esercizatione passaggio parametri tramite indirizzo, piuttosto che copia-valore */

#include <stdio.h>

struct DescrizioniFatture{
    int NumLettereNome;
    char cliente[20];
    int giorno;
    int mese;
    int anno;
    float costo;
}Fattura1, Fattura2;

int main() {

    void DatiFattura(struct DescrizioniFatture *numlet, struct DescrizioniFatture *cl, struct DescrizioniFatture *gi,
                     struct DescrizioniFatture *me, struct DescrizioniFatture *ann,
                             struct DescrizioniFatture *cos); //Prototipo per l'immissione dati
    printf("Inserisci dati Fattura 1\n");
    DatiFattura(&Fattura1.NumLettereNome, &Fattura1.cliente, &Fattura1.giorno, &Fattura1.mese, &Fattura1.anno,
            &Fattura1.costo); //Immissione dati nella variabile Fattura1 di tipo struct DescrizioniFatture
            //Inserisco come dati l'indirizzo di memoria delle variabili interne

    printf("\nInserisci dati Fattura 2\n");
    DatiFattura(&Fattura2.NumLettereNome, &Fattura2.cliente, &Fattura2.giorno, &Fattura2.mese, &Fattura2.anno,
            &Fattura2.costo); //Immissione dati nella variabile Fattura2 di tipo struct DescrizioniFatture
            // Inserisco come dati l'indirizzo di memoria delle variabili interne


    void LeggiFattura(struct DescrizioniFatture *numlet, struct DescrizioniFatture *cl, struct DescrizioniFatture *gi,
                      struct DescrizioniFatture *me, struct DescrizioniFatture *ann,
                              struct DescrizioniFatture *cos); //Prototipo stampa dati
    printf("Dati fattura 1\n");
    LeggiFattura(&Fattura1.NumLettereNome, &Fattura1.cliente, &Fattura1.giorno, &Fattura1.mese, &Fattura1.anno,
                &Fattura1.costo); //Stampa i dati nella variabile Fattura1 di tipo struct DescrizioniFatture
    printf("Dati fattura 2\n");
    LeggiFattura(&Fattura2.NumLettereNome, &Fattura2.cliente, &Fattura2.giorno, &Fattura2.mese, &Fattura2.anno,
                &Fattura2.costo); //Stampa i dati nella variabile Fattura2 di tipo struct DescrizioniFatture

    return 0;
}

/* Immetto come parametri formali dei puntatori, che puntano agli indirizzi di memoria dei parametri attuali,
 * sovrascrivendoli in tempo reale*/

void DatiFattura(struct DescrizioniFatture *numlet, struct DescrizioniFatture *cl, struct DescrizioniFatture *gi,
        struct DescrizioniFatture *me, struct DescrizioniFatture *ann, struct DescrizioniFatture *cos)
{
    printf("Inserisci numero lettere nome cliente (<20)\n");
    scanf("%d", &numlet);
    printf("Inserisci le lettere del nome singolarmente\n");
    for(int i=0; i<numlet;i++){
        scanf(" %c", &cl[i]);
    }
    printf("Inserisci giorno\n");
    scanf("%d", &gi);
    printf("Inserisci mese\n");
    scanf("%d", &me);
    printf("Inserisci anno\n");
    scanf("%d", &ann);
    printf("Inserisci costo\n");
    scanf("%d", &cos);
}

void LeggiFattura(struct DescrizioniFatture *numlet, struct DescrizioniFatture *cl, struct DescrizioniFatture *gi,
                 struct DescrizioniFatture *me, struct DescrizioniFatture *ann, struct DescrizioniFatture *cos)
{
    printf("Lettere nome: %d\n", numlet);
    printf("Nome:\n");
    for(int i=0; i<numlet; i++)
    {
        printf(" %c",cl[i]);
    }
    printf("Giorno: %d\n", gi);
    printf("Mese: %d\n", me);
    printf("Anno: %d\n", ann);
    printf("Costo: %d\n", cos);
}

9 Risposte

  • Re: Procedure tramite passaggio per indirizzo

    Se ci dici cosa fare, passo passo, per replicare il tuo problema, si può cerca di capire le cause ...
  • Re: Procedure tramite passaggio per indirizzo

    Correggo dentro il codice.

    XSlayer50 ha scritto:


    
    /* Esercizatione passaggio parametri tramite indirizzo, piuttosto che copia-valore */
    
    #include <stdio.h>
    
    struct DescrizioniFatture{
        int NumLettereNome;
        char cliente[20];
        int giorno;
        int mese;
        int anno;
        float costo;
    }Fattura1, Fattura2;
    ->Non fare così, tieni separate definizione del tipo e dichiarazione delle variabili: ne guadagna la lettura.
    
    
    
    int main() {
    
        void DatiFattura(struct DescrizioniFatture *numlet, struct DescrizioniFatture *cl, struct DescrizioniFatture *gi,
                         struct DescrizioniFatture *me, struct DescrizioniFatture *ann,
                                 struct DescrizioniFatture *cos); //Prototipo per l'immissione dati
    ->non è il posto giusto per il prototipo, va fuori dal main. Inoltre la parola chiave struct non è necessaria. Inoltre SEMBRA che tu 
       non abbia  ben chiara cosa sia una struct! Stai definendo tante nuove struct fatte da un solo membro.
       Doveva essere così:
          void DatiFattura(DescrizioniFatture *UnaFattura);
          
          
    
    
    
        printf("Inserisci numero lettere nome cliente (<20)\n");
        scanf("%d", &numlet);
        printf("Inserisci le lettere del nome singolarmente\n");
        for(int i=0; i<numlet;i++){
            scanf(" %c", &cl[i]);
        }
    -> Non si inseriscono così le stringhe! Prima di andare avanti con cose complesse cerca di capire le basi.
        
    
  • Re: Procedure tramite passaggio per indirizzo

    In effetti, come ti dice Nicola, ci sono delle carenze di base di conoscenza del linguaggio che andrebbero prima colmante. Ti consiglio di studiare da un libro anche di base prima di scrivere codice.
  • Re: Procedure tramite passaggio per indirizzo

    Volendo posso anche fare
    typedef struct {}DescrizioniFatture;
    DescrizioniFatture Fattura1, Fattura2;
    Però pensavo che nel caso in cui non facessi questo, allora nella dichiarazione del parametro attuale il tipo fosse struct DescrizioniFatture, come quando dichiaro una variabile senza usare typedef, dato che in quel caso dovrei fare
    struct DescrizioniFatture Fattura 1;
    struct DescrizioniFatture Fattura 2;
    o sbaglio?

    Riguardo alla stringa so che andrebbe usata, solo che volevo spontaneamente allenarmi a operare con l'array, altrimenti l'avrei usata.
    Grazie invece per avermi detto del prototipo, i miei testi lo mettono dentro appena prima la chiamata.

    Comunque, corretto qualcosa (usato typedef per non immettere lo struct nella chiamata, messi i prototipi fuori e qualche piccolo accorgimento, il codice è questo, che comunque alla chiamata per la stampa dei valori da degli indirizzi piuttosto che i valori stessi, e poi dei caratteri à.
    /* Esercizatione passaggio parametri tramite indirizzo, piuttosto che copia-valore */
    
    #include <stdio.h>
    
    typedef struct {
        int NumLettereNome;
        char cliente[20];
        int giorno;
        int mese;
        int anno;
        float costo;
    }DescrizioniFatture;
    DescrizioniFatture Fattura1, Fattura2;
    
    void DatiFattura(DescrizioniFatture *numlet, DescrizioniFatture *cl, DescrizioniFatture *gi,
                     DescrizioniFatture *me, DescrizioniFatture *ann,
                     DescrizioniFatture *cos); //Prototipo per l'immissione dati
    void LeggiFattura(DescrizioniFatture *numlet,DescrizioniFatture *cl,DescrizioniFatture *gi,
                      DescrizioniFatture *me, DescrizioniFatture *ann,
                      DescrizioniFatture *cos); //Prototipo stampa dati
    
    int main() {
    
        printf("Inserisci dati Fattura 1\n");
        DatiFattura(&Fattura1.NumLettereNome, &Fattura1.cliente, &Fattura1.giorno, &Fattura1.mese, &Fattura1.anno,
                    &Fattura1.costo); //Immissione dati nella variabile Fattura1 di tipo DescrizioniFatture
        //Inserisco come dati l'indirizzo di memoria delle variabili interne
    
        printf("\nInserisci dati Fattura 2\n");
        DatiFattura(&Fattura2.NumLettereNome, &Fattura2.cliente, &Fattura2.giorno, &Fattura2.mese, &Fattura2.anno,
                    &Fattura2.costo); //Immissione dati nella variabile Fattura2 di tipo DescrizioniFatture
        // Inserisco come dati l'indirizzo di memoria delle variabili interne
    
    
        printf("\nDati fattura 1\n");
        LeggiFattura(&Fattura1.NumLettereNome, &Fattura1.cliente, &Fattura1.giorno, &Fattura1.mese, &Fattura1.anno,
                     &Fattura1.costo); //Stampa i dati nella variabile Fattura1 di tipo DescrizioniFatture
        printf("\nDati fattura 2\n");
        LeggiFattura(&Fattura2.NumLettereNome, &Fattura2.cliente, &Fattura2.giorno, &Fattura2.mese, &Fattura2.anno,
                     &Fattura2.costo); //Stampa i dati nella variabile Fattura2 di tipo DescrizioniFatture
    
        return 0;
    }
    
    /* Immetto come parametri formali dei puntatori, che puntano agli indirizzi di memoria dei parametri attuali,
     * sovrascrivendoli in tempo reale*/
    
    void DatiFattura(DescrizioniFatture *numlet, DescrizioniFatture *cl, DescrizioniFatture *gi,
            DescrizioniFatture *me, DescrizioniFatture *ann, DescrizioniFatture *cos)
    {
        printf("Inserisci numero lettere nome cliente (<20)\n");
        scanf("%d", &numlet);
        printf("Inserisci le lettere del nome singolarmente\n");
        for(int i=0; i<numlet;i++){
            scanf(" %c", &cl[i]);
        }
        printf("Inserisci giorno\n");
        scanf("%d", &gi);
        printf("Inserisci mese\n");
        scanf("%d", &me);
        printf("Inserisci anno\n");
        scanf("%d", &ann);
        printf("Inserisci costo\n");
        scanf("%f", &cos);
    }
    
    void LeggiFattura(DescrizioniFatture *numlet, DescrizioniFatture *cl, DescrizioniFatture *gi,
            DescrizioniFatture *me, DescrizioniFatture *ann, DescrizioniFatture *cos)
    {
        printf("Lettere nome: %d\n", numlet);
        printf("Nome:\n");
        for(int i=0; i<numlet; i++)
        {
            printf(" %c",cl[i]);
        }
        printf("Giorno: %d\n", gi);
        printf("Mese: %d\n", me);
        printf("Anno: %d\n", ann);
        printf("Costo: %f\n", cos);
    }
  • Re: Procedure tramite passaggio per indirizzo

    Guarda che ci sono tanti errori ... non te ne accorgi anche solo compilando?

    Per la stringa sbagli anche con l'array! Non controlli effettivamente il numero di caratteri che l'utente indica e soprattutto non imposti il terminatore a fine stringa.
  • Re: Procedure tramite passaggio per indirizzo

    Durante la funzione Datifattura non mi vengono segnalati errori (neanche provando a eseguirlo ovviamente), ma quando inizia la funzione Leggifattura si comporta in modo anomalo per poi terminare con errori.
    Inoltre sostituendo in DatiFattura il codice precedente con
        printf("Inserisci numero lettere nome cliente (<20)\n");
        scanf("%d", &numlet);
        printf("%d",numlet);
        printf("Inserisci le lettere del nome singolarmente\n");
        for(int i=0; i<numlet;i++){
            scanf(" %c", &cl[i]);
        }
    il printf("%d",numlet); restituisce correttamente il numero immesso, che infatti funziona e arresta il for una volta arrivato al numero indicato.
    Tuttavia la stessa stampa nella funzione LeggiFattura restituisce invece un indirizzo.
    Per questo non capisco cosa stia sbagliando, probabilmente nell'utilizzo del puntatore come parametro formale.
  • Re: Procedure tramite passaggio per indirizzo

    No ... stai sbagliando un sacco di cose, altro che solo il parametro formale.
    Intanto ti ripeto che NON hai inserito il terminatore della stringa ed è un problema. NON usare quell'input ma l'input classico di una stringa, se non lo conosci non ti inventare altro ma studialo.

    Non so con quale compilatore operi ma è praticamente impossibile che tu non abbia segnalazioni.

    Nella struttura il numerodilettere non ha alcun senso. Toglilo.

    Il prototipo della prima funzione sarà semplicemente
    
    void DatiFattura(DescrizioniFatture *fatt);
    
    lo userai nel main così
    
    DatiFattura(&Fattura1);
    
    e la funzione sarà
    
    void DatiFattura(DescrizioniFatture *fatt)
    {
    	printf("Nome cliente\n");
    	scanf("%19s", fatt->cliente);
    
    	printf("Inserisci giorno\n");
    	scanf("%d", &fatt->giorno);
    	
    	printf("Inserisci mese\n");
    	scanf("%d", &fatt->mese);
    	
    	printf("Inserisci anno\n");
    	scanf("%d", &fatt->anno);
    	
    	printf("Inserisci costo\n");
    	scanf("%f", &fatt->costo);
    }
    
    Segui il suggerimento senza ignorarlo. STUDIA da un libro, non andare a tentoni cercando di fare prove e controprove su cose che non hai studiato. Non arrivi da nessuna parte scrivendo per tentativi.
  • Re: Procedure tramite passaggio per indirizzo

    Non avevo mai letto del dover inserire manualmente un terminatore sul mio libro. Immagino sia per questo che hai inserito %19s invece che %20s, cioè per riservare la cella 19 (la ventesima o ultima) al carattere terminatore nel caso si arrivi ad essa? Quindi in questo caso nell'array stringa avrei il numero di celle specificato -1, quindi specificandone 20, una è inassegnabile se ho ben capito.

    Grazie comunque, quell'utilizzo col singolo puntatore è molto più corretto, e ora il programma funziona correttamente.
  • Re: Procedure tramite passaggio per indirizzo

    Non è "molto più corretto" ... è solo corretto. Quello che hai scritto tu non era "poco corretto" ma senza senso.

    Per la stringa sì, non so quale libro utilizzi ma cerca bene nel capitolo delle stringhe C ...
Devi accedere o registrarti per scrivere nel forum
9 risposte