Passare puntatori a struct
Fa parte della sezione Logica e flusso del percorso C di Coddy. Lezione 47 di 63.
Sebbene passare le struct per valore funzioni bene per leggere i dati, diventa inefficiente con le struct di grandi dimensioni perché viene copiata l’intera struttura. Ancora più importante, non puoi modificare la struct originale dall’interno della funzione. È qui che diventa essenziale passare puntatori a struct.
Quando passi un puntatore a una struct invece della struct stessa, la funzione riceve l'indirizzo di memoria della struct originale. Questo approccio offre due vantaggi principali: è più efficiente (non viene effettuata alcuna copia) e consente alla funzione di modificare i dati originali.
La sintassi per una funzione che accetta un puntatore a una struct è:
void functionName(struct StructureName *ptr) {
// Corpo della funzione che usa ptr->member
}All'interno della funzione, usi l'operatore freccia per accedere ai membri della struct e modificarli. Qualsiasi modifica apportata tramite il puntatore influirà direttamente sulla struct originale nella funzione chiamante, rendendo questo approccio perfetto per le funzioni che devono aggiornare o trasformare i dati della struct.
Questa tecnica è fondamentale per creare programmi C efficienti che lavorano con strutture di dati complesse, poiché combina la potenza dei puntatori con l'organizzazione delle struct.
Sfida
FacileCrea un programma in C che dimostri il passaggio di puntatori a struct alle funzioni per modificare i dati in modo efficiente. Il programma deve:
- Definire una
structdenominataBankAccountcon i seguenti membri:- Un intero
accountNumberper memorizzare il numero del conto - Un array di caratteri
ownerNamedi dimensione 30 per memorizzare il nome del titolare del conto - Un float
balanceper memorizzare il saldo del conto - Un intero
transactionCountper memorizzare il numero di transazioni
- Un intero
- Scrivere una funzione denominata
depositMoneyche:- Accetti come parametri un puntatore a una struct
BankAccounte un importo di tipo float - Aggiunga l'importo al saldo del conto usando l'operatore freccia
- Incrementi di 1 il numero di transazioni
- Stampi
Deposit successful. New balance: [balance]
- Accetti come parametri un puntatore a una struct
- Scrivere una funzione denominata
withdrawMoneyche:- Accetti come parametri un puntatore a una struct
BankAccounte un importo di tipo float - Verifichi se l'importo del prelievo è maggiore del saldo corrente
- Se i fondi sono insufficienti, stampi
Insufficient funds. Current balance: [balance] - Se i fondi sono sufficienti, sottragga l'importo dal saldo, incrementi il numero di transazioni e stampi
Withdrawal successful. New balance: [balance]
- Accetti come parametri un puntatore a una struct
- Scrivere una funzione denominata
displayAccountche:- Accetti come parametro un puntatore a una struct
BankAccount - Stampi le informazioni del conto in questo formato esatto:
Account Information:Account Number: [accountNumber]Owner: [ownerName]Balance: [balance]Transactions: [transactionCount]
- Accetti come parametro un puntatore a una struct
- Nella funzione main:
- Creare una variabile
BankAccountdenominataaccount - Leggere dall'input il numero del conto, il nome del titolare e il saldo iniziale
- Impostare il numero di transazioni su 0
- Chiamare
displayAccountper mostrare lo stato iniziale del conto - Leggere un importo da depositare e chiamare
depositMoney - Leggere un importo da prelevare e chiamare
withdrawMoney - Chiamare
displayAccountper mostrare lo stato finale del conto
- Creare una variabile
Questa sfida dimostra l'efficacia del passaggio di puntatori a struct alle funzioni. A differenza del passaggio per valore, le funzioni ricevono l'indirizzo di memoria della struct originale, potendo così modificare direttamente i dati originali. Questo approccio è più efficiente (non avviene alcuna copia) e consente alle funzioni di modificare in modo permanente i valori della struct nella funzione chiamante.
Provalo tu
#include <stdio.h>
#include <string.h>
// TODO: Definisci qui la struct BankAccount
// TODO: Scrivi qui la funzione depositMoney
// TODO: Scrivi qui la funzione withdrawMoney
// TODO: Scrivi qui la funzione displayAccount
int main() {
// Leggi l'input
int accountNum;
char ownerName[30];
float initialBalance;
float depositAmount;
float withdrawAmount;
scanf("%d", &accountNum);
scanf("%s", ownerName);
scanf("%f", &initialBalance);
scanf("%f", &depositAmount);
scanf("%f", &withdrawAmount);
// TODO: Crea una variabile BankAccount e inizializzala
// TODO: Chiama displayAccount per mostrare lo stato iniziale
// TODO: Chiama depositMoney con l'importo da depositare
// TODO: Chiama withdrawMoney con l'importo da prelevare
// TODO: Chiama displayAccount per mostrare lo stato finale
return 0;
}Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.
Tutte le lezioni di Logica e flusso
1Fondamenti dei puntatori
Che cos’è un puntatore?Dichiarare i puntatoriL’operatore di indirizzo (&)L’operatore di dereferenziazione (*)Puntatori NULLRiepilogo: nozioni di base sui puntatori4Progetto: Utility di testo semplice
Panoramica del progettoConteggio dei caratteri2Puntatori e array
I nomi degli array come puntatoriElementi degli array e puntatoriAritmetica dei puntatoriConfrontare i puntatoriRiepilogo: attraversamento di un array con i puntatori5Puntatori e funzioni
Passaggio per valorePassare puntatori alle funzioniModificare le variabili tramite puntatoriUn esempio classico: scambiare valoriPassare array alle funzioniRiepilogo: argomenti puntatore nelle funzioni8Struct e puntatori
Puntatori a structL’operatore freccia (->)Passare le struct per valorePassare puntatori a structAllocazione dinamica delle structRiepilogo: modifica di una struct - puntatore3Array di caratteri e stringhe
Stringhe come array di charIl terminatore nullInput di stringhe con scanfUso di strlen()Uso di strcpy()Uso di strcat()Uso di strcmp()Riepilogo: funzioni di base per le stringhe6Gestione della memoria
Memoria Stack vs. HeapAllocazione dinamica - malloc()Usare sizeof() per l'allocazioneVerificare il fallimento dell'allocazioneLiberare la memoria con free()Allocare con calloc()Riepilogo: array dinamico9Progetto: Inserimento semplice di un contatto
Progetto: Definire una struct ContattoFunzione per creare un contattoEsercitati da solo: Compilatore C online