Menú

Mostrar Mensajes

Esta sección te permite ver todos los mensajes escritos por este usuario. Ten en cuenta que sólo puedes ver los mensajes escritos en zonas a las que tienes acceso en este momento.

Mostrar Mensajes Menú

Mensajes - GominaTilted

#1
Esta función me da error al abrir el fichero y no entiendo muy bien por qué, si alguien me puede ayudar un poco se lo agradecería eternamente :p

/*
* función base de los consumidores
* - cada consumidor va volcando línea a línea el contenido del buffer
*   en el fichero cuyo nombre se le pasa como parámetro
*/
void *consumidor(void *arg)
{
    int fin = 0;
    char *s = arg, *b;
    pthread_t id;
    FILE *f;
   
    f = fopen(s, "w");
   
    if (f == NULL)
    {
        perror("Error abriendo fichero.\n");
        exit(1);
    }
   
    id = pthread_self();
   
   while(fin != 1)
   {
       if (buf_vacio(buf))
       {
           pthread_cond_wait(&cond_prod, &mtx);
       }
       else if (buf_vacio(buf) && terminar == 1)
       {
           fin = 1;
       }
       else
       {
          b = buf_quitar(buf);
          fputs(b, f);
          pthread_cond_wait(&cond_prod, &mtx);
    }
   }
   
   fclose(f);
   printf("Consumidor %lu: fichero de salida: '%s'.\n", id, (char *) s);
   
    return (void *) 1;
}
#2
Cita de: YreX-DwX en 23 Marzo 2020, 01:18 AM
Bueno... encontrado el error, te comento lo que he hecho para que en otra ocasión puedas encontrar el problema tú solo.
Primero he comentado todo el contenido del main() excepto las primeras líneas hasta la llamada a LeerFichero() para ver si el problema estaba en esa función o en las siguientes. El error está ahí así que he ido a LeerFichero(). Una vez aquí, he añadido una línea para ver el contenido en cada iteración:
Código (cpp) [Seleccionar]

while ( getline(fich_in, linea) ){
    cout << "\n#Contenido linea: " << linea << endl;
    Estudiante e;
    if ( StrToEstudiante(linea,e) )
        v.push_back(e);
}

Si compilas y ejecutas verás que sólo se llega a mostrar el contenido de la primera línea del fichero por lo que el error está en la primera iteración. Vamos entonces  a la función StrToEstudiante(). En esta función añadimos otra línea para ver cada token.
Código (cpp) [Seleccionar]

dato = ExtraerToken(texto);
cout << "#Dato extraido: " << dato << endl;
if ( dato.length() != 0 )

Vemos que todos los tokens se extraen correctamente por lo que el problema está en asignarValores(). Comentamos las líneas intermedias y las vamos descomentando una por una y ejecutando el programa con cada cambio. Aquí verás que el problema ocurre al descomentar setCurso() por lo que vamos ahí y... Resulta que estás haciendo una llamada recursiva a setCurso() desde setCurso() por lo que tenemos una recursividad infinita.



El tema de copiar funciones que ya tienes al final hace que te limites a un estilo de programación siempre igual que puede resultar en ocasiones ineficiente. Cada situación puede ocasionar una solución mejor.
Y respecto a tu otra duda, diría que sí, es habitual en el constructor modificar directamente los atributos privados. Así generas menos dependencias y un error en un set() no va a hacer que todos tus objetos se creen de forma incorrecta. Además ya habrás visto que al ir llamando funciones dentro de funciones, cuando tienes un problema tienes que empezar a buscar hacia dentro y cuantas más tengas, más laborioso será llegar al final.
PD: Otro tip es que uses siempre nombres de variables significativos. Si otra persona tiene que leer tu código (y nunca sabes cuando puede pasar eso) o tú mismo cuando tengas códigos con mucho tiempo de desarrollo detrás y los veas después de mucho tiempo, siempre será más complicado saber qué es esto:
Código (cpp) [Seleccionar]

string dato;
unsigned int campo;
string id, a, n;
char s;
int e, h, w;
string tit;
int curs;

Que esto:
Código (cpp) [Seleccionar]

string dato;
unsigned int campo;
string id, apellidos, nombre;
char sexo;
int edad, height, weight;
string titulo;
int curso;


