marcelogarberoglio / PI

Para realizar consultas
6 stars 0 forks source link

EJ5-Segundo Parcial 2022-2C #272

Open santiagoBassi opened 1 year ago

santiagoBassi commented 1 year ago

Hola Marcelo, buenos dias. Queria saber si es correcta la resolucion del siguiente ejercicio. Adjunto el enunciado y el codigo, gracias!!

La Biblia consta de 76 libros, y cada libro está compuesto a su vez por versículos. Algunos libros tienen pocos versículos, por ejemplo 21, otros tienen más de 2000 (el libro Salmos contiene 2146 versículos). Cada versículo es un texto que puede ser corto o tener cientos de caracteres. Se creará un TAD para almacenar la Biblia completa, sabiendo que: ● Se la ingresará completa pero no necesariamente en orden (utilizando la función addVerse). Por ejemplo una persona puede estar agregando los primeros versículos del libro 1 (Génesis) mientras otra persona ingresa los últimos versículos del libro 6 (Josué) y otro los capítulos intermedios del libro 42 (Lucas). ● Se harán muchas consultas a la Biblia (utilizando la función getVerse) por un versículo en particular, para lo cual se indicará el número de libro y el número de versículo. El objetivo principal es que la función getVerse sea lo más eficiente posible. Se pide: Implementar el TAD completo

ej5ADT.c

#include <stddef.h>
#include <stdlib.h>
#include "ej3ADT.h"
#include "ej5ADT.h"
#include <stdio.h>
#define AMOUNT_BOOKS 76
#define BLOCK 10
#define BLOCK_VERSE 100

typedef struct book{
    char ** verses;
    size_t size;
    size_t max_verse;
}TBook;

typedef struct bibleCDT{
    TBook books[AMOUNT_BOOKS];
}bibleCDT;

bibleADT newBible(){
    return calloc(1,sizeof(bibleCDT));
}

/*
** Agrega un versículo a la Biblia. Si ya estaba ese número de versículo en ese
** número de libro, no lo agrega ni modifica y retorna 0. Si lo agregó retorna 1
** bookNbr: número de libro
** verseNbr: número de versículo
*/
int addVerse(bibleADT bible, size_t bookNbr, size_t verseNbr, const char * verse){
    if(bookNbr<=0 || bookNbr>AMOUNT_BOOKS  || verseNbr<=0){
        return 0;            //libro invalido o verseNbr invalido
    }

    if(verseNbr>bible->books[bookNbr-1].size){                                  //si el vers se pasa del vec, lo agrando
        bible->books[bookNbr-1].verses=realloc(bible->books[bookNbr-1].verses,(verseNbr+BLOCK)*sizeof(char *));
        for(int i = bible->books[bookNbr-1].size; i<verseNbr+BLOCK;i++){
            bible->books[bookNbr-1].verses[i]=NULL;
        }
        bible->books[bookNbr-1].size=verseNbr+BLOCK;
    }

    if(bible->books[bookNbr-1].verses[verseNbr-1]!=NULL){   //ya estaba ocupado
        return 0;
    }

    bible->books[bookNbr-1].verses[verseNbr-1]=verse;
    return 1;
}

static char * copyStr(const char * verse){
    int i=0;
    char *ans=NULL;
    while(*(verse+i)!='\0'){
        if(i%BLOCK_VERSE==0){
            ans=realloc(ans,sizeof(char)*(i+BLOCK_VERSE));
        }
        *(ans+i)=*(verse+i);
        i++;
    }
    ans=realloc(ans,sizeof(char)*(i+1));
    *(ans+i)='\0';
    return ans;
}
/*
** Retorna una copia de un versículo o NULL si no existe.
** bookNbr: número de libro
** verseNbr: número de versículo
*/
char * getVerse(bibleADT bible, size_t bookNbr, size_t verseNbr){
    if(bookNbr<=0 || bookNbr>AMOUNT_BOOKS|| verseNbr>bible->books[bookNbr-1].size || verseNbr<=0){
        return NULL;            //libro invalido o verseNbr invalido
    }
    char * ans=bible->books[bookNbr-1].verses[verseNbr-1];
    if(ans!=NULL){
        ans=copyStr(ans);
    }
    return ans;
}

/* Libera todos los recursos reservados por el TAD */
void freeBible(bibleADT bible){
    for(int i=0; i<AMOUNT_BOOKS;i++){
        if(bible->books[i].verses!=NULL){
            free(bible->books[i].verses);
        }
    }    
    free(bible);
}

ej5ADT.h

#include <stdlib.h>

typedef struct bibleCDT * bibleADT;
bibleADT newBible();
/*
** Agrega un versículo a la Biblia. Si ya estaba ese número de versículo en ese
** número de libro, no lo agrega ni modifica y retorna 0. Si lo agregó retorna 1
** bookNbr: número de libro
** verseNbr: número de versículo
*/
int addVerse(bibleADT bible, size_t bookNbr, size_t verseNbr, const char * verse);
/*
** Retorna una copia de un versículo o NULL si no existe.
** bookNbr: número de libro
** verseNbr: número de versículo
*/
char * getVerse(bibleADT bible, size_t bookNbr, size_t verseNbr);
/* Libera todos los recursos reservados por el TAD */
void freeBible(bibleADT bible);

ej5.c

#include "ej5ADT.h"
#include <assert.h>
#include <string.h>
#include <stdio.h>

int main(void) {

  bibleADT b = newBible();
  assert(getVerse(b, 1, 1) == NULL);

  char aux[2000];
  strcpy(aux, "En el principio creo Dios los cielos y la tierra.");
  assert(addVerse(b, 1, 1, aux) == 1);
  strcpy(aux, "Y atardecio y amanecio: dia tercero.");
  assert(addVerse(b, 1, 13, aux) == 1);
  assert(addVerse(b, 1, 13, "Amaos los unos a los otros") == 0); // Ya estaba
  strcpy(aux, "los contados de la tribu de Dan fueron sesenta y dos mil setecientos.");
  assert(addVerse(b, 4, 39, aux) == 1);
  assert(addVerse(b, 4, 46,"fueron todos los contados seiscientos tres mil quinientos cincuenta.") == 1);
  char *v = getVerse(b, 4, 45);
  assert(v == NULL);
  v = getVerse(b, 4, 39);

  assert(strncmp(v, "los con", 7) == 0);
  free(v);
  freeBible(b);
  puts("Aleluya !");
  return 0;
}
marcelogarberoglio commented 1 year ago

Fijate el ejemplo en main que usamos el mismo vector aux para almacenar distintos versículos, es justo el ejemplo que mencioné ayer en clase, entonces esto no está bien bible->books[bookNbr-1].verses[verseNbr-1]=verse; por otro lado, deberías hacer lo mismo que hicimos para el diccionario: almacenar la longitud del versículo. No es necesario usar BLOCK