PI-ITBA / 2024_02

Consultas 2C 2024
4 stars 0 forks source link

jokesADT #179

Open pilarserrats opened 2 days ago

pilarserrats commented 2 days ago

Hola buenas tardes, estoy con problemas en la función addJoke ya que me tira SEGV en cat->chistes[cat->cantChistes].texto = realloc(cat->chistes[cat->cantChistes].texto, (i + BLOQUE_JOKES)); Se pedía implementar todas las funciones menos freeJokes y deleteCategory. Adjunto el archivo .h y luego mi .c

typedef struct jokesCDT * jokesADT;

// Devuelve un nuevo TAD para almacenar y recuperar chistes
jokesADT newJokes();

/* Libera toda la memoria reservada por el ADT */
void freeJokes(jokesADT jokes);

/* Agrega una categoría si es que no estaba 
*  Se asume que la categoría sólo contiene minúsculas, no
* es necesario validarlo
*/
void addCategory(jokesADT jokes, const char * category);

/**
* Agrega un nuevo chiste a una categoría. Si la categoría no existe
* entonces no agrega el chiste. No verifica si el chiste está repetido, 
* ya sea en la categoría dada o en otra
*/
void addJoke(jokesADT jokes, const char * category, const char * joke);

/*
* Retorna la copia de un chiste para una categoría. Debe elegir al azar
* entre los chistes de la categoría. Si la categoría no existe
* o no tiene chistes retorna NULL
*/
char * joke(jokesADT jokes, const char * category);

/*
* Elimina una categoría y todos los chistes de esa categoría
*/
void deleteCategory(jokesADT jokes, const char * category);

/* Retorna la cantidad de categorías */
size_t categoriesCount(const jokesADT jokes);

/*
* Retorna un vector con una copia de todas las categorías, ordenado
* alfabéticamente. La cantidad de elementos estará dada por la función
* categoriesCount. Si no hay categorías retorna NULL
*/
char ** categories(const jokesADT jokes);
#define BLOQUE 5
#define BLOQUE_JOKES 15

typedef struct chistesVec
{
    char * texto;  
    size_t lenChiste; 
}chistesVec;

typedef struct tNode
{
    const char * categoria; //String 
    chistesVec * chistes; //Vector de chistes 
    size_t dimChistes; 
    size_t cantChistes; 
    struct tNode * tail; 
}tNode;

typedef struct jokesCDT{
    tNode * list; //Lista con todos los chistes por categoria
    size_t cantCategories; 
}jokesCDT; 

jokesADT newJokes(){
    srand(time(NULL));
    return calloc(1, sizeof(jokesCDT));
}

static tNode * addCatRec(struct tNode * l, const char * category, int * added){
    int c; 
    if(l == NULL || (c = strcmp(l->categoria, category)) > 0){
        tNode * newNode = malloc(sizeof(tNode)); 
        newNode->categoria = malloc(strlen(category) + 1); 
        strcpy(newNode->categoria, category); 
        newNode->dimChistes = 0; 
        newNode->cantChistes = 0; 
        newNode->chistes = NULL; 
        newNode->tail = l; 
        *added = 1; 
        return newNode; 
    }

    if(c == 0){
        return l; 
    }

    l->tail = addCatRec(l->tail, category, added); 
    return l;
}

void addCategory(jokesADT jokes, const char * category){
    int added = 0; 
    jokes->list = addCatRec(jokes->list, category, &added); 
    jokes->cantCategories += added; 
}

static tNode * buscaCategoriaRec(tNode * l, const char * category){
    int c; 
    if(l == NULL || (c = strcmp(l->categoria, category)) > 0){
        return NULL; //No esta
    }

    if(c == 0){
        return l; 
    }

    return buscaCategoriaRec(l->tail, category); 
}

void addJoke(jokesADT jokes, const char * category, const char * joke){
    tNode * cat = buscaCategoriaRec(jokes->list, category); 

    if(cat != NULL){
        //Antes de agregarlo veo que haya espacio en el vector
        if(cat->dimChistes % BLOQUE == 0){
            cat->chistes = realloc(cat->chistes, (cat->dimChistes + BLOQUE) * sizeof(chistesVec)); 
            cat->dimChistes += BLOQUE; 
        }

        //Ahora si agrego el chiste al final del vector
        int i; 
        for(i = 0; joke[i]; ++i){
            //voy agrandando de a bloques cuando sea necesario el espacio para el texto
            if(i % BLOQUE_JOKES == 0){
                cat->chistes[cat->cantChistes].texto = realloc(cat->chistes[cat->cantChistes].texto, (i + BLOQUE_JOKES));
            }
          cat->chistes[cat->cantChistes].texto[i] = joke[i]; 
        }
        cat->chistes[cat->cantChistes].lenChiste = i;

        cat->chistes[cat->cantChistes].texto = realloc(cat->chistes[cat->cantChistes].texto, i + 1); 
        cat->chistes[cat->cantChistes].texto[i] = '\0'; 

        cat->cantChistes++; 
    }
 }

 static int randInt(int izq, int der){
    if(izq > der){
        int aux = der; 
        der = izq; 
        izq = aux; 
    }

    return rand() % (der - izq + 1) + izq;
}

char * joke(jokesADT jokes, const char * category){
    tNode * cat = buscaCategoriaRec(jokes->list, category); 
    if(cat == NULL || cat->cantChistes == 0){
        return NULL;
    }

    int jokeNbr = randInt(0, cat->cantChistes - 1); 
    char * jokeCopy = malloc(cat->chistes[jokeNbr].lenChiste + 1); 
    strcpy(jokeCopy, cat->chistes[jokeNbr].texto); 
    return jokeCopy;
}

size_t categoriesCount(const jokesADT jokes){
    return jokes->cantCategories; 
}

char ** categories(const jokesADT jokes){
    char ** vec = NULL; 
    int dim = categoriesCount(jokes);
    if(dim != 0){
        vec = realloc(vec, dim * sizeof(char*)); //Guardo dim posiciones para un vector de punteros a char

        tNode * current = jokes->list; 
        tNode * prev = NULL; 
        for(int i = 0; i < dim && current != NULL; ++i){
            vec[i] = malloc(strlen(current->categoria) + 1);
            strcpy(vec[i], current->categoria); 
            prev = current; 
            current = current->tail; 
        }
    }
    return vec; 
}
marcelogarberoglio commented 2 days ago

Para poder usar realloc el puntero tiene que ser NULL o apuntar al heap, pero vos creaste/agrandaste el vector de esta forma

if(cat->dimChistes % BLOQUE == 0){ cat->chistes = realloc(cat->chistes, (cat->dimChistes + BLOQUE) * sizeof(chistesVec)); cat->dimChistes += BLOQUE; }

sin inicializar las nuevas posiciones, que tienen basura, por lo que cat->chistes[cat->cantChistes].texto no es NULL sino basura, por eso falla el realloc.