Muchas gracias :). No había visto eso :/
#3
Ahora probaré, porque en dev-c++ explota todo (literalmente, no va, crashea el dev-c++)
#4
La verdad es que uso sublimetext y compilo en la consola de linux directamente, pero entraré a dev-c++  ;D
#5
Te comento, asignValores() lo piden así en el enunciado. Lo de las funciones me lo apunto, pero vamos nace de que la tarea es una tontería y la he querido hacer rápido cpy/paste de funciones iguales. El problema se da al leer de fichero en el main. Con un main más sencillo no da error, como este por ejemplo:

Código (cpp) [Seleccionar]

#include "estudiante.h"
#include <iostream>

using namespace std;

int main()
{
Estudiante e;
cout <<  "Soy una persona con estos datos: \n" << (Persona)e << endl;
return 0;
}


Solucioné un segmentation fault que daba en ese main por utilizar los set donde no debía (hacía comprobaciones innecesarias en asignarValores() y daba error). Para no leeros el código, estudiante es una clase hija de persona, y en esta se añaden dos set y se modifica el setID().

El archivo es este

SW106563;EL MASSOUDI MOLNE;LAURA ANTONIA;X;24;163;87;Grado en Geografía y Medio Ambiente;4
KG802920;IBARGUCHI FORNELLS;NOARA;M;24;160;47;Grado en Información y Documentación;1
P65091;SUEIRAS AKALAI;MAYORO;H;37;165;85
U03504;VIQUEIRA BUCATARU;ANGEL SERGIO;H;30;148;64
EM012710;IZETA BELSA;INMACULADA;M;22;178;104;Grado en Negocios Internacionales;1


En realidad es mucho más largo pero son datos con ese formato.

El error concreto es "Segmentation fault (core dumped)"

EDIT: Una duda que me surge, ¿sería más óptimo utilizar los set en el constructor o modificar los atributos privados directamente?
#6
Programación C/C++ / Segmentation Fault ayuda
22 Marzo 2020, 17:24 PM
Buenas, antes de nada pedir perdón por el tocho de código. Tengo que arreglar un segmentation fault en mi programa pero no veo el error. Teóricamente el archivo que contiene el main no se puede modificar, pero creo que el error viene dado por acceder a un std::vector. También sospecho de la función asignValores(), pero no sé por qué podría fallar. Estos son los archivos implicados (acepto cualquier consejo a parte de el propio error).

Persona.h

#ifndef persona_H
#define persona_H
#include <iostream>
#include <string>
using namespace std;
class Persona
{
public:
Persona();
bool asignarValores(string, string, string, char, int, int, int);
bool setID(string);
bool setApellidos(string);
bool setNombre(string);
bool setSexo(char);
bool setEdad(int);
bool setEstatura(int);
bool setPeso(int);
string getID();
string getApellidos();
string getNombre();
char getSexo();
int getEdad();
int getEstatura();
int getPeso();
bool validarSexo(char);
bool validarEdad(int);
bool validarEstatura(int);
bool validarPeso(int);
friend ostream& operator<<(ostream&, Persona);

private:
string id;
string apellidos;
string nombre;
char sexo;
int edad;
int estatura;
int peso;

};

#endif


Persona.cpp

#include "persona.h"
#include <string>
Persona::Persona()
{
setID("Desconocido");
setApellidos("Desconocido");
setNombre("Desconocido");
setSexo('0');
setEdad(0);
setEstatura(0);
setPeso(0);
}

bool Persona :: asignarValores(string nid, string ap, string nom, char s, int e, int h, int w)
{
bool ok = false;

setID(nid);
setApellidos(ap);
setNombre(nom);
setSexo(s);
setEdad(e);
setEstatura(h);
setPeso(w);
ok = true;


return ok;
}

bool Persona :: setID(string nid)
{
id = nid;
return true;
}

bool Persona :: setApellidos(string ap)
{
apellidos = ap;
return true;
}

bool Persona :: setNombre(string nom)
{
nombre = nom;
return true;
}

bool Persona :: setSexo(char s)
{
bool ok = false;

if (validarSexo(s))
{
sexo = s;
ok = true;
}

return ok;
}

