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 - xaps

#71
Programación C/C++ / Re: Problema manejo de Pila
13 Febrero 2014, 00:56 AM
Cita de: erest0r en 13 Febrero 2014, 00:51 AM
Logre acomodarlo de forma que ahora si cumple su cometido, aunque buscare maneras mas eficientes de trabajarlo, estas son las 2 funciones que modifique:


int borrarTope( Pila *miPila )
{
    Nodo *nodo;
    int valor;

    if( miPila->ultimo == miPila->primero )
    {
        valor = miPila->ultimo->num;
        free( miPila->ultimo );
        miPila->primero = NULL;
        miPila->ultimo = NULL;
    }
    else
    {
        nodo = miPila->primero;

        while( nodo->sig != miPila->ultimo )
            nodo = nodo->sig;

        valor = miPila->ultimo->num;
        free( miPila->ultimo );
        miPila->ultimo = nodo;
        miPila->ultimo->sig = NULL;
    }

    return valor;
}

void borrarTodo( Pila *miPila )
{
    while( miPila->primero != NULL )
    {
        Nodo *nodo;
        nodo = miPila->primero;
        miPila->primero = miPila->primero->sig;
        free(nodo);
    }
}


De todas maneras, gracias por haberte tomado la molestia  :)

Ahora entiendo por que haces el while en borrarTope, tienes los punteros invertidos. Si inviertes la dirección de los punteros, obtendrás una clase pila mucho más eficiente. Sigo pensando que deberías mirarte el enlace, ya que tienes mal planteada la pila.

Saludos
#72
Programación C/C++ / Re: Problema manejo de Pila
13 Febrero 2014, 00:37 AM
Cita de: erest0r en 13 Febrero 2014, 00:13 AM
Gracias por el link, me pondre a leerlo, es solo que segun lei, en una pila se extrae el ultimo valor ingresado, y la solucion que me colocaste es para eliminar un elemento de una cola.

EDIT: Es decir mi puntero de nodo lo corro mientras su elemento puntero "sig" sea distinto a la ultima posicion para liberar la ultima posicion y luego hacer esa ultima posicion igual al mi puntero nodo. Pero cuando trato de mostrar despues la pila resultante, me empieza a mostrar valores locos.

El código que te he puesto hace la función POP, que es la que se encarga de eliminar el elemento superior de una pila.
Además, veo distintos errores en varias de las funciones que has programado, como por ejemplo en la función resetPila, que no te encargas de liberar la memoria de los diferentes nodos antes de perder las direcciones de memoria del primer y ultimo nodo. Tampoco te hace falta un puntero hacia el último elemento de la pila, ya que no vas a usarlo para nada (Recordemos que una pila es Last In First Out).
Mírate la clase Stack (Pila) del enlace que te he pasado, yo creo que te ayudará a entender mejor como funcionan las clases pila y cola, y si tienes alguna duda coméntalo y intentaré resolvértela.

Saludos
#73
Pues me pondré a ello, muchas gracias! ^^
#74
Programación C/C++ / Re: Problema manejo de Pila
13 Febrero 2014, 00:01 AM
No entiendo que haces en la función borrarTope. Para eliminar el primer elemento de la pila lo único que has de hacer es:

if(miPila->primero == miPila->ultimo)
{
 free(miPila->primero);
 miPila->primero = NULL;
 miPila->segundo = NULL;
}
else
{
 Nodo* nodo = miPila->primero;
 miPila->primero = miPila->primero->sig;
 free(nodo);
}


En cualquier caso, te recomiendo crear una clase pila y añadirle un parámetro int con el tamaño de la pila, que irías actualizando según añades o eliminas un elemento de la cola.

