Programmazione C - problema di algoritmo

7 risposte [Ultimo messaggio]
Ritratto di anubis
anubis
(Guru)
Offline
Guru
Iscritto: 07/04/2007
Messaggi: 3656

Allora signori.. questa è la traccia:

data la struttura:

struct pers{
char cognome[MAX_LUNG];
char nome[MAX_LUNG];
char indirizzo[MAX_LUNG];
int  eta;
} anagrafica[MAX_ELE];

e dato il prototipo di funzione:

struct pers *findPerson(const struct pers *array, int array_size, char *cognome);

scrivere un programma che trovi le persone con il cognome corrispondente a quello ricercato.

in pratica si dovrebbe fare una query e riceve i dati delle persone con lo stesso cognome.

il mio codice:

/*
 * esercitazione-1.c
 * Copyright (C) Andrea Florio 2009 <andrea@opensuse.org>
 *
 * Polinomio is free software: you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Polinomio is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
#include <stdio.h>
#include <string.h>
#define MAX_LUNG 20
#define MAX_ELE 2
 
struct pers{
char cognome[MAX_LUNG];
char nome[MAX_LUNG];
char indirizzo[MAX_LUNG];
int  eta;
} anagrafica[MAX_ELE];
 
struct pers *findPerson(const struct pers *, int , char *);
void importPerson (struct pers *);
 
int main () {
 
int i;
 
 for (i=0; i<MAX_ELE; i++) {
    printf("Digitare i dati per la %d^ persona\n", i+1);
    importPerson(&anagrafica[i]);
    printf("\n");
    }
 
char surname[MAX_LUNG] = "";
printf("Digita il Cognome da ricercare:\n");
printf("(Attenzione e' case sensitive)\n");
scanf("%s", surname);
printf("\n");
 
 
struct pers *found;
 
found = findPerson(anagrafica, MAX_ELE, surname);
 
if (found == NULL) {
    printf("Non e' stato trovato nessun riscontro\n");
    return 0;
}
else {
 
    printf("La persona trovata e':\n");
    printf("Nome: %s\n", found->nome);
    printf("Cognome: %s\n", found->cognome);
    printf("Indirizzo: %s\n", found->indirizzo);
    printf("Eta': %d\n", found->eta);
    printf("\n");
}
 
#ifdef WIN32
    system("PAUSE");
#endif
 
return 0;
}
 
/* Questa funzione ha il difetto di terminare dopo aver trovato il primo elemento
 * la funzione restituisce un puntatore all'elemento individuato, se non
 * esiste alcun riscontro, la funzione ritornerà NULL
 */
 
struct pers *findPerson(const struct pers *anagrafica, int array_size, char *cognome) {
 
int i;
 
  for (i=0; i<array_size; i++) {
 
    if ( strcmp(anagrafica[i].cognome, cognome) == 0)
        return &anagrafica[i];
    }
 
    return NULL;
}
 
/* Inserisci i valori digitati dall'utente nella struttura */
void importPerson (struct pers *mystudente) {
 
// Il prototipo e' qui, per rispettare il minimo privilegio
    void strip_end (char *, int );
 
    printf("Digitare il nome:\n");
    fgets(mystudente->nome, MAX_LUNG, stdin);
    strip_end(mystudente->nome,'\n');
 
    printf("Digitare il cognome:\n");
    fgets(mystudente->cognome, MAX_LUNG, stdin);
    strip_end(mystudente->cognome,'\n');
 
    printf("Digitare l'indirizzo:\n");
    fgets(mystudente->indirizzo, MAX_LUNG, stdin);
    strip_end(mystudente->indirizzo,'\n');
 
    printf("Digitare l'eta':\n");
    scanf("\n%d", &mystudente->eta);
 
/* Devo intercettare "\n" o con un utilizzo ricorsivo
 * di questa funzione, il carattere "\n" andrebbe a
 * terminare l'fgets per aquisire il nome.
 */
    while( getchar()!='\n');
}
 
/* Questa funzione sostituice con "nul" l'ultima occorrenza del valore c
 * nella stringa s, in questo programma e' utilizzata per eliminare \n dalla
 * stringa importata da fgets, senza rimuoverlo infatti, la stringa non
 * corrispondera' mai con il campo di ricerca
 */
