PI-ITBA / 2024_02

Consultas 2C 2024
4 stars 0 forks source link

TP11EJ12 #158

Open lucaMesi opened 5 days ago

lucaMesi commented 5 days ago

Hola buenas tardes, queria consultar si estaba bien implementado el codigo de este ejercicio, por si hay algo que no es muy eficiente o si hay alguna forma mejor de hacerlo.

#include <stdio.h>
#include <string.h>
#include "12.h"
#include <stdlib.h>

typedef char elemType[20];

typedef struct tNodeClose * tListClose;

typedef struct tNode * tList;

typedef struct tNodeClose{
    elemType close;
    tListClose tailClose;
}tNodeClose;

typedef struct tNode{
    elemType person;
    tNodeClose * firstClose; //lista de allegados de first person
    int countClose;
    tList tail;
}tNode;

typedef struct socialCDT{
    tNode * firstPerson; //lista de personas con allegados
    int countPersons;
}socialCDT;

/* Crea un nuevo TAD vacío */
socialADT newSocial(){
    return calloc(1, sizeof(socialCDT));
}

//libera los allegados de c/persona 
static void freeCloseRec(tNodeClose * firstClose){
    if(firstClose != NULL){
        freeCloseRec(firstClose->tailClose);
        free(firstClose);
    }
}

static void freeSocialRec(tNode * firstPerson){
    if(firstPerson != NULL){
        freeSocialRec(firstPerson->tail);
        freeCloseRec(firstPerson->firstClose); // me libera los allegados de una persona
        free(firstPerson);
    }
}

/* Libera todos los recursos reservados por el TAD */
//llama a allegados rec tantas veces como haya de personas con allegados 
void freeSocial(socialADT soc){
    freeSocialRec(soc->firstPerson);
    free(soc);
}

static tList addPersonRec(tNode * listP, elemType newPerson, int * no_existe){
    if (listP != NULL && !strcmp(newPerson, listP->person)){
        return listP;
    }
    if (listP == NULL || strcmp(listP->person, newPerson) > 0){
        tList new = malloc(sizeof(tNode));//creo el nuevo nodo
        new->firstClose = NULL;// inicializo los allegados del nuevo nodo en NULL
        new->countClose = 0;
        strncpy(new->person, newPerson, sizeof(elemType)); // pongo el nombre de la persona   
        *no_existe = 1;
        new->tail = listP;
        return new;
    }
    listP->tail = addPersonRec(listP->tail, newPerson, no_existe);
    return listP;
}

/* Almacena una nueva persona. Si la persona existe, no hace nada
** Guarda una copia del nombre, no simplemente el puntero
*/
void addPerson(socialADT soc, const char * name){
    elemType newPerson;
    strncpy(newPerson, name, sizeof(elemType));

    int no_existe = 0;
    soc->firstPerson = addPersonRec(soc->firstPerson, newPerson, &no_existe);
    if (no_existe){
        soc->countPersons++;
    }
}

//agrega un allegado
static tListClose addRelatedRec(tNodeClose * listClose, const char * related){
    if (listClose == NULL || strcmp(listClose->close, related) > 0){
        tNodeClose * newClose = malloc(sizeof(tNodeClose));
        strcpy(newClose->close, related);
        newClose->tailClose = listClose;
        return newClose;
    }
    listClose->tailClose = addRelatedRec(listClose->tailClose, related);
    return listClose;
}

/* Si existe una persona con ese nombre, agrega la nueva relación
** Si la persona no existe, no hace nada
** Si related ya estaba relacionado, lo agrega repetido
** Almacena una copia de related, no simplemente el puntero
**
 */
void addRelated(socialADT soc, const char * name, const char * related){
    //busco la persona
    tList aux;
    for(aux = soc->firstPerson; aux != NULL; aux = aux->tail){
            //por si me pase en el orden alfabetico
        if (strcmp(aux->person, name) > 0){
            return;
        }
        if (!strcmp(name, aux->person)){
            //lo encontre
            aux->firstClose = addRelatedRec(aux->firstClose, related);
            aux->countClose ++;
            return;
        }
    }
}

static char ** relatedRec(tNode * person){
    char ** closePeople = malloc((person->countClose + 1) * sizeof(char *));
    tListClose aux;
    int i;
    for (i = 0, aux = person->firstClose; i < person->countClose; i++, aux = aux->tailClose){
        closePeople[i] = malloc(sizeof(elemType));
        strcpy(closePeople[i], aux->close);
    }
    closePeople[i] = NULL;
    return closePeople;
}

/* Retorna una copia de los nombres relacionados con una persona
** en orden alfabético.
** Para marcar el final, después del último nombre se coloca NULL
** Si la persona no existe, retorna un vector que sólo tiene a NULL como 
** elemento
 */
char ** related(const socialADT soc, const char * person){
    //busco la persona
    tList aux;
    for(aux = soc->firstPerson; aux != NULL && strcmp(aux->person, person) <= 0; aux = aux->tail){
        if (!strcmp(aux->person, person)){//lo encontre
            return relatedRec(aux);
        }
    }
    //si no lo encontre
    return  calloc(1, sizeof(char *));
}

static char ** personsRec(tNode * persons, int dim){
    char ** toReturn = calloc(dim + 1,sizeof(char *));
    tNode * aux;
    int j = 0;
    for (aux = persons; aux != NULL && j < dim; j++, aux = aux->tail){
        toReturn[j] = malloc(sizeof(elemType));
        strncpy( toReturn[j], aux->person, sizeof(elemType));
    }
    toReturn[j] = NULL;
    return toReturn;
}

/* Retorna una copia de los nombres de las personas en orden alfabético.
** Para marcar el final, después del último nombre se coloca NULL
** Si no hay personas, retorna un vector que sólo tiene a NULL como 
** elemento
 */
char ** persons(const socialADT soc){
    return personsRec(soc->firstPerson, soc->countPersons);
}
marcelogarberoglio commented 5 days ago

Si el máximo es 20 caracteres para el nombre elemtype debería tener 21 (y no como magic number). Y cuando hacés strncpy, si te pasan la longitud máxima o algo más largo no copia el cero, por lo que tendrías que colocar un cero al final, o sea

define MAX 20

typedef char elemType[MAX+1];

strncpy(newPerson, name, MAX); newPerson[MAX] = 0;

y para la respuesta no es necesario que uses strncpy, ya sabés que internamente no superás el máximo, además strncpy si es más corto completa con ceros, y no es necesario eso para la respuesta.

En addPersonRec llamás dos veces a strcmp, podrías llamarla una vez y guardar en una variable el resultado. Lo mismo en addRelated

en addRelatedRec no usás strncpy

en personsRec deberías usar malloc en vez de calloc, y cambiarle el nombre, me imagino que tu idea era hacerlo recursivo. De hecho todo ese código podría estar en persons

lucaMesi commented 4 days ago

Muchas gracias Marcelo