bool Persona :: setEdad(int e)
{
bool ok = false;

if(validarEdad(e))
{
edad = e;
ok = true;
}

return ok;
}

bool Persona :: setEstatura(int h)
{
bool ok = false;

if(validarEstatura(h))
{
estatura = h;
ok = true;
}

return ok;
}

bool Persona :: setPeso(int w)
{
bool ok = false;

if(validarPeso(w))
{
peso = w;
ok = true;
}

return ok;
}

string Persona :: getID()
{
return id;
}

string Persona :: getApellidos()
{
return apellidos;
}

string Persona :: getNombre()
{
return nombre;
}

char Persona :: getSexo()
{
return sexo;
}

int Persona :: getEdad()
{
return edad;
}

int Persona :: getEstatura()
{
return estatura;
}

int Persona :: getPeso()
{
return peso;
}

bool Persona :: validarSexo(char s)
{
bool ok = false;

if(s == 'M' || s == 'H' || s == 'O')
ok = true;

return ok;
}

bool Persona :: validarEdad(int e)
{
bool ok = false;

if(e >= 15 && e <= 100)
ok = true;

return ok;
}

bool Persona :: validarEstatura(int h)
{
bool ok = false;

if(h >= 30 && h <= 250)
ok = true;

return ok;
}

bool Persona :: validarPeso(int w)
{
bool ok = false;

if(w >= 25 && w <= 300)
ok = true;

return ok;
}

ostream& operator<<(ostream& out, Persona p)
{
out << p.getID() << ";";
out << p.getApellidos() << ";";
out << p.getNombre() << ";";
out << p.getSexo() << ";";
out << p.getEdad() << ";";
out << p.getEstatura() << ";";
out << p.getPeso() << endl << endl;

return out;
}


Estudiante.h

#ifndef estudiante_H
#define estudiante_H
#include <iostream>
#include <string>
#include "persona.h"
using namespace std;

class Estudiante: public Persona
{
public:
Estudiante();
bool asignarValores(string, string, string, char, int, int, int, string, int);
bool setTitulacion(string);
bool setCurso(int);
bool setID(string);
string getTitulacion();
int getCurso();
friend ostream& operator<<(ostream&, Estudiante);

private:
string titulacion;
int curso;
bool validarID(string);
bool validarCurso(int);
};

#endif


Estudiante.cpp

#include "persona.h"
#include "estudiante.h"
#include <string>

Estudiante :: Estudiante()
{
setID("Desconocido");
setApellidos("Desconocido");
setNombre("Desconocido");
setSexo('0');
setEdad(0);
setEstatura(0);
setPeso(0);
setTitulacion("Desconocido");
setCurso(0);
}

bool Estudiante :: asignarValores (string id2, string ap, string nom, char s, int a, int h, int w, string tit, int c)
{
bool ok = false;

setID(id2);
setApellidos(ap);
setNombre(nom);
setSexo(s);
setEdad(a);
setEstatura(h);
setPeso(w);
setTitulacion(tit);
setCurso(c);
ok = true;

return ok;
}

bool Estudiante :: setTitulacion(string tit)
{
titulacion = tit;

return true;
}

bool Estudiante :: setCurso(int c)
{
bool ok = false;

if (validarCurso(c))
{
setCurso(c);
ok = true;
}

return ok;
}

bool Estudiante :: setID(string id2)
{
bool ok = false;

if (validarID(id2))
{
Persona::setID(id2);
ok = true;
}

return ok;
}

string Estudiante :: getTitulacion()
{
return titulacion;
}

int Estudiante :: getCurso()
{
return curso;
}

ostream& operator<<(ostream& out, Estudiante e)
{
out << e.getID() << ";";
out << e.getApellidos() << ";";
out << e.getNombre() << ";";
out << e.getSexo() << ";";
out << e.getEdad() << ";";
out << e.getEstatura() << ";";
out << e.getPeso() << ";";
out << e.getTitulacion() << ";" << e.getCurso() << endl << endl;

return out;
}

bool Estudiante :: validarID(string id2)
{
bool ok = false;

if (id2[0] >= 'A' && id2[0] <= 'Z' && id2[1] >= 'A' && id2[1] <= 'Z')
ok = true;

return ok;
}