void strip_end (char *s, int c) {
 
    char *stripend;
    stripend = strrchr(s, c);
    if (stripend != NULL)
    *stripend = 0;
}

il problema è che la funzione è in grado di trovare solo la prima persona con quel cognome in caso di + persone con lo stesso congome.. idee??

OpenSUSE Member,Packman Packager, Education Project Admin, LXDE Project Admin
Powered by http://en.opensuse.org/HP_Pavilion_dv6855el

Ritratto di anubis
anubis
(Guru)
Offline
Guru
Iscritto: 07/04/2007
Messaggi: 3656

bug nella codifica del tag code..

il codice è qui:

http://pastebin.com/m4e869277

OpenSUSE Member,Packman Packager, Education Project Admin, LXDE Project Admin
Powered by http://en.opensuse.org/HP_Pavilion_dv6855el

Ritratto di cla90
cla90 (non verificato)
()

found punta alla struttura restituita da findperson

la soluzione piu' semplice sarebbe aggiungere un puntatore "pers *next" nella struttura pers

in findperson il ciclo deve arrivare fino a fine lista e ogni persona trovata deve essere 'appesa' letteralmente al puntatore *next della precedente, cosi' crei una lista di nodi...

alla visualizzazione fai un ciclo che alla fine di ogni nodo salta (tramite *next) al nodo successivo, finche' non trovi un *next che vale NULL

non so se mi sono spiegato bene...

------------x
p.s. ho scritto tempo fa un programma simile in c++, ma il succo e' lo stesso...
se ti puo' essere utile ti passo il sorgente

Ritratto di anubis
anubis
(Guru)
Offline
Guru
Iscritto: 07/04/2007
Messaggi: 3656

non ho studiato e quindi non posso usare,

pile, code, alberi ed allocazione dinamica della memoria...

la tua soluzioni riguarda quindi strutture ricorsive, che in teoria non avrei fatto Sad

inoltre sia la struttura, che il prototipo sono dati dalla traccia e non posso essere modificati

OpenSUSE Member,Packman Packager, Education Project Admin, LXDE Project Admin
Powered by http://en.opensuse.org/HP_Pavilion_dv6855el

Ritratto di cla90
cla90 (non verificato)
()

ah quindi sei vincolato...

altra soluzione:

crei un'array di puntatori a pers lungo quanto l'intera lista (potrebbero anche avere tutti lo stesso cognome)
e lo inizializzi tutto a null

nel ciclo in findperson scorri tutta la lista
ad ogni persona trovata scrivi il puntatore in una cella dell'array (partendo da arr [0] ovviamente)
per poi passare alla visualizzazione del risultato con un'altro ciclo che si passa l'array finche' non trova una cella null

cosi' sprechi lo spazio di tutte le celle dell'array rimaste inutilizzate, ma non dovresti aver problemi...

Ritratto di anubis
anubis
(Guru)
Offline
Guru
Iscritto: 07/04/2007
Messaggi: 3656

e visto che la funzione DEVE ritornare un puntatore a struct, potrei ritornare il puntatore al primo elemento dell'array..

me gusta.. ci provo subito

di funzionare funziona.. il problema è...

se devo rispettare la traccia (senza modificare il prototipo), faccio una cosa brutta, in quanto il vettore di puntatori è conosciuto dalla funzione in quanto facente parte della funzione chiamante.. se devo programmare come si deve però (e rendere portabile la funzione) , dovrei passare il nome del vettore alla funzione, e questo modificherebbe il prototipo..

uffaaa

Smile

OpenSUSE Member,Packman Packager, Education Project Admin, LXDE Project Admin
Powered by http://en.opensuse.org/HP_Pavilion_dv6855el

Ritratto di cla90
cla90 (non verificato)
()

per rendere portabile la funzione (senza conoscere l'elenco in precedenza) e fare una cosa pulita, l'unica via e' quella della lista di nodi concatenati credo...

Ritratto di anubis
anubis
(Guru)
Offline
Guru
Iscritto: 07/04/2007
Messaggi: 3656

per la cronaca, va con queste modifiche:

http://pastebin.com/m495dddba

OpenSUSE Member,Packman Packager, Education Project Admin, LXDE Project Admin
Powered by http://en.opensuse.org/HP_Pavilion_dv6855el