EDITO: Te añado un enlace hacia un aporte de hace unos meses en el que publiqué las clases pila y cola implementadas por mi. No serán las clases más eficientes que veas, pero te pueden servir para hacerte una idea. Enlace: http://foro.elhacker.net/programacion_cc/aporte_c_clases_pila_y_cola-t405322.0.html;msg1906527#msg1906527
#75
Buenas noches.
Estoy desarrollando una DLL para hookear una serie de procesos de una aplicación conectada a un servidor (es un cliente en lo que seria una conexión cliente-servidor). Pues bien, el hecho es que estoy controlando los paquetes que entran y salen mediante esta DLL y he implementado una pequeña función que envía paquetes legítimos a través del propio cliente.
El problema que tengo es que hay una serie de paquetes que necesitan una cierta diferencia de tiempo entre ellos, pero no puedo congelar la aplicación mientras espero ese tiempo (Por lo tanto, Sleep() y cualquier bucle que congele la aplicación quedan descartados), por lo que me estoy planteando utilizar multithreading, pero antes quería preguntaros si se os ocurre alguna otra forma de hacer esto. ¿Quizás una cola de paquetes y alguna manera de controlar cuándo se mandan a la función SendPacket?

Gracias :)
#76
¿Que es lo que no te sale? ¿Que has hecho hasta ahora? Nosotros no te vamos a hacer los deberes, si quieres que se te ayude muéstranos el trabajo que lleves hecho hasta ahora y nosotros intentaremos guiarte para que lo termines por ti mismo.

Saludos
#77
He desarrollado una clase Pila y una Clase cola para estudiar de cara a la universidad y se me ha ocurrido publicarla aquí, ya que estoy viendo publicaciones en las que se hacen preguntas sobre la implementación de estas clases y podrían ayudar a más de uno. Si alguien encuentra algún error que lo comente, por favor.

Aquí los archivos:

Stack.h
Código (cpp) [Seleccionar]
#include <cstddef>

template <class T>
class Stack
{
  private:
    struct Node
    {
      Node* nextNode;
      T data;
    };
   
    Node* topNode = NULL;
    int dataSize = 0;
   
    static Node* copyNode(Node* node)
    {
      Node* newNode = NULL;
      if (node)
      {
newNode = new Node;
newNode->data = node->data;
newNode->nextNode = copy(node->nextNode);
      }
      return newNode;
    }
    static void deleteNode(Node* node)
    {
      if (node)
      {
deleteNode(node->nextNode);
delete node;
      }
    }
   
  public:
    Stack();
    Stack(const Stack& original);
    ~Stack();

    T top() const;
    bool empty() const;
    int size() const;
   
    void push(const T& data);
    void pop();
    void clear();
   
    Stack& operator =(const Stack& original);
};

template <class T>
Stack<T>::Stack() {}

template <class T>
Stack<T>::Stack(const Stack &original)
{
  if (this != &original)
  {
    dataSize = original.dataSize;
    topNode = copy(original.topNode);
  }
}

template <class T>
Stack<T>::~Stack()
{
  deleteNode(this->topNode);
}

template <class T>
Stack<T>& Stack<T>::operator =(const Stack& original)
{
  if (this != &original)
  {
    dataSize = original.dataSize;
    deleteNode(topNode);
    topNode = copyNode(original.topNode);
  }
  return *this;
}

template <class T>
T Stack<T>::top() const
{
  return topNode->data;
}

template <class T>
void Stack<T>::push(const T& data)
{
  Node* newTop = new Node;
  newTop->data = data;
  newTop->nextNode = topNode;
  topNode = newTop;
 
  dataSize = dataSize + 1;
}

template <class T>
void Stack<T>::pop()

  Node* auxNode = topNode;
  topNode = topNode->nextNode;
  delete auxNode;
 
  dataSize = dataSize - 1;
}

template <class T>
bool Stack<T>::empty() const
{
  return (topNode == NULL);
}

template <class T>
int Stack<T>::size() const
{
  return dataSize;
}

template <class T>
void Stack<T>::clear()
{
  deleteNode(topNode);
  topNode = NULL;
  dataSize = 0;
}


Queue.h
Código (cpp) [Seleccionar]
#include <cstddef>

template <class T>
class Queue
{
  private:
    struct Node
    {
      T data;
      Node* prevNode;
    };
   
    int dataSize;
    Node* frontNode;
    Node* lastNode;
   
    static Node* copyNode(Node* node, Node* last)
    {
      Node* newNode = NULL;
      if(node)
      {
newNode = new Node;
newNode->data = node->data;
newNode->prevNode = copyNode(node->prevNode);
if (newNode->nextNode == NULL) last = newNode;
      }
      return newNode;
    }
   