bool Estudiante :: validarCurso(int c)
{
bool ok = false;

if(c <= 4 && c >= 1)
ok = true;

return ok;
}


main.cpp

#include <iostream>
#include <fstream>
#include <vector>
#include "estudiante.h"

using namespace std;

/*
* Prototipos de las funciones empleadas,
* implementadas despues de main()
*/
string ExtraerToken(string&);
bool StrToestudiante (string, Estudiante&);
vector<Estudiante> LeerFichero(string);
Estudiante MasAlto (vector<Estudiante>);
Estudiante MasBajo (vector<Estudiante>);
Estudiante MasJoven (vector<Estudiante>);
Estudiante MasViejo (vector<Estudiante>);
unsigned int NumEstudiantesCurso (vector<Estudiante>, int c);

/*
* Programa principal
*/
int main ()
{
    const string NOMBRE = "personal.dat"; //Nombre del archivo de datos
    vector<Estudiante> misestudiantes; //Vector para almacenar estudiantes leidos
   
    cout << endl << "Leyendo archivo ... ";
    misestudiantes = LeerFichero(NOMBRE);
    cout << "Fin." << endl;
    cout << endl;
    cout << "*** Num. estudiantes correctamente leidos: " << misestudiantes.size() << " ***" << endl;
    cout << endl;
    cout << "1. Estudiante mas ALTO:" << endl;
cout << MasAlto(misestudiantes) << endl;
    cout << endl;
cout << "2. Estudiante mas BAJO:" << endl;
cout << MasBajo(misestudiantes) << endl;
    cout << endl;
    cout << "3. Estudiante mas JOVEN:" << endl;
cout << MasJoven(misestudiantes) << endl;
    cout << endl;
    cout << "4. Estudiante mas VIEJO:" << endl;
cout << MasViejo(misestudiantes) << endl;
    cout << endl;
cout << "5. Estudiantes por curso:" << endl;
for (unsigned int i = 1; i <= 4; i++)
cout << "\tCurso " << i << " = " << NumEstudiantesCurso(misestudiantes,i) << endl;

return 0;
}

/**********************************************************************/ /**
*
*  Extraer 1 token de información de la cadena separada por ';'
*  El token es eliminado de la cadena de entrada
*
*  @param [in,out]  s  Cadena de datos
*
*  @return  string con el token extraido
*
*/ /**********************************************************************/
string ExtraerToken(string & s)
{
    string res="";
    size_t pos;
   
    pos = s.find(";");
    if ( pos != string::npos )
    {
        res = s.substr(0,pos);
        s.erase(0,pos+1);
    }
    else
    {
        res = s;
        s = "";
    }
       
    return res;
}

/**********************************************************************/ /**
*
*  Asignar valores a un objeto Estudiante a partir de
*  una línea de texto con datos separados por ';'
*
*  @param [in]  texto  Linea de texto
*  @param [in,out]  est  Estudiante modificado
*
*  @retval  true   Ha sido posible asignar correctamente valores.
*  @retval  false  No ha sido posible asignar correctamente valores.
*
*/ /**********************************************************************/
bool StrToEstudiante (string texto, Estudiante& est)
{
    string dato;
    unsigned int campo;
    string id, a, n;
    char s;
    int e, h, w;
    string tit;
    int curs;
    bool ok = true;
   
    campo = 0;
    while ( ok && campo < 9 )
    {
        dato = ExtraerToken(texto);
        if ( dato.length() != 0 )
        {
            switch ( campo )
            {
                case 0: id = dato; break;
                case 1: a = dato; break;
                case 2: n = dato; break;
                case 3: s = dato[0]; break;
                case 4: e = stoi(dato); break;
                case 5: h = stoi(dato); break;
                case 6: w = stoi(dato); break;
                case 7: tit = dato; break;
                case 8:
                curs = stoi(dato);
                ok = est.asignarValores(id,a,n,s,e,h,w,tit,curs);
                break;
            }
            campo++;
        }
        else
            ok = false;
    }
    return ok;
}

