Array di record

di il
2 risposte

Array di record

Chiedo gentilmente a chiunque abbia voglia di darmi una mano di dare un'occhiata a questo programma perchè credo sia completamente sbagliato soprattutto il codice del modulo che effettua l'inserimento in posizione
Mille grazie in anticipo!

/*ESERCIZIO n. 1
Scrivere un programma che consente all'utente di lavorare su una lista di persone che può variare da un minimo di 0 ad
un massimo di N elementi (dove N è una costante fissata, per esempio pari a 10). Ogni persona è caratterizzata da un
nome, cognome ed età.
Il programma deve effettuare le seguenti operazioni:
• Caricare i dati da un file con il seguente formato. Il file contiene i dati delle persone ordinate in base all’età
Cognome Nome Età
Rossi Mario 50
Bianchi Carlo 22
Biscardi Aldo 18
Biagi Luca 16
• Contare quante persone sono minorenni (età minore di 19)
• Inserire un elemento in posizione tale che l’età sia compresa tra altri due elementi della lista
Per esempio supponiamo di voler aggiungere: Sarti Anna 21. Occorre individuare la prima posizione della lista
che contiene l’età di una persona minore uguale di 21 considerando anche il valore memorizzato nella
posizione successiva. Dopo l’inserimento gestire opportunamente gli elementi successivi
• Stampare i dati della lista*/

#include <iostream>
#include <fstream>
using namespace std;

struct persone {
	string nome;
	string cognome;
	int eta;
};

const int N = 4;

void schermoMenu(int& scelta);
void convalidaStringa(string& s);
void caricaDaFile(persone persona[N], string nomeFile);
int contaMinorenni(persone persona[N]);
int trovaPos(persone persona[N], persone nuovaPersona);
void inserisciInPos(persone persona[N], persone nuovaPersona);
void stampaDati(persone persona[N]);

int main() {
	persone persona[N];
	string nomeFile;
	int scelta;
	persone nuovaPersona;
	while (true) {
		schermoMenu(scelta);
		if (scelta == 1) {
			cout << "\nInserisci il nome del file di testo da cui vuoi caricare i dati\n ";
			cin.ignore();
			getline(cin, nomeFile);
			caricaDaFile(persona, nomeFile);
		}
		if (scelta == 2) {
			cout << "\n_I minorenni nella collezione sono: " << contaMinorenni(persona) << endl;
		}
		if (scelta == 3) {
			cout << "\n_Acquisisci dati nuova persona, inserisci cognome:\n ";
			cin.ignore();
			convalidaStringa(nuovaPersona.cognome);
			cout << "\n_inserisci nome:\n ";
			convalidaStringa(nuovaPersona.nome);
			cout << "\n_inserisci eta':\n ";
			cin >> nuovaPersona.eta;
			while (nuovaPersona.eta <= 0) {
				cout << "\n_Errore l'eta' non puo' essere inferiore o uguale a zero, riprova:\n ";
				cin >> nuovaPersona.eta;
			}
			inserisciInPos(persona, nuovaPersona);
		}
		if (scelta == 4) {
			stampaDati(persona);
		}
		if (scelta == 0) {
			break;
		}
	}
	return 0;
}

void schermoMenu(int& scelta) {
	cout << "\t |MENU|\n ";
	cout << "\n_1.Carica i dati da un file\n ";
	cout << "\n_2.Conta i minorenni (eta' minore di 19)\n ";
	cout << "\n_3.Inserisci elemento in una posizione tale che l'eta' sia compresa tra altri 2 elementi\n ";
	cout << "\n_4.Stampa i dati della collezione\n ";
	cout << "\n_0.Termina applicazione\n ";
	cout << "\n___Scegli opzione: ";
	cin >> scelta;
	while (scelta < 0 || scelta > 4) {
		cout << "\n_Errore opzioni disponibili da 0 a 4. Inserisci: ";
		cin >> scelta;
	}
	return;
}

void caricaDaFile(persone persona[N], string nomeFile) {
	ifstream flussoDaFile(nomeFile.c_str());
	for (int i = 0; i < N; i++) {
		flussoDaFile >> persona[i].cognome;
		cout << "*debugC: " << persona[i].cognome << endl;
		flussoDaFile >> persona[i].nome;
		cout << "*debugN: " << persona[i].nome << endl;
		flussoDaFile >> persona[i].eta;
		cout << "*debugE: " << persona[i].eta << endl;
	}
	flussoDaFile.close();
	cout << "\nIl file e' stato letto\n ";
	return;
}

int contaMinorenni(persone persona[N]) {
	int conta = 0;
	for (int i = 0; i < N; i++) {
		if (persona[i].eta < 19) {
			conta++;
		}
	}
	return conta;
}

int trovaPos(persone persona[N], persone nuovaPersona) {
	for (int i = 0; i < N - 1; i++) {
		if ((nuovaPersona.eta >= persona[i].eta && nuovaPersona.eta <= persona[i + 1].eta) || (nuovaPersona.eta <= persona[i].eta && nuovaPersona.eta >= persona[i + 1].eta)) {
			return i;
		}
	}
	return -1;
}