    static void deleteNode(Node* node)
    {
      if(node)
      {
deleteNode(node->prevNode);
delete node;
      }
    }

  public:
    Queue();
    Queue(const Queue& original);
    ~Queue();
   
    T front() const;
    bool empty() const;
    int size() const;
   
    void push(const T &data);
    void pop();
    void clear();
   
    Queue& operator =(const Queue& original);
};

template <class T>
Queue<T>::Queue()
{
  dataSize = 0;
  frontNode = NULL;
  lastNode = NULL;
}

template <class T>
Queue<T>::Queue(const Queue& original)
{
  if (this != &original)
  {
    dataSize = original.dataSize;
    frontNode = copyNode(original.frontNode);
  }
}

template <class T>
Queue<T>::~Queue()
{
  deleteNode(frontNode);
}

template <class T>
T Queue<T>::front() const
{
  return frontNode->data;
}

template <class T>
bool Queue<T>::empty() const
{
  return (frontNode == NULL);
}

template <class T>
int Queue<T>::size() const
{
  return dataSize;
}

template <class T>
void Queue<T>::push(const T &data)
{
  Node* newNode = new Node;
  newNode->data = data;
  newNode->prevNode = NULL;
  if (!frontNode) frontNode = newNode;
  else lastNode->prevNode = newNode;
  lastNode = newNode;
 
  dataSize = dataSize + 1;
}

template <class T>
void Queue<T>::pop()
{
  Node* aux = frontNode;
  frontNode = frontNode->prevNode;
  delete aux;
 
  dataSize = dataSize - 1;
}

template <class T>
void Queue<T>::clear()
{
  deleteNode(frontNode);
  frontNode = NULL;
  lastNode = NULL;
  dataSize = 0;
}

template <class T>
Queue<T>& Queue<T>::operator =(const Queue& original)
{
  if (this != &original)
  {
    dataSize = original.dataSize;
    deleteNode(frontNode);
    frontNode = copyNode(original.frontNode);
  }
  return *this;
}


Saludos.
#78
Al usar templates has de incluir la implementación desde la cabecera de la clase añadiendo #include "tu_cpp.cpp" al final de tu archivo de cabecera.
Otra opción es la de tener la cabecera y la implementación en el mismo fichero, pero no lo recomiendo si el código es muy extenso.

Saludos
#79
Pues creo que voy a hacer lo que me ha dicho mi profesor, pondré las sobrecargas como miembros de la clase y aprovecharé para declararlas constantes.

En cuanto tenga una versión presentable la subo para que la veáis ^^

Gracias por la ayuda!

EDITO:

Ya he conseguido implementar la clase con templates. Os añado el código y a continuación os explico un poco que he hecho/modificado para que me funcione.

Matriz.h
Código (cpp) [Seleccionar]
#include <iostream>
 
using namespace std;

/*ostream y iostream no son templates, no entienden los cast dinámicos que se hacen con un template,
*es por esto que se necesita redefinir la clase y el método antes que el template, para convertirlo en template
*http://www.elrincondelc.com/nuevorincon/foros/viewtopic.php?t=13415&view=next&sid=02c39e45352bd867b56de65ebb1afd22
*/
template <class T> class Matriz;
template <class T> ostream& operator <<(ostream &salida, const Matriz<T> &mat);
template <class T> istream& operator >>(istream &entrada, Matriz<T> &mat);
/* --- */

template <class T> class Matriz {
 
private:
 
  int nfilas;
  int ncolumnas;
  T **matr = NULL;
 
  void borrar();
 
public:
 
  //Constructora
  Matriz(int filas, int columnas);
 
  //Constructora-copiadora
  Matriz(const Matriz& m);
 
  //Destructora
  ~Matriz();
 
  //Consultoras
  int filas() const;
  int columnas() const;
  T consultar(int fila, int columna) const;
 
  //Modificadora
  void modificar(int fila, int columna, T x);
 
  //Operadores
  Matriz<T>& operator =(const Matriz &b);
 
  void operator +=(const Matriz &mat);
  void operator -=(const Matriz &mat);
 
  Matriz<T> operator +(const Matriz &b) const;
  Matriz<T> operator -(const Matriz &b) const;
  Matriz<T> operator *(const Matriz &b) const;
 
  Matriz<T> operator *(int b) const;
//Matriz<T> operator *(int a, const Matriz &b); Está declarada como pública y externa a la clase
 
  bool operator ==(const Matriz &b) const;
  bool operator !=(const Matriz &b) const;
 
  friend ostream& operator << <>(ostream &salida, const Matriz<T> &mat);
  friend istream& operator >> <>(istream &entrada, Matriz<T> &mat);
};