/**********************************************************************/ /**
*
*  Leer fichero de datos, devuelve vector de Estudiantes
*
*  @param [in]  nom  Nombre del fichero
*
*  @return  vector de Estudiantes
*
*/ /**********************************************************************/
vector<Estudiante> LeerFichero(string nom)
{
    ifstream fich_in;
    vector<Estudiante> v;
    string linea;
   
    fich_in.open (nom);
   
    if (fich_in)
    {
        while ( getline(fich_in, linea) )
        {
            Estudiante e;
            if ( StrToEstudiante(linea,e) )
                v.push_back(e);
        }
           
        fich_in.close ();
    }
    else
    cerr << "LeerFichero: Error al abrir el archivo de datos." << endl;

    return v;
}

/**********************************************************************/ /**
*
*  Determina el estudiante más alto de un vector de Estudiantes
*
*  @param [in]  v  Vector de Estudiantes
*
*  @return  Estudiante de mayor estatura (el primero del vector)
*
*/ /**********************************************************************/
Estudiante MasAlto (vector<Estudiante> v)
{
unsigned int max;
Estudiante e;
if ( v.size() > 0 )
{
max = 0;
for (unsigned int i=0; i < v.size(); i++)
if (v[i].getEstatura() > v[max].getEstatura())
max = i;
e = v[max];
}
return e;
}

/**********************************************************************/ /**
*
*  Determina el estudiante más bajo de un vector de Estudiantes
*
*  @param [in]  v  Vector de Estudiantes
*
*  @return  Estudiante de menor estatura (el primero del vector)
*
*/ /**********************************************************************/
Estudiante MasBajo (vector<Estudiante> v)
{
unsigned int min;
Estudiante e;
if ( v.size() > 0 )
{
min = 0;
for (unsigned int i=0; i < v.size(); i++)
if (v[i].getEstatura() < v[min].getEstatura())
min = i;
e = v[min];
}
return e;
}

/**********************************************************************/ /**
*
*  Determina el estudiante más joven de un vector de Estudiantes
*
*  @param [in]  v  Vector de Estudiantes
*
*  @return  Estudiante de menor edad (el primero del vector)
*
*/ /**********************************************************************/
Estudiante MasJoven (vector<Estudiante> v)
{
unsigned int min;
Estudiante e;
if ( v.size() > 0 )
{
min = 0;
for (unsigned int i=0; i < v.size(); i++)
if (v[i].getEdad() < v[min].getEdad())
min = i;
e = v[min];
}
return e;
}

/**********************************************************************/ /**
*
*  Determina el estudiante más viejo de un vector de Estudiantes
*
*  @param [in]  v  Vector de Estudiantes
*
*  @return  Estudiante de mayor edad (el primero del vector)
*
*/ /**********************************************************************/
Estudiante MasViejo (vector<Estudiante> v)
{
unsigned int max;
Estudiante e;
if ( v.size() > 0 )
{
max = 0;
for (unsigned int i=0; i < v.size(); i++)
if (v[i].getEdad() > v[max].getEdad())
max = i;
e = v[max];
}
return e;
}

