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

#421
Por un socket no se puede "enviar" una clase a lo bestia.

El motivo es que sus miembros, por ejemplo la clase string, gestionan memoria dinámica, por lo que si envías una clase "a pelo" la aplicación va a fallar siempre.

Lo que tienes que hacer es "serializar" la clase. Serializar es algo común en programación; cuando guardas una clase en un archivo la estás serializando.

Obviamente no hay una única forma de serializar los datos, depende del uso posterior que se les vaya a dar.

En el caso de las redes, la mejor opción es valerse de algún protocolo a nivel de aplicación para gestionar el serializado. Algunos ejemplos de estos protocolos son: Json, Protocol buffers, XDR, ASN.1

Estos protocolos no son parte del estándar de C++, para poder usarlos tendrás que bajarte alguna librería que los implemente o currarte tu propia implementación. La ventaja es que encontrarás librerías para la gran mayoría de los lenguajes existentes.

#422
Efectivamente.

Al crear un elemento nuevo con 'new', todo su contenido se crea en el heap, si se almacenase algo en el stack tendrías un problema porque esa información acabaría desapareciendo al salir del ámbito que le corresponda. Lo que está en el heap sólo desaparece cuando usas delete.

Un saludo.
#423
Cita de: JoelGonzalez en 24 Mayo 2014, 04:36 AM
He reposteando el código con la estructura y no se si he complicado su lectura por las operaciones . y -> que debo de usar para su acceso, aunque aclaro que apenas aprendí a usarlas, por lo que agradecería si me dieras tu opinión sobre el cómo manipule la estructura.

Las estructuras solo admiten dos tipos de accesos:

* por valor, usando el operador '.'
* por referencia, mediante el operador '->'

El operador por referencia se usa cuando accedes a la estructura a través de un puntero, si no hay puntero se usa el operador por valor.

La ventaja de usar estructuras es que permite agrupar variables que son dependientes, lo cual simplifica las llamadas a funciones y el diseño general de la aplicación. La pega es que, al estar las variables metidas en paquetes, es necesario añadir el acceso a la estructura a cada uso que hagamos de una de sus variables.

Una ventaja que también tienen las estructuras es que pueden copiarse unas a otras usando el operador igual '=', cosa que no sucede con los punteros, por ejemplo:


typedef struct
{
  int a;
  float b;
} datos;

int main( )
{
  datos grupo1, grupo2;

  grupo1.a = 25;
  grupo1.b = 84.59;

  grupo2 = grupo1;

  printf( "%d %f\n", grupo2.a, grupo2.b );
}


Para copiar el contenido de los punteros tendrás que hacerlo a mano... los punteros son punteros... es lo que tiene usar un lenguaje que te da tanto control sobre la memoria.

Cita de: JoelGonzalez en 24 Mayo 2014, 04:36 AM
Sobre el cambio en la implementación de la función PedirCaminos tengo algunas inquietudes porque a simple vista hacen lo mismo pero en la ejecución del programa difieren

La forma de crear la matriz de nodos es irrelevante en este caso.

Puedes crearlas en el orden que tu dices simplemente cambiando un poco los bucles:

Código (cpp) [Seleccionar]

for (i = 0; i < n; i++)
{
  G[i][i] = 0;

  for (j = i+1; j < n; j++)
  {
    printf("\n\tCiudad %d --> Ciudad %d : ", i+1, j+1);
    scanf("%d",&G[i][j]);
    Flush_in();
    G[j][i] = G[i][j];
  }
}


Cita de: JoelGonzalez en 24 Mayo 2014, 04:36 AM
Y sobre lo demás no entiendo muy bien aquello de que haya posibilidad de que las rutas no tengan el mismo valor de ida que de vuelta

Cuando te mueves en coche, te habrás dado cuenta de que hay situaciones en las que los dos sentidos de circulación de una misma carretera dejan de ir paralelos el uno al otro ( accidentes geográficos, otras estructuras anteriores, ... ). Esto hace que, en la vida real, la distancia A-B no sea la misma que la distancia B-A... y en ocasiones la diferencia no es despreciable.