template <class T>
Matriz<T>::Matriz(int filas = 0, int columnas = 0) : nfilas(filas), ncolumnas(columnas)
{
  if (nfilas > 0 and ncolumnas > 0)
  {
    matr = new T* [filas];
    for (int i = 0; i < filas; ++i) matr[i] = new T [columnas];
  }
}
 
template <class T>
Matriz<T>::Matriz(const Matriz &m)
{
  *this = m;
}
 
template <class T>
Matriz<T>::~Matriz()
{
  borrar();
}
 
template <class T>
void Matriz<T>::borrar()
{
  if (this->matr != NULL)
  {
    for (int i = 0; i < nfilas; ++i) delete[] matr[i];
    delete[] matr;
    matr = NULL;
  }
}
 
template <class T>
int Matriz<T>::filas() const
{
  return nfilas;
}
 
template <class T>
int Matriz<T>::columnas() const
{
  return ncolumnas;
}
 
template <class T>
T Matriz<T>::consultar(int fila, int columna) const
{
  return matr[fila][columna];
}
 
template <class T>
void Matriz<T>::modificar(int fila, int columna, T x)
{
  matr[fila][columna] = x;
}
 
template <class T>
Matriz<T>& Matriz<T>::operator =(const Matriz &mat)
{
  if (this != &mat)
  {
    this->borrar();
 
    if (mat.matr)
    {
      this->nfilas = mat.nfilas;
      this->ncolumnas = mat.ncolumnas;
 
      this->matr = new T* [nfilas];
      for (int i = 0; i < nfilas; ++i)
        this->matr[i] = new T [ncolumnas];
 
      for (int i = 0; i < nfilas; ++i)
      {
        for (int j = 0; j < ncolumnas; ++j)
          this->matr[i][j] = mat.matr[i][j];
      }
    }
  }
  return *this;
}
 
template <class T>
void Matriz<T>::operator +=(const Matriz &mat)
{
  if (this->nfilas != 0 and this->ncolumnas != 0 and mat.nfilas != 0 and mat.ncolumnas != 0)
  {
    for (int i = 0; i < nfilas; ++i)
      for (int j = 0; j < ncolumnas; ++j)
        this->matr[i][j] += mat.matr[i][j];
  }
}
 
template <class T>
void Matriz<T>::operator -=(const Matriz &mat)
{
  if (this->nfilas != 0 and this->ncolumnas != 0 and mat.nfilas != 0 and mat.ncolumnas != 0)
  {
    for (int i = 0; i < nfilas; ++i)
      for (int j = 0; j < ncolumnas; ++j)
        this->matr[i][j] -= mat.matr[i][j];
  }
}
 
template <class T>
Matriz<T> Matriz<T>::operator +(const Matriz &b) const
{
  int filas = this->nfilas;
  int columnas = this->ncolumnas;
 
  Matriz<T> res(filas, columnas);
 
  for (int i = 0; i < filas; ++i)
    for (int j = 0; j < columnas; ++j)
      res.matr[i][j] = this->matr[i][j] + b.matr[i][j];
 
  return res;
}
 
template <class T>
Matriz<T> Matriz<T>::operator -(const Matriz &b) const
{
  int filas = this->nfilas;
  int columnas = this->ncolumnas;
 
  Matriz<T> res(filas, columnas);
 
  for (int i = 0; i < filas; ++i)
    for (int j = 0; j < columnas; ++j)
      res.matr[i][j] = this->matr[i][j] - b.matr[i][j];
 
  return res;
}
 
