Practica del Curset de C avanxat per a operatas: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH! La practica ke haureu de fer es implementar modularment una aplicacio que treballi amb una llista de complexes. Esta pensat perque treballeu amb tres moduls. Un que implementi una llista generica. Un altre que implementi el tipus complexe. I un altre que contingui el main i que faci servir els altres dos. Si teniu dubtes sobre disseny modular fare un altre fitxeret amb una petita explicacio despres de Nadal. Si les dubtes sobre el tema de disseny modular es massa dur i no us deixa dormir, sempre teniu l'opcio d'enviar-me un `meil'. MODUL LLISTA GENERICA La majoria de vosaltres haureu implementat algun cop una llista dun tipus concret: parrella d'enters (alias Calcul Numeric), dades personals (alias Repetidors de PGMI) i d'altres que us hagin presentat. Us haureu adonat que el codi sempre es el mateix: crea, afegeix, esborra, consulta... Pero que si voleu fer-ho servir per un altre tipus nesqueu implementar una altra llista diferent. Varies de les coses que heu apres en el curset us permetran implemen- tar aquesta maravillosa llista generica que, un cop feta us estalviara molts mal de caps i nomes per 50$!!!!. Consell: Feu-la ben feta, es el modul que us sera mes util per altres practiques. Si heu sigut llestos i us heu saltat els paragrafs anteriors heu estat molt habils, nomes diuen que pollades. Es ara que entrem en materia. Be, com podem implementar una llista generica? I si fem una llista amb punters generics que puguin apuntar a qualsevol cosa? Be aquesta es la idea; una llista de punters generics on els nodes es definirien enaixi: typedef struct NODEGENERIC { void *v; struct NODEGENERIC *s; } nodegeneric; Llavors definiriem la llista com un punter al fantasma (i un al actual si la voleu fer amb punt d'interes) typedef struct LLISTAGENERICA { void *act, *cap; } llistagenerica; PROBLEMES: Tenim els problemes derivats de desconeixer el tipus de dades que contenen. Son els que ara us explicare. El primer problema es que no sabem quin criteri agafar per ordenar-los. Ho haureu d'implementar afegint a la llista un camp que sigui... un punter a funcio! Ostia tu ja man fotut! No, tranquils, es mes facil del que sembla. Aquesta funcio rebra dos punter generics que apunten als elements a comparar i retornara un enter com el que torna el strcmp. La declaracio de la llista sera aixi: typedef struct LLISTAGENERICA { nodegeneric *act, *cap; int (*fcomp) (void*, void*); } llistagenerica; Quan crideu la funcio crea li pasareu el punter a la funcio que us vingui be segons el tipus que voleu fer servir a la llista. Arriba l'hora de inserir l'element que ens hauran passat com un punter; com l'inserim? Solucio explosiva (anonima): Com que es un punter igualem l->act->v=p i ja esta! Pobres ingenus. Aquest punter es totalment accesible des de fora del modul. Si fem un free(p), la nostra llista petara. Mes encara si canviem el valor de l'objecte al que apunta p fora de la llista, tambe canviara dins de la llista. Normalment aixo no interesa. Solucio Xapu (Vokimon): Fas un duplicat del objecte i el fas apuntar pel punter generic del node. El que passa es que com sempre no saps com es de gran l'objecte ni com copiar-lo. La meva solucio (jo pensava que genial) era fer-li a la llista un altre camp que se li passes com a parametre a crea i que ens digui el tamany del objecte per que des de fora si que ho saps fent un sizeof. char* temp1,temp2; int i; l->act->v=malloc (l->tamany); i=0; temp1=l->act->v; temp=p; while (i>tamany) { temp1*=temp2*; temp1++; temp2++; i++; } Aquesta copia bit a bit funciona be per estructures, vectors... pero i si el tipus es un com una altre llista o un arbre. Solucio legal (Xter): La solucio passa per afegir un parell de camps mes al cap de la llista. Un punter a funcio a la funcio de ocupacio de memoria i un altre a la funcio de copia. Penseu-vos per posar-ho a la memoria per que no podria ser una mateixa funcio. Jo no ho se, ke algu m'ho expliqui. Pot ser que a l'hora d'esborrar no basti amb alliberar memoria pot ser tambe seria bo afegir un altre punter a funcio per esborar oi? la vostra llista quedara definida aixi. typedef struct LLISTAGENERICA { nodegeneric *act, *cap; int (*fcomp) (void*, void*); void* (*falloc) (void); void (*fcopia) (void*,void*); void (*fborra) (void*); } llistagenerica; Maca, oi que si? ATENCIO: Heu de permetre que hagin implementades mes d'una llista i de tipus diferents. Ja sabeu, res de variables globals al modul. ATENCIO JR: Sobre la funcio de CONSULTA teniu dos opcions: - Duplicar la dada i retornar la dada duplicada. - Retornar el punter al mateix objecte dins de la llista. Si feu la primera quan programeu amb la llista haureu d'anar en compte de no cridarla sense que ningu rebi el valor. Perdreu unes possicions de memoria precioses. Si feu la segona haureu de tenir cura de que si modifiqueu el que us donen modificareu tambe la llista cosa que esta en contra de la filosofia de TAD's pero que es molt comuna als programatas de C. Tampoc us baralleu podeu fer les dos alhora si voleu. FLORITURES: Si ja heu acabat la practica i no sabeu que fer, podeu provar les seguents millores del modul llista generica. - Afegir a les funcions inserir, esborrar... una funcio d'aplicacio que se li passi la llista i un punter a funcio i el que faci sigui aplicar aquesta funcio a tot els elements de la llista. Prometo puntuar molt millor. Amants del LISP. - Permetre fer les dues funcions consulta d'adalt a la vegada. MODUL COMPLEXES (TAD complexes pels PMGII's) Aquest modul no te res d'especial. Ha de contindre la definicio del tipus complexe, les funcions tipiques amb complexes (suma, resta, modul... No us mateu massa) i les funcions de comparacio, copia... que fareu servir a la llista. Recordeu que els parametres de aquestes darreres funcions estan definits al modul llista com a void*. Quina estratagema podeu fer per definir la funcio de comparacio? Casting? Be si l'ester us ho va deixar pendent suposo que sera per que ho penseu, no us ho penso dir. Be, si, pero a canvi d'un sopar. MODUL MAIN Imaginacio al poder!! Per que poden servir els altres dos moduls junts? Aquest modul ha de ser sufientment dur i xorra com per comprovar que els altres dos funcionen de perla. ... I res mes. Aixo no es sembla res a un enunciat pero al menys us he xplicat la practica. Si teniu algun altre dubte envieu-me un mail. Els contesto i tot. Vokimon (is04060):.