Record e Tabelle in C++

Indice dei contenuti

Tabelle e Record

Nella programmazione quando si devono memorizzare grosse quantità di dati nella memoria centrale del calcolatore è opportuno definire delle strutture dati astratte costituite da una raccolta di tipi semplici aggregati attraverso un nome collettivo e identificati da un indice. Ad esempio la gestione di una rubrica telefonica può essere ottenuta definendo per ciascun soggetto il nome, cognome, l’indirizzo e il numero di telefono. Se i soggetti sono molti ad esempio già in numero superiore a 10, la gestione di queste informazioni diventa gravosa e pertanto si conviene organizzare tali informazioni in una struttura di tipo tabella in cui ogni riga costituisce il recapito telefonico di un soggetto. Una struttura dati di questo tipo in memoria centrale è detta appunto tabella, su memoria di massa (su un unità di memorizzazione tipo disco fisso, unità a dischetti) è detto file.
Per poter definire una tabella è importante definire la struttura dati elementare di cui è costituita la tabella: il record. Un record è una variabile strutturata eterogenea composta da elementi di tipo diverso e identificata da un nome collettivo. Ad esempio nell’esempio precedente si può definire un record di nome “recapito”. Le componenti del record sono detti campi. E’ utile quando si definisce in un algoritmo e quindi programma un record definire un modello di tale struttura che dia informazioni anche sulla dimensione del record (dimensione logica). La dimensione logica di un record è la somma delle dimensioni di tutte le dimensioni dei campi che formano il record stesso. Inoltre alcuni campi come quelli alfanumerici sono definiti dall’utente altri come quelli numerici hanno dimensioni prefisssate e la loro dimensione varia a seconda del linguaggio di programmazione in cui si codifica l’algoritmo. Ipotizzando che i numeri interi si rappresentano con interi di 2 o 4 byte a massimo e che i numeri reali da 4 a 16 byte non è difficile calcolare la dimensione logica del record.
Infatti ogni carattere alfanumerico in base alla sua codifica ASCII occupa lo spazio di un solo byte o di almento due byte nella rappresentazione Unicode. Nell’esempio introduttivo se ne rappresenta il tracciato record che è una rappresentazione formale della struttura dati (modello) che il programmatore definisce.

Nell’esempio proposto il tracciato record è:

Recapito
CognomeNomeIndirizzoTelefono
15 caratteri15 caratteri50 caratteri10 caratteri
Dimensione logica 90 caratteri = 90 byte in codifica ASCII 8 bit o 180 in codifica Unicode

Poiché il programmatore nel problema ha necessità di avere più record dello stesso tipo allora si definisce una tabella una variabile strutturata identificata da un nome collettivo in cui ogni singolo record è individuato da un indice intero.

Selezione di un campo specifico in un record e di un campo specifico nella tabella.

L’operazione di selezione di un campo specifico all’interno di un record avviene secondo la nomenclatura nome-record.nome-campo ad esempio se nel record “recapiti” si vuole selezionare il campo “indirizzo” si scriverà recapiti.indirizzi. In una tabella se si vuole selezionare del decimo decimo record il campo “telefono” la nomenclatura adottata ipotizzando che il nome della tabella sia “tb” e l’indice della tabella e/o vettore di record i:

tb(10).telefono

Come esempio poniamo il seguente problema dato una tabella di N record del tipo “recapito” caricare la tabella.
L’utente inserisci a richiesta il numero dei contatti che devono essere inseriti nella tabella.
Un ipotesi

ClasseNomeTipo
Inputtbtabella di 100 elementi di tipo record
 
InputNIntero
internokintero indice della tabella

Non ci sono output perché l’algoritmo ci chiede solo di caricare la tabella. La variabile r viene definita a partire dal modello. In fase di codifica si definisce prima un tipo dati (il nostro modello) e poi in seguito una variabile strutturata a partire dal tipo definito.

  1. Inizio
  2. scrivi “Quanti contatti vuoi inserire ?”
  3. leggi N
  4. Ciclo k= 1 a N
  5. scrivi “dammi il cognome”
  6. leggi tb(k).cognome
  7. scrivi “dammi il nome”
  8. leggi tb(k).nome
  9. scrivi “dammi l’indirizzo”
  10. leggi tb(k).indirizzo
  11. scrivi “dammi telefono”
  12. leggi tb(k).telefono
  13. fine ciclo
  14. Fine