template <class T>
Matriz<T> Matriz<T>::operator *(const Matriz &b) const
{
  if (this->ncolumnas == b.nfilas)
  {
    int pos = this->ncolumnas;
 
    int filas = this->nfilas;
    int columnas = b.ncolumnas;
 
    Matriz<T> res(filas, columnas);
    for (int i = 0; i < filas; ++i)
    {
      for (int j = 0; j < columnas; ++j)
      {
        T value = 0;
        for (int k = 0; k < pos; ++k) value += this->matr[i][k] * b.matr[k][j];
        res.matr[i][j] = value;
      }
    }
    return res;
  }
}
 
template <class T>
Matriz<T> Matriz<T>::operator *(int b) const
{
  int filas = this->nfilas;
  int columnas = this->ncolumnas;
 
  Matriz res(filas, columnas);
  for (int i = 0; i < filas; ++i)
    for (int j = 0; j < columnas; ++j) res.matr[i][j] = this->matr[i][j] * b;
 
  return res;
}
 
template <class T>
Matriz<T> operator *(int a, const Matriz<T> &b)
{
  return b*a;
}
 
template <class T>
bool Matriz<T>::operator ==(const Matriz &b) const
{
  if (this->nfilas != b.nfilas or this->ncolumnas != b.ncolumnas) return false;
  for (int i = 0; i < this->nfilas; ++i)
    for (int j = 0; j < this->ncolumnas; ++j)
      if (this->matr[i][j] != b.matr[i][j]) return false;
 
  return true;
}
 
template <class T>
bool Matriz<T>::operator !=(const Matriz<T> &b) const
{
  if (this->nfilas != b.nfilas or this->ncolumnas != b.ncolumnas) return true;
  for (int i = 0; i < this->nfilas; ++i)
    for (int j = 0; j < this->ncolumnas; ++j)
      if (this->matr[i][j] != b.matr[i][j]) return true;
 
  return false;
}
 
template <class T>
ostream& operator <<(ostream &salida, const Matriz<T> &mat)
{
  for (int i = 0; i < mat.nfilas; ++i)
  {
    for (int j = 0; j < mat.ncolumnas; ++j) salida << mat.matr[i][j] << " ";
    salida << endl;
  }
  return salida;
}
 
template <class T>
istream& operator >>(istream &entrada, Matriz<T> &mat)
{
  for (int i = 0; i < mat.nfilas; ++i)
    for (int j = 0; j < mat.ncolumnas; ++j) entrada >> mat.matr[i][j];
  return entrada;
}


Pues bien, como podéis comprobar he arreglado el problema que tenia con las funciones friend y los templates implementando las sobrecargas como métodos de la clase y añadiendo una pre-especificación que está comentada con un enlace, dónde se explica la solución al error de las sobrecargas de iostream (parece que el problema venía por temas internos de la clase iostream que no interpretaba bien operaciones internas de los templates). La sobrecarga del operador de un entero por una matriz he tenido que declararlo como externo a la clase, ya que si se declara como método cogerá el parámetro implícito como primer parámetro de la operación.

El resto de cambios son por la implementación de los templates.

Si alguien tiene alguna duda o sugerencia, será bienvenida ^^

Saludos y gracias amchacon por toda la ayuda!

PD: Iré mejorando la clase, como ya dije quiero implementar Gauss y varias cosas más, pero de momento voy a centrarme en el estudio de punteros que para mitades de enero tengo el examen final de programación y quiero mi matricula  ;-)
#80
Cita de: amchacon en 17 Diciembre 2013, 19:37 PM
La implementación no coindice con la declaración en la clase (Matriz != Matriz<T>).
No se a que te refieres exactamente... ¿Dices que en la declaración en la clase de las funciones amigas, he puesto Matriz en vez de Matriz<T>? Aunque lo cambie sigo teniendo el mismo problema :S
Creo que el compilador está dejando de mostrarme errores a partir de que encuentra ese, porque ayer ya estuve corrigiendo varias malas implementaciones del template y el compilador no se quejaba.  :silbar:

De todas formas, hoy le he preguntado a mi profesor de programación de la universidad sobre esto, y me ha dicho que si podía implementarlo como miembro de la clase y aplicarle la etiqueta const hasta ganaría eficiencia, ya que el compilador ya trabajaría de manera distinta que si no fuera una función constante. También me ha dicho que no desarrolla una clase y implementa sobrecargas de operadores y funciones amigas desde hace varios años, por lo que los métodos pueden haber cambiado. ¿Que opináis sobre esto?