En tu algoritmo, en la entrada de datos estás haciendo:


for (i = 0; i < (datos -> num_ciudades); i++ )
{
  for (j = 0; j < (datos -> num_ciudades); j++)
  {
    // ...
   datos -> G[j][i] = datos -> G[i][j];
  }
}


Es decir, estás asumiendo que la distancia A-B es igual a la distancia B-A. Si permites que estos valores sean diferentes podrás adaptar tu código a situaciones reales ( carreteras, internet, ... )

Cita de: JoelGonzalez en 24 Mayo 2014, 04:36 AM
y tampoco sobre que las rutas tengan un mismo sentido aunque tengo la sensación de que son muy interesante esas propuestas.

¿No te has encontrado nunca una carretera de sentido único? ¿Y si esa carretera resulta que une dos ciudades? en ese caso, existirá la conexión A-B pero no la conexión B-A, lo mismo para ir de B a A tienes que hacer B-C-A eso es algo que te puedes encontrar estudiando casos reales.

Y para terminar, una propuesta más, da la posibilidad de guardar las rutas en un fichero y leerlo después, claro... los casos reales suelen tener más de 20 ciudades y puede ser un auténtico tormento tener que introducir a mano una matriz de, por ejemplo 1000 x 1000 elementos jejejeje

Una vez tengas esto terminado, bien diseñado y estructurado te puedes plantear añadir nuevas variables a tu sistema, como por ejemplo la velocidad máxima de cada enlace o el consumo medio de combustible necesario para recorrer esa ruta. El caso es que así puedes establecer diferentes criterios a la hora de buscar la ruta óptima:

* Quiero ver la ruta más rápida (menor tiempo total para hacer el camino A-B )
* Quiero ver la ruta más corta  (menor distancia)
* Quiero ver la ruta más económica (menor consumo)
...

Si te das cuenta, los GPS funcionan más o menos así.

Un saludo.
#424
En C++ no hace falta usar los typedef para las estructuras:

El siguiente código en C++...
Código (cpp) [Seleccionar]

struct tDatos
{
string nombre;
int edad;
};


... es equivalente a tu versión en C:


struct {
string nombre;
int edad;
}tDatos;


No es un fallo, pero el código tiene menos basura y eso se agradece ;)

El fallo te da porque tu has declarado lista.datos como un puntero... no como un array de punteros.

La siguiente instrucción sí sería válida:

Código (cpp) [Seleccionar]
lista.datos = datosPersona;

Aún así, si lo que quieres es almacenar una lista de punteros, puedes usar mejor un contenedor de C++.

El más común es std::vector:

Código (cpp) [Seleccionar]

struct tLista
{
  std::vector< tDatosPtr > datos;
};

int main( )
{
  tLista lista;
 
  tDatosPtr datosPersona = new tDatos;
  datosPersona->nombre = "pepe";
  datosPersona->edad = 12;

  lista.datos.push_back( datosPersona );
  int numero_elementos = lista.datos.size( ); 
};


La otra opción es declarar lista.datos como un puntero doble:

Código (cpp) [Seleccionar]

struct tLista{
int cont;
tDatosPtr* datos;
};
#425
Tu no estás enviando un struct, como te dije, la red solo entiende de bytes, el ejemplo envía el contenido de la memoria donde se encuentra el struct.

Como te comenté, lo suyo es usar algún protocolo a nivel de aplicación que sea independiente del lenguaje de programación y de la arquitectura de la máquina. Te puse ejemplos: XDR, Protocol buffers, JSon. Estos protocolos funcionarán exactamente igual tanto en C++ como en Java, .NET, Ruby, ...

Si tu envías una trama por la red pueden pasar dos cosas: lo recibes o no lo recibes... no vas a recibir una parte sí y otra no. Si envías dos mensajes A y B en ese orden puede suceder lo siguiente:

* recibes A y B
* recibes B y A
* recibes A o B
* no recibes ninguno

No existe la opción de "recibes medio paquete de A y medio de B".

Lo de poner un secuencial en la trama es para que tu después seas capaz de ordenar los mensajes para poder recomponer la imagen correctamente.

#426
Buenas Joel. Bienvenido al foro.

Si te das cuenta, en todas las funciones tienes que pasar tanto la matriz como el número de ciudades, puedes ahorrarte la molestia empaquetando ambas variables en una estructura:


typedef struct
{
  int Grafo[20][20];
  int NumCiudades;
} Datos;


Y algo parecido para el vector de rutas.

De esta forma los dos datos van a viajar siempre juntos y reducirás el número de argumentos de las funciones ( que siempre es de agradecer ). Además también se mejora la legibilidad del programa porque desde un primer momento se sabe que esas dos variables van de la mano.


  for (i = 0; i < n; i++)
  {
    for (j = 0; j < n; j++)
    {
      if (i == j)

        G[i][j] = 0;

      if (i < j)
      {

          printf("\n\tCiudad %d --> Ciudad %d : ", i+1, j+1);
          scanf("%d",&G[i][j]);
          Flush_in();

        G[j][i] = G[i][j];
      }
    }
  }


Este bucle tiene margen de mejora... si i < j es requisito, puedes evitar la comparación con un par de cambios


  for (i = 0; i < n; i++)
  {
    for (j = 0; j <= i; j++) // Se reduce el rango de j
    {
      if (i == j)
        G[i][j] = 0;
      else // Desaparece el if
      {

          printf("\n\tCiudad %d --> Ciudad %d : ", i+1, j+1);
          scanf("%d",&G[i][j]);
          Flush_in();

        G[j][i] = G[i][j];
      }
    }
  }


O incluso...


  for (i = 0; i < n; i++)
  {
    G[i][i] = 0;

    for (j = 0; j < i; j++)
    {
      printf("\n\tCiudad %d --> Ciudad %d : ", i+1, j+1);
      scanf("%d",&G[i][j]);
      Flush_in();
      G[j][i] = G[i][j];
    }
  }


Por lo demás, a simple vista no veo nada raro.

Como posibles mejoras yo propondría las siguientes:

* permitir elegir entre diferentes algoritmos de enrutado.
* posibilidad de que las rutas de ida no tengan el mismo valor que las de vuelta.
* rutas de un solo sentido ( va de la mano con la propuesta anterior )

Y no se, si se me ocurre algo más actualizaré el mensaje

Un saludo.
#427
Se me ocurren dos opciones:

1. usar una pila y una cola:

cada letra la introduces en ambos contenedores a la vez. Una vez tienes la palabra completa empiezas a asacar elementos de la pila y de la cola... si coinciden hasta el final es palíndromo.

Nota: recuerda que una pila es de tipo LIFO y una cola FIFO.

2. Con una pila y un string:

Guardas la palabra en un string y en la pila... después vas comparando el string desde el principio hasta el final con lo que vas sacando de la pila... si coinciden hasta el final es palíndromo.

Por cierto, respecto a esta afirmación que has hecho:

Cita de: CNerd en 22 Mayo 2014, 18:46 PM
... de ser impar (porque las pares no pueden ser palindromos) ...

Palíndromos de 4 letras:
Citar
erre
allá
elle
alla

Palíndromos de 6 letras:
Citarnarran
rallar
selles

Palíndromos de 8 letras:
Citaracurruca
#428
Programación C/C++ / Re: Asociacion en c++
23 Mayo 2014, 08:46 AM
Eso no es herencia:

En el ejemplo que pongo se ve cómo se pueden comunicar clases sin necesidad de herencia.

Código (cpp) [Seleccionar]

#include <iostream>
#include <string>

class B;

class A
{
  friend class B;

  public:
    A( )
      : b( nullptr )
    { }

    void SetB( B* ptr_b )
    { b = ptr_b; }

    void EnviarMensaje( const std::string& mensaje ) const;

  private:

    B* b;

    void PonerMensaje( const std::string& mensaje ) const
    { std::cout << "A: " << mensaje << std::endl; }
};

class B
{
  friend class A;

  public:
    B( )
      : a( nullptr )
    { }

    void SetA( A* ptr_a )
    { a = ptr_a; }

    void EnviarMensaje( const std::string& mensaje ) const
    { if ( a ) a->PonerMensaje( mensaje ); }

  private:

    A* a;

    void PonerMensaje( const std::string& mensaje ) const
    { std::cout << "B: " << mensaje << std::endl; }
};


void A::EnviarMensaje( const std::string& mensaje ) const
{ if ( b ) b->PonerMensaje( mensaje ); }

int main( )
{
  A a;
  B b;

  a.SetB( &b );
  b.SetA( &a );

  a.EnviarMensaje( "Hola" ); // Pantalla: B: Hola
  b.EnviarMensaje( "Adios" ); // Pantalla: A: Adios
}


Deberías aclarar un poco más los requisitos
#429
Cita de: mk7 en 21 Mayo 2014, 18:03 PM
Pero teniendo en cuenta que cada frame habría que enviarlo en varios paquetes igual es mucho lio para reconstruirlos en el destino.

Por UDP puedes enviar tantos paquetes como quieras... si a cada paquete le añades un campo con un identificador secuencial, se pueden ordenar sin problemas al llegar al destino.

Cita de: mk7 en 21 Mayo 2014, 18:03 PM
La verdad, es que dándote la razón, me gustaría hacer una prueba inicial con TCP a ver que rendimiento resulta.

Dado que TCP intenta por todos los medios garantizar la entrega de los paquetes, como la calidad de la conexión no se ajuste a la velocidad de transmisión requerida no va llegar absolutamente nada... o si llega lo va a hacer con un retraso importante.

UDP en cambio te permite gestionar la recepción de paquetes, lo que te permite descartar automáticamente paquetes antiguos sin perjudicar el rendimiento.

Cita de: mk7 en 21 Mayo 2014, 18:03 PM
Los datos a transferir serían bytes. En el destino busco renderizar la imagen RGB24 usando OpenGL. Entonces lo que quiero es reconstruir el array tal cual lo envío en bytes.

La red solo entiende de tramas... y las tramas son campos de bytes... a la red le da igual si estás enviando una foto, un video porno casero o la fórmula de la cocacola... lo que tú introduzcas en un extremo de la conexión lo vas a recuperar en el otro.

Es decir, vas a enviar un chorizo de bytes y vas a recuperar un chorizo de bytes. Es responsabilidad tuya saber generar ese chorizo de bytes y, por tanto, de saber reconvertirlo en algo útil para ti.


Cita de: mk7 en 21 Mayo 2014, 18:03 PM
OniRGB888* textura es un puntero a una posición de memoria. textura+1 sería el siguiente pixel y cada pixel son 3 bytes (uno por color), por lo tanto, se enviarían 3 bytes cada vez que avanzo el puntero. (Creo no equivocarme).

Como te comenté, a la red eso le da absolutamente igual. Este dato es importante para ti, lo necesitas para saber como obtener un stream de bytes que represente la imagen que quieres enviar... luego troceas ese stream en fragmentos de... no se... 1000 bytes.

Cada red tiene un tamaño máximo de trama (MTU), si la red recibe una trama mayor, la troceará para enviarla... eso es transparente para ti, pero es importante saberlo por si te genera problemas. un MTU típico es 1500, tienes que tener en cuenta que ese MTU incluye los datos que envías y la cabecera propia de cada trama, que depende del protocolo de la red.

Cita de: mk7 en 21 Mayo 2014, 18:03 PM
Aquí es donde no se como tengo que enviar este objeto. Se que el método send me devuelve los bytes enviados y tengo iterar hasta envíar el frame completo. ¿Como le paso al método send la posición de memoria de este objeto?¿Como le digo que vaya en bytes en lugar de 3 bytes?

Lo primero que tienes que hacer es obtener una secuencia de bytes con la que puedas recomponer la imagen... el formato de esa secuencia puede ser libre, pero ha de ser conocido tanto por cliente como por servidor.

Después tienes que enviarlo por la red. En este caso tienes dos opciones:

* Lo envías "crudo", es decir, tal cual. El problema que te puedes encontrar es que una máquina se big endian y la otra little endian y tengas que implementar algoritmos diferentes para recomponer la imagen.

* Lo envías usando un protocolo de aplicación ya conocido ( XDR, Protocol buffers, JSon... ) estos protocolos suelen incluir codificaciones especiales para que la información se pueda recuperar sin problemas independientemente de las peculiaridades de las máquinas que intervienen en la comunicación.

Además de esto, puedes implementar tu propia capa de control. Esto te permitiría desechar mensajes antiguos y ordenar las diferentes tramas que componen una imagen. Esto se puede hacer de varias formas:

* Antes de enviar una imagen, envías un mensaje en el que indicas el número de tramas que van a componer la imagen... puedes enviar más información, como la fecha de la imagen, su número de identificación... lo que se te ocurra. Este mensaje lo recibe la máquina destino y le permite conocer de antemano lo que tiene que recibir. Luego cada parte de la imagen la tienes que enviar con el mismo identificador que la primera trama y luego un número de orden.

* Te ahorras el mensaje inicial y haces que en cada parte de la imagen viaje toda la información necesaria:



#define MAX_BUFF_IMAGEN 1000

typedef struct
{
  int id_imagen; // Identificador de la imagen, cada imagen diferente tendra un identificador distinto
  int index // Indice para poder ordenar los mensajes de una misma imagen.
  int numDatos; // Numero de datos en el buffer "datos"
  char[ MAX_BUFF_IMAGEN ] datos; // Buffer para almacenar un fragmento de la imagen
} Trama;

void enviar( char* imagen, int longImagen )
{
  Trama trama;
  trama.id_imagen = 0;
 
  int partes = longImagen / MAX_BUFF_IMAGEN;
  if ( longImagen % MAX_BUFF_IMAGEN != 0 )
    partes++;

  int i;
  for ( i = 0; i < partes; i++ )
  {
    trama.index = i;
   
    // Se envian como mucho 1000 bytes
    if ( longImagen > MAX_BUFF_IMAGEN )
      trama.numDatos = MAX_BUFF_IMAGEN;
    else
      trama.numDatos = longImagen;

    // Se copia una parte de la imagen
    memcpy( trama.datos, imagen + i * MAX_BUFF_IMAGEN, trama.numDatos );

    // Se envia el mensaje
    send( socket, &trama, sizeof( trama ),  0);
  }
}
#430
es un proyecto de envergadura.

La mejor forma que se me ocurre para poder "interpretar" el audio es usar una red neuronal debidamente entrenada... el problema es que, como te dijo engel lex la cantidad de matices de la voz y la cantidad de timbres diferentes pueden llevarte a construir una red neuronal bastante grande... y eso va a ser a costa de sacrificar el rendimiento.

Por otro lado, el procedimiento inverso se me antoja aún más complicado, ya que un texto plano, por si solo, no tiene información acerca de los matices de la voz original... eso tendrías que almacenarlo por separado y enchufárselo todo a un sintetizador de voz para recomponer el audio... hasta donde llego, los sintetizadores de voz tienen bastante matemática por detrás, no se cual será tu base al respecto, pero espero que bastante buena. Imagino que tendrás que usar frecuentemente integrales y derivadas para poder sintetizar correctamente la voz.

Lo mismo deberías replantearte el proyecto y afianzar conocimientos antes de dar pasos como este.