Closed ThomasR62875 closed 1 year ago
No podés hacer int c= strcasecmp(cats->catname, name); if(cats==NULL
Ya que primero desreferenciás cats y después preguntás si es NULL. Si lo probás, vas a ver que aborta cuando quiere agregar la primer categoría
También está mal strcpy(nuevacat->catname, name); primero hay que reservar memoria
Traten de hacer una prueba, en el enunciado tienen el programa de testeo
O por ejemplo creaRta modifica una copia de respuesta. Cuando la función termina respuesta sigue valiendo basura. Una función no puede modificar una variable si no se le pasa su valor izquierdo
Hola Marcelo, ahí me puse a ver las cosas que me corregiste. Cambie esas primeras lineas q estaban mal pero igualmente no logro que funcionen. Ahora estan así, y me sigue tirando sanitizer. Cual es el error dentro de strcasecmp?? (esquive unos assert para ver si las demas funciones andaban y tmb el error viene del strcasecmp) yo le paso dos vectores de chars en ambos lados, eso esta bien , verdad??
int c;
if(cats==NULL || (c=strcasecmp(cats->catname, name))>0)
Y lo último que me dijste, de la función creaRta fue una confusión mia, pero la intención era pasar el valor izquierdo. Con agregar otro asterico en el tipo de variable que recibe creaRta, pasar bien el "char * rta;" y poner ahora un adelante de rta cuando lo quiera usar dentro de esa función , ya estaria??
Las líneas que copiaste ahora están bien. Si compilaste con -g sanitizer te muestra cuál es la línea que arroja error. En todo caso pasá el código completo y cuál es el mensaje de error
En cuanto a creaRta podés pasar el puntero del puntero, pero me parece más simple que no sea void y retorne el nuevo puntero, por ejemplo como hace realloc, que le pasás el puntero actual y te devuelve el nuevo.
Me di cuenta que en el comentarioa anterior me olvide de decirte que me estas saltando un sanitizer en el primer assert;
wsiADT w = newWsi();
char ** v = authors(w, "politica");
assert(v[0]==NULL); // no hay autores
Hice los cambios que me recomendaste en la función creaRta (tmb vi errores q tenia de antes) y quedo así:
char ** creaRta(Phrase * phrase, char ** rta, int * dimrta, int * cantautores)
{ //copio el autor del nodo, y paso al proximo hasta llegar al final
if(phrase==NULL){ //legue al final asiq corto
return NULL;
}
int i;
for(i=0; phrase->who[i]; i++){
if(*dimrta % BLOQUE ==0){ //le guardo más espacio si lo necesita
rta[*cantautores]=realloc(rta[*cantautores], BLOQUE + *dimrta);
}
rta[*cantautores][i]=phrase->who[i]; //copio caracter por caracter
*dimrta+=1 ;
}
*cantautores++;
*dimrta=0;
rta= creaRta(phrase->tailp, rta, dimrta, cantautores);
return rta;
}
char ** authors(wsiADT wsi, const char * category)
{ //uso searchCat para ver si existe dicha categoria, en el caso de q si copio en un vector de strings todos los autores
int i, j, flagc=0;
tCat * catparametro;
searchCat(wsi->primerc, category, &flagc, catparametro);
if(flagc==1){ //encontro la cateogria
//voy a usar una funcion recursiva para recorrer la lista, e ir copiando uno por uno ya que los fui ordenando cuando los meti en la propia lista.
char ** respuesta;
int dim=0, cantautores=0;
respuesta = creaRta(catparametro->primerp, respuesta, &dim, &cantautores);
return respuesta;
}
return NULL;
}
Y sobre lo de strcasecmp, si lo estoy compilando con el -g sanitizer asiq te mando el código con el error: La primer funcion que usa el strcasecmp es :
tCat * addCatREC(tCat * cats, const char * name, int *flag) {
int c;
if (cats == NULL || (c = strcasecmp(cats->catname, name)) >
0) { //pasaron una lista vacia, se llego al final o alfabeticamente ya se paso, asiq creo el nodo con la nueva info y lo devuelvo
tCat *nuevacat = calloc(1, sizeof(tCat));
cpystr(nuevacat->catname, name);
nuevacat->tail = cats;
return nuevacat;
}
if ((c = strcasecmp(cats->catname, name)) > 0) {
tCat *nuevacat = calloc(1, sizeof(tCat));
cpystr(nuevacat->catname, name);
nuevacat->tail = cats;
return nuevacat;
}
if (c == 0) { //se encontro la cateogria asiq no debo agregar nada, solo activo el flag.
*flag = 1;
return cats;
}
//sigo buscando la cateogria.
cats->tail= addCatREC(cats->tail, name, flag);
}
El error que salta sobre la linea del strcasecmp es este:
Lo que dice el mensaje de error que aborta porque strcasecmp desreferencia un puntero NULL. Obivamente el error no está en strcasecmp sino en la llamada a la misma, en la línea 69, la función addCatRec. Eso es porque en catName dejás NULL cuando hacés cpystr(nuevacat->catname, name); no hay forma de que cpystr modifque la variable nuevacat->catname Por otro lado, en esa misma función no entiendo para que hacés el segundo if, si eso ya lo hiciste en el primer if, o sea: llamás a stracascmp pero ya sabemos que el resultado no va a ser mayor que cero
Uh me estoy chocando siempre con la misma pared con lo de pasar el valor derecho como variable en vez del izquierdo, perdon. Lo del segundo if no te lo deberia haber mandado, fue un intento para ubicar mejor el error.
Cambie la función a una forma recursiva para ir copiadno el name letra por letra, y me quedo así,:
char * cpystr(char * recibe, const char * name, int *dim)
{ //es un strcpy q tmb guarda memoria en el heap
if(name==NULL){
return recibe;
}
if(*dim % BLOQUE == 0) {
recibe = realloc(recibe, sizeof(char) * (*dim + BLOQUE +1));
}
recibe[*dim]=name[0]; //copia la primer letra del string name
*dim++; //guarde una letra, asiq le sumo dim
recibe= cpystr(recibe, name+1, dim);
return recibe;
}
tCat * addCatREC(tCat * cats, const char * name, int *flag) {
int c;
if (cats == NULL || (c = strcasecmp(cats->catname, name)) > 0) { //pasaron una lista vacia, se llego al final o alfabeticamente ya se paso, asiq creo el nodo con la nueva info y lo devuelvo
tCat *nuevacat = calloc(1, sizeof(tCat));
int dim=0; //dimensión usada en cpystr para saber cuando guardar más espacio
nuevacat->catname = cpystr(nuevacat->catname, name, &dim);
nuevacat->catname = realloc(nuevacat->catname, sizeof(char)*(dim+1)); //le reajusto la memoria q se le guardo
nuevacat->tail = cats;
return nuevacat;
}
if (c == 0) { //se encontro la cateogria asiq no debo agregar nada, solo activo el flag.
*flag = 1;
return cats;
}
//sigo buscando la cateogria.
cats->tail= addCatREC(cats->tail, name, flag);
}
Como en otro punto que te eh mandado por github salta el sanitizer en el if para saber si guardar más espacio if(*dim % BLOQUE == 0) la dim esta inicializada en 0 entonces nose porq una división hace saltar el sanitizer
¿Un copyStr recursivo? ¿Por qué te complicaste con eso? A mi me parece que el puntero name nunca se va a hacer NULL
La verdad lo volvi a mirar más tranquilo y si, cambie todo inecesariamente. Con solo pasar el valor izquiero al cpystr anteriror ya estaria bien ?? quedaria así
void cpystr(char ** recibe, const char * name)
{ //es un strcpy q tmb guarda memoria en el heap
int i;
for(i=0; name[i]; i++){
if(i%BLOQUE == 0){
*recibe = realloc(*recibe, sizeof(char)*(BLOQUE+1+i));
}
*recibe[i]=name[i];
}
*recibe = realloc(*recibe, i+1);
recibe[i]=0; //el 0 final
}
tCat * addCatREC(tCat * cats, const char * name, int *flag) {
int c;
if (cats == NULL || (c = strcasecmp(cats->catname, name)) > 0) { //pasaron una lista vacia, se llego al final o alfabeticamente ya se paso, asiq creo el nodo con la nueva info y lo devuelvo
tCat *nuevacat = calloc(1, sizeof(tCat));
cpystr(&nuevacat->catname, name);
nuevacat->tail = cats;
return nuevacat;
}
if (c == 0) { //se encontro la cateogria asiq no debo agregar nada, solo activo el flag.
*flag = 1;
return cats;
}
//sigo buscando la cateogria.
cats->tail= addCatREC(cats->tail, name, flag);
}
Seguís complicándote haciendo que copyStr sea void, no se por qué. Por ejemplo cuando hacés
*recibe[i]=name[i];
tiene mayor precedencia el corchete que el asterisco
Y acá usás recibe como si fuera un string, no un puntero a string
recibe[i]=0;
Cuanto más complejo hagan el código, más probable que tengan errores.
Buenas, segui intentando completar el codigo y me salto sanitizer en una linea dentro del searchCat. " encontro->catname = cats->catname; "
Pense que había sido q nunca le guarde memoria en el heap a ese string q iba a copiar (ademas de q así no se copia un string), asiq cambie la linea a " size_t dim; encontro->catname = cpystr(catnew, &dim); " pero también tira un sanitizer, y ahí ya me quede sin ideas de que puede ser el error.
void searchCat(tCat * cats, const char * catnew, int * flag, tCat * encontro)
{ //en el flag marca 1 si encontro la categoria, no lo cambia sino
//si la encuentra iguala a esa categoria el nodo encontro.
if(cats==NULL){ //llegue al final
return;
}
if(strcasecmp(cats->catname, catnew)==0){ //encontro la categortia, asiq la copio en el nuevo nodo, y corto la función
encontro->catname = cats->catname;
encontro->tail=cats->tail;
encontro->primerp=cats->primerp;
*flag=1;
return;
}
if(cats->tail==NULL){ //no encontro, y no hay más
return;
}
//no encontro ni llego al fin paso a la proxima cat
searchCat(cats->tail, catnew, flag, encontro);
}
Lo he mencionado más de una vez: no sé por qué se complican haciendo estas funciones void y pasando un puntero a la respuesta. Tal vez sea una nueva tendencia y yo me quedé en el pasado, pero haría que devuelva el valor que querés, sobre todo porque no todos los lenguajes permiten pasar un "valor izquierdo", así que la forma que copio abajo es fácilmente trasladable a otros lenguajes:
tCat searchCat(tCat cats, const char * catnew) {
if(cats==NULL){ //llegue al final
return NULL;
}
// TODO faltaría retornar NULL si encuentra uno mayor al que está buscando
if(strcasecmp(cats->catname, catnew)==0){
return cats;
}
return searchCat(cats->tail, catnew);
}
La forma en que vos lo hiciste es mucho más complicado, lo que te lleva a cometer errores importantes, como estar cambiando los tail: rompés la lista.
Hola me puse a hacer el recu del segundo parcial del cuatri pasado. Queria saber si estaba bien