/**********************************************************************/ /**
*
*  Determina el nº de estudiantes de un curso de un vector de Estudiantes
*
*  @param [in]  v  Vector de Estudiantes
*  @param [in]  c  Curso a buscar
*
*  @return  número de estudiantes en el curso c
*
*/ /**********************************************************************/
unsigned int NumEstudiantesCurso (vector<Estudiante> v, int c)
{
unsigned int num = 0;

for (unsigned int i=0; i < v.size(); i++)
if ( v[i].getCurso() == c )
num++;
return num;
}
#7
Programación C/C++ / Re: Clase pila estática
31 Octubre 2019, 14:50 PM
Cita de: YreX-DwX en 31 Octubre 2019, 14:06 PM
Siempre que los objetos que se pasan como parámetro no se van a modificar es recomendable pasarlos constantes para asegurar que pase lo que pase no se va a modificar (como decirle al compilador "no me dejes modificar este objeto ni por error") y por referencia para que así se pase la dirección de memoria del objeto original y no se cree una copia local (ya que si no se pasa por referencia, se pasa por valor y entonces lo que se hace es crear una copia del objeto con su consiguiente gasto de memoria).
Muchas gracias, no lo sabía.
#8
Programación C/C++ / Re: Clase pila estática
31 Octubre 2019, 13:54 PM
Cita de: YreX-DwX en 31 Octubre 2019, 13:41 PM
El constructor de copia tiene un problema y es que le asignas 10 a <max> en vez de asignarle <p.max> ya que la longitud del nuevo tiene que ser la misma que la del que copias.
Y la función <Copiar()> tiene otro problema y es que estás incrementando <cima> pero en ningún momento la pones a -1 antes de empezar a incrementar y tampoco actualizas el valor de <max>. Además como ya no estás usando las funciones <Apilar()> y <Desapilar()> en la función <Copiar()> (y por tanto ya no estás modificando la original) ahora sí puedes (y debes) pasar el parámetro constante y por referencia.
No sabía si tenía que actualizar el valor de max, ya que como el array se crea en función de p.max, pero claro, no había pensado que interviene todo el objeto. El resto podría haber estado dándole vueltas 1 mes y no lo saco xD. Muchas gracias, ya va. ¿Por qué en la función copiar es conveniente pasar el objeto por referencia y ponerlo como const? Gracias de nuevo, esta es la última pregunta de verdad ^^.
#9
Programación C/C++ / Re: Clase pila estática
31 Octubre 2019, 12:48 PM
Ahora tengo dos constructores, el por defecto y el que le paso el tamaño de la pila. Todas las cosas que no tengan sentido en cuanto al planteamiento del problema es (como Altura y Altura2), tienen que ver con el enunciado de la práctica, está hecho para que si no te va la sobrecarga no te funcionen bien las recursivas con referencias.
Entonces a lo que iba, si le paso al de copia por parámetro el tamaño máximo de la pila no va, pero si no se lo paso lo ejecuta en bucle.
Mis constructores:
Pila::Pila()
{
    cima = -1;
    max = 10;
    accesos = 0;
   
    v = new int[max];
   
}

Pila::Pila(int n)
{
    cima = -1;
    max = n;
    accesos = 0;
   
    v = new int[max];
   
}

Pila::Pila (const Pila & p)
{
  cima = -1;
  max = 10;
  accesos = 0;
  v = new int[p.max];
  Copiar(p);
}

Pila::~Pila()
{
  delete[] v;
}


Y aquí Copiar() y la sobrecarga:

void Pila::Copiar(Pila p)
{
  delete [] v;
  v = new int [p.max];
  for (int i = 0; i <= p.cima; i++)
  {
    cima++;
    v[i] = p.v[i];
  }
}

const Pila& Pila::operator= (const Pila & p)
{
  cout << "Se ejecuta la sobrecarga" << endl;
  Copiar(p);
  return p;
}


La función Copiar() funciona bien, ya que al ponerle cout saca los valores correctos, entonces el error supongo que es del constructor de copia. Cuando no entra en bucle infinito me sale el error "double free or corruption (fasttop)", el cual he buscado en stack overflow pero no he entendido mucho, simplemente que es posible que al hacer la asignación libere el espacio de memoria de la parte derecha, no izquierda. Copia bien en la pila 2, pero la original la modifica y se queda 0 0 3 4, como si hubiese borrado las dos primeras posiciones o fueran espacios de memoria a los que no se puede acceder.
#10
Programación C/C++ / Re: Clase pila estática
30 Octubre 2019, 18:57 PM
Gracias, ya tengo la <Cimapila()>, estaba la asignación al revés. Supongo que en <Copiar()> sí que tengo que generar un espacio nuevo en memoria, ya así te aseguras que hay un espacio reservado, aunque creo que al crear el objeto se debería de reservar ese espacio, no lo entiendo muy bien. Al hacer la sobrecarga de la asignación estamos en el mismo caso. Lo que si que tendría que hacer es un "delete [] v" en el destructor en vez de <Vaciar()>, y creo que también en la sobrecarga del operador.
Te dejo la función <Copia()>, la sobrecarga y un pantallazo con los valores que obtengo al realizar la asignación:
const Pila& Pila::operator= (const Pila & p)
{
  delete[] v;
  v = new int[max];
  Copiar(p);
  return p;
}


void Pila::Copiar(Pila p)
{
  v = new int [max];
  for (int i = 0; i < p.cima; i++)
    v[i] = p.v[i];
}


https://ibb.co/LzQbPKT

PD: perdón no sé cómo se ponen imágenes xD.