Newsgroup: it.comp.lang.c
Titolo: Aiuto!

Qualcuno mi aiuti per piacere.
Devo fare un progetto e ho qualche difficoltà con l'allocazione dinamica
della memoria e il conseguente ordinamento.
Metto qui di seguito il testo dell'esercizio così il santo che volesse darmi
qualche delucidazione avrà tutti i dati necessari per capire il problema.
Ringrazio anticipatamente chiunque voglia darmi una mano.
Ciao.
Chiara.
Esercizio:
In questo esercizio si deve costruire un programma modulare che prende una
sequenza di dati relativi al personale di un'azienda da una file di dati,
calcola un aggiornamento dello stipendio per tutti e riscrive il file con
l'elenco dei dipendenti con i dati aggiornati e ordinati in ordine
alfabetico, per cognome  e in caso di omonimia per nome.
Per scrivere correttamente questo programma si devono utilizzare le seguenti
caratteristiche del C:
  a.. funzioni di manipolazione di stringhe,
  b.. allocazione dinamica della memoria
  c.. funzioni di gestione di file I/O.
Il Problema.
L'input consisterà delle seguenti informazioni relative al personale:
nome
cognome
anzianità di servizio in anni, mesi e giorni,
stipendio.
L'anzianità di servizio é così espressa da tre interi, lo stipendio da un
float e nome, cognome da stringhe.
Il file di dati contiene un dato per linea, senza linee bianche, e la prima
linea contiene il numero dei dipendenti.
Per esempio il file di input può apparire così:
18
andrea
balsamo
15
11
4
12000.95
rita
colli
20
2
13
16000.82
.
L'algoritmo.
I dati saranno manipolati in un vettore di puntatori a una strutture
persVettPunt, dinamicamente allocato. I campi di tipo stringa della
struttura devono essere a loro volta dinamicamente allocati.
Lo stipendio va aggiornato sommando allo stipendio attuale l'uno per mille
dello stesso per ogni anno di anzianità e in proporzione per ogni mese e
giorno.
Il programma di ordinamento da utilizzare deve essere definito su vettori di
puntatori void, dovrà avere come parametri il vettore da ordinare, il numero
degli elementi del vettore e la dimensione in bytes del tipo puntato e la
funzione di confronto, come per esempio:
void selSort(void **a , const int n, size_t sizeEl,int (*confronto) ( void
*, void *));
Il formato dell'output.
Si deve visualizzare il file modificato come segue:
================================================
cognome     nome     anzianità: anni     mesi     giorni     stipendio
================================================
balsamo     andrea                     15     11         4         12192.05
colli             rita                        20     2         13
16324.05
..
La struttura del programma.
&deg; Scrivere la definizione di tipo per la struttura persDati
&deg; Il programma principale dovrebbe consistere di poche linee, relative
all'apertura e chiusura del file, alla chiamate delle funzioni che si
occupano della lettura dei dati, della loro manipolazione.
&deg; Si faccia in modo da rispettare il principio del minimo privilegio,
ogni funzione riceva tutti e soli i dati che sono necessari per la sua
esecuzione.

 dinamica della memoria e il conseguente ordinamento.