void inserisciInPos(persone persona[N], persone nuovaPersona) {
	int pos = trovaPos(persona, nuovaPersona);
	if (pos == -1) {
		cout << "\n_L'eta' della persona acquisita non e' compresa fra nessuna delle altre\n ";
	} else {
		persona[pos].cognome = nuovaPersona.cognome;
		persona[pos].nome = nuovaPersona.nome;
		persona[pos].eta = nuovaPersona.eta;
		cout << "\n_Acquisizione inserita in lista\n ";
	}
	return;
}

void convalidaStringa(string& s) {
	getline(cin, s);
	while (s.size() <= 0) {
		cout << "\n_Errore stringa vuota, inserisici di nuovo:\n ";
		getline(cin, s);
	}
	return;
}

void stampaDati(persone persona[N]) {
	cout << "\t  |STAMPA DATI|\n ";
	for (int i = 0; i < N; i++) {
		cout << "\n ";
		cout << "\n_ " << i + 1 << " persona " << endl;
		cout << "\n_Cognome: " << persona[i].cognome << endl;
		cout << "\n_Nome: " << persona[i].nome << endl;
		cout << "\n_Eta': " << persona[i].eta << endl;
	}
	return;
}

2 Risposte

  • Re: Array di record

    Salve, Frank!
    Premetto di aver dato solo un'occhiata al codice, tuttavia ho notato un paio di cose che non funzionano.
    Anzitutto, la consegna prevede che nella lista vi siano un numero di elementi compreso fra 0 e N. Nella seguente sezione di codice, invece, chiedi a priori al programma di raccogliere i dati di N persone:
    
       for (int i = 0; i < N; i++) {		//E se nel file ci fossero meno di N persone?
          flussoDaFile >> persona[i].cognome;
          cout << "*debugC: " << persona[i].cognome << endl;
          flussoDaFile >> persona[i].nome;
          cout << "*debugN: " << persona[i].nome << endl;
          flussoDaFile >> persona[i].eta;
          cout << "*debugE: " << persona[i].eta << endl;
       }
    
    In mia opinione in questo caso conviene gestire in quest'altra maniera l'array:
    anzitutto, fra le dichiarazioni aggiungiamo un 'int num = 0;', che sarà il numero di posti dell'array effettivamente occupati.
    Dopodichè, potremmo riarrangiare il precedente frammento di codice nel seguente modo:
    
    while (flussoDaFile  && num < N)	//Il ciclo continuerà finchè non ci saranno errori nell'estrazione o non sarà raggiunta la dimensione massima
    {
    	flussoDaFile >> persona[num].cognome;
    	flussoDaFile >> persona[num].nome;
    	flussoDaFile >> persona[num].eta;
    	/*
    		I vari output di debug, se servono
    	*/
    	if (flussoDaFile)		//Se l'input è stato eseguito correttamente, allora incrementiamo il contatore
    	{
    		++num;
    	}				//In caso contrario, l'estrazione si concluderà e avremo in num il numero effettivo di elementi.
    }
    
    Con questa accortezza, sappiamo che la nostra lista contiene `num' elementi su un massimo di `N', come richiesto dall'esercizio.
    (Segue che in tutto il codice si dovrà utilizzare num, non N, come "limite superiore" della capienza dell'array)

    A questo punto il secondo errore che ho notato:
    
    ...
       else {
          persona[pos].cognome = nuovaPersona.cognome;
          persona[pos].nome = nuovaPersona.nome;
          persona[pos].eta = nuovaPersona.eta;
          cout << "\n_Acquisizione inserita in lista\n ";
       }
    
    Quello che accade in questo punto della funzione non è un'inserzione, ma una sostituzione del pos-esimo elemento con i dati di una nuova persona.
    Per implementare l'inserimento della persona, è sufficiente traslare tutto il contenuto dell'array a partire dall'elemento pos-esimo fino alla fine un posto più in là, e poi fare quel che hai scritto:
    
    ...
    else
    {
    	//Se num < N, allora incrementiamo num
    	if (num < N) ++num;
    	//A partire dall'ultimo elemento fino al pos-esimo, spostiamo tutto di un posto verso la fine
    	for (int i = num; i >= pos; --i)
    	{
    		//Se l'array contiene già N elementi, l'ultimo verrà scartato per far posto a quello nuovo
    		if (i+1 < N) persona[i+1] = persona[i];
    	}
    	//Infine, inseriamo nella posizione 'liberata' la nuova persona
    	persona[pos].cognome = nuovaPersona.cognome;
    	persona[pos].nome = nuovaPersona.nome;
    	persona[pos].eta = nuovaPersona.eta;
    }
    
    Sperando di non aver fatto a mia volta errori, questo è quanto son riuscito a scorgere di errato nel tuo codice.
    Saluti!
  • Re: Array di record

    Aaah va bene, grazie mille Brunplunsu per la risposta sei stato davvero gentilissimo a dedicarmi il tuo tempo!
Devi accedere o registrarti per scrivere nel forum
2 risposte