Il Flow chart del nostro algoritmo è:

Algoritmo di Caricamento Tabella

Utilizzo di strutture dati di tipo Record in C++

L’uso di tabella in C++ come strutture dati statiche avviene utilizzando le dichiarazioni di tipo. Infatti poichè il record per sua definizione è una struttura dati eterogenea definita dall’utente; è opportuno prima dichiarare la struttura come modello e poi utilizzare quel modello come tipo di variabile.

In altri temini si definisce il tipo di record con la seguente dichiarazione:

struct nome {

tipo nome;

tipo nome;

…..

tipo nome: };

Notare il punto e virgola dopo le parentesi graffe.

Dopo aver dichiarato la struttura del record, nella dichiarazione delle variabili si definisce un array che come tipo di variabile è proprio del tipo record dichiarato in precedenza.

L’algoritmo in C++ utilizzando il procedimento top-down senza parametri è:

#include <iostream>
#include <string>
using namespace std;
struct recapito {
    char cognome[15];
    char nome[15];
    char indirizzo[30];
    char telefono[10];
};
int n; // Numero contatti dato di input//
recapito tb[100]; // definisco una tabella di 100 record di tipo recapito //
// definizione procedura carica dati tabella //
void carica();
int main()
{
    cout << “\n Inserisci il numero dei contatti\t”;
    cin >> n;
    carica();
    return 0;
}  
void carica()
{ int k;
    for (k=0;k<n;k++)
    {
       {getchar();
        cout << “\n Inserisci il cognome\t”;
        cin.getline(tb[k].cognome,15);
        cout << “\n Inserisci il nome \t”;
        cin.getline(tb[k].nome,15);
        cout << “\n Inserisci indirizzo \t”;
        cin.getline(tb[k].indirizzo,30);
        cout << “\n Insrisci il numero di teleofno\t”;
        cin.getline(tb[k].telefono,10);
        cout << “Premi un tasto per continuare”;
}}
    }
}


Osservazioni sulla codifica in C++
Ogni programma, è conveniente quando deve eseguire più compiti, scomporlo in sottoprogrammi.
Per fare questo ogni compito del programma può essere associato ad un sottoprogramma. I sottoprogrammi sono dichiarati come prototipi subito dopo le dichiarazioni delle variabili globali, e dopo l’intestazione del programma (le sezioni che includno le librerie e altre clausole dichiarative). In seguito il main o funzione principale e poi l’implementazione dei sottoprogrammi dichiarati nella parte di prototipazione.
Possiamo riassumere la struttura di un programma in sotto programmi secondo questo schema:
Problematiche di sicurezza del codice:
Questo listato non protegge da attacchi buffer overflow sulle stringhe; infatti se l’utente supera il numero ei caratteri indicati nella getline i dati inseriti nelle stringhe successive saranno sovrascritti alterando il loro contenuto.
Una soluzione può essere quella di realizzare una piccola funzione che legga carattere per carattere i dati di input fin quando l’utente non digita il tasto invio.
La funzione potrebbe essere così scritta:

void leggi(char input[],int l)
{
    int k=0;
    while (( input[k!=’\n’) && (k<l)
        {
            input[k]=getchar();
            k++;
        }
}

Intestazione
Dichiarazione modelli dati e variabili globali
Prototipi delle funzioni
int main() // Programma principale
Implementazione delle funzioni

Nel programma proposto sono state utilizzate le funzionni  getchar() e getline che consentono un pieno controllo delle stringhe. La prima riceve in input un carattere anche una spaziatura, la seconda assicura che la variabile stringa anche se contiene spaziature sia integralmente inserita nella variabile di una lunghezza pari al secondo argomento della istruzione ad esempio

getline(variabile stringa,30);

consentirà all’utente l’input di una variabile di massimo 29 caratteri comprese le spaziature; da notare che l’ultimo carattere è utilizzato come terminatore di stringa “\0”.
La prima funzione quindi assicura che la prima spaziatura non sia l’input della prima istruzione di input del programma.


Per continuare a leggere questo articolo devi sottoscrivere un abbonamento
Puoi abbonarti al link al menù principale o cliccando sul link Abbonati Ora!