Farti tutto l'esercizio e` un po troppo :)
Per  quanto riguarda  l'allocazione dinamica  non vedo  grossi problemi.
Supponi di  aver definito una  "struct dipendente" che contiene  tutti i
campi richiesti dall'esercizio. Il numero di dipendenti e` noto a priori
(basta  leggere  la  prima  riga  del file),  non  devi  cimentarti  non
strutture dinamiche (leggi liste):
struct dipendente *dipendenti;
FILE *filein;
char buff[MAX_LINE_SIZE];
int ndip;
...
fgets(buff, sizeof(buff), filein);
sscanf(buff, "%d", &ndip);
dipendenti = malloc(sizeof(struct dipendente) * ndip);
assert(dipendenti);
Adesso  dipendenti punta  ad un'area  di memoria  grande abbastanza  per
contenere tutto l'elenco dei dipendenti. Inizia un ciclo while fino alla
fine  del file  che con  una serie  di fgets  ricostruisce ogni  struct.
Ricorca  che i  singoli elementi  dell'array possono  essere indicizzati
nella forma dipendenti[i], anche se dipendenti e` un puntatore.
L'algoritmo e` forse la parte  piu` complessa. Visto che devi cimentarti
con puntatori a funzioni io sceglierei questo approccio:
int less(struct dipendente *a, struct dipendente *b) {
        int r;
 
        if ((r = strcmp(a->cognome, b->cognome)) != 0)
	        return (r < 0)? 1: 0;
        /* Cognomi uguali */
        r = strcmp(a->nome, b->nome);
	return (r < 0)? 1: 0;
}
La funzione  opera un confronto  lessicografico prima sui cognomi  e, se
questi sono uguali,  sul nome. Restituisce 1 se  il primo identificativo
e` minore del secondo, 0 altrimenti.
Adesso serve una funzione per scambiare due elementi dell'array:
void swap(struct dipendente *s, int a, int b) {
        struct dipendente tmp;
        memcpy(&tmp, &s[a], sizeof(struct dipendente);
        memcpy(&s[a], &s[b], sizeof(struct dipendente);
        memcpy(&s[b], &tmp, sizeof(struct dipendente);
}
La  funzione  scambia  l'elemento  di  posizione  a  con  l'elemento  di
posizione b.
Adesso l'algoritmo di sort vero e proprio:
typedef int (*fcmp)(stuuct dipendente *, struct dipendente *);
void sel_sort(struct dipendente *v, int n, fcmp compare) {
        int i, j;
        for(i = 0; i < n; i++) {
                int min = i;
                for (j = i + 1; j < n; j++) {
                        if (compare(v[j], v[min)
                                min = j;
                }
                swap(v, i, min);
        }
}
La funzione andra` chiamata cosi`:
sel_sort(dipendenti, ndip, less);
Occhio che il codice non e` compilato, magari c'e` qualche errore...
Se hai problemi _specifici_ esponi pure i tuoi dubbi, ma ricorda che non
siamo qui` per fare i tuoi esercizi ;)
ciao
Kronos
-- 
Home: 
http://kronoz.cjb.net
Porc i' mond che cio' sott i piedi!
V. Catozzo

Se non ti disturbo vorrei avere un chiarimento sui tuoi preziosissimi
consigli (ringraziandoti ancora per la disponibilità).
Tutta la prima parte va bene ma quando vai a chiamare la Sel_sort fai quel
typedef di cui mi è sfuggito il significato e poi dentro la sel_sort, che
cosa è il compare?
Grazie ancora dell'aiuto.


> }
Il typdef l'ho messo per chiarezza. Ho dichiarato che il tipo fcmp e` un
puntatore  ad una  funzione che  restituisce  un intero  ed accetta  due
parametri di  tipo struct  dipendente * (puntatori  alla struttura). Nel
testo  dell'esercizio viene  mostrato  un prototipo  della funzione  che
accetta un puntatore alla funzione di comparazione, io ho seguito questa
indicazione.
A  questo  punto, all'interno  di  sel_sort,  compare  e` di  tipo  fcmp
(puntatore a funzione) e lo uso per confrontare i due elementi. L'ultimo
argomento che passo quando chiamo sel_sort  e` infatti 'less', che e` il
nome di una  funzione del tipo corretto. Se tu volessi  cambiare il tipo
di ordinamento dovresti solo passare  una funzione di confronto diversa,
lasciando inalterata la funzione di sort.
ciao
Kronos
-- 
Home: 
http://kronoz.cjb.net
Un apostolo vedendo Gesu` camminare sulle acque:
- Cazzo se e` buono 'sto fumo!!!

Credo che il problema reale sia la mia totale ignoranza in materia, però
all'interno della sel_sort il compilatore mi da un errore sul passaggio di
parametri.
Forse il punto è che sbaglio a definire la sel_sort.
Queste sono le definizioni che ho fatto:
typedef int (*fcmp)(struct dipendente*,struct dipendente*);
int less(struct dipendente*,struct dipendente*);
void swap(struct dipendente*,int, int);
void sel_sort(struct dipendente *, int , fcmp);
e credo che il problema sia proprio sull'ultima.
L'errore me lo da dentro la sel_sort quando viene invocato il compare:
void sel_sort(struct dipendente *v,int n,fcmp compare)
{
    int i,j;
        for(i=0;i<n;i++) {
                    int min=1;
                                for(j=i+1;j<n;j++) {
                                        if(compare(v[j],v[min])) min=j;
                                            }
                swap(v,i,min);
        }
}
Grazie ancora,  anche per le dritte circa le risposte. Avrai capito che non
sono molto pratica e il tuo aiuto mi è veramente molto utile1.
Grazie.
Chiara.

 if(compare(v[j],v[min])) min=j;
diventa
if (compare(&v[j], &v[min])) ...
-- 
Andrea Laforgia (
walkie...@libero.it
)
"Usenet is a strange place" [Dennis Ritchie]

 }
I prototipi e la funzione sono a posto. Con il gcc compilano senza alcun
warning.
ciao
Kronos
-- 
Home: 
http://kronoz.cjb.net
"La mia teoria scientifica preferita e` quella secondo la quale gli 
 anelli di Saturno sarebbero interamente composti dai bagagli andati 
 persi nei viaggi aerei." -- Mark Russel

 passi due strutture.
E` vero! Mi era proprio sfuggito...
ciao
Kronos
-- 
Home: 
http://kronoz.cjb.net
Se alla sera, dopo una strepitosa vittoria, guardandoti allo
specchio dovessi notare un secondo paio di palle, che il tuo 
cuore non si riempia d'orgoglio, perche` vuol dire che ti 
stanno inculando -- Saggio Cinese

if ((*compare)(v[j], v[min])) min = j;
E' assolutamente equivalente.
Il problema e' nel passaggio dei parametri.


 if(compare(v[j],v[min])) min=j;
Del min=i invece che uguale a 1 me ne sono accorta appena il programma è
partito.
Per compilare uso il gcc, e infatti passadogli i parametri giusti non ho
avuto nessun problema.
Grazie ancora.
Ciao
Chiara.

 > if(compare(&v[j],&v[min])) min=j;
ciao ciao
Chiara