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

#861
Veo que no tienes muy claro el protocolo http.

En el protocolo Http el servidor únicamente se limita a proporcionar al cliente la información que éste solicita y después corta la conexión.

Si un cliente, en un momento dado, requiere un refresco de la información ha de solicitárselo al servidor creando una nueva conexión.

El servidor en ningún momento guarda un listado de los clientes que estén viendo una página alojada en el mismo.

Dicho esto, las comunicaciones básicas que se han de dar son las siguientes:

1. Cliente envía la petición
2. Servidor responde a la petición
3. Servidor cierra la conexión

Como ves, en ningún caso el servidor se queda esperando a ver si el cliente tiene algo más que decir. Y dado que el protocolo de red empleado es TCP, la propia lógica del protocolo permite asegurar que la información ha llegado correctamente.

Si el cliente necesita algo más tendrá que volver a establecer una nueva conexión con el servidor.
#862
Código (cpp) [Seleccionar]
Maleta *Mi_Maleta=new Maleta[10];

Creas un array de 10 punteros de tipo Maleta.

Código (cpp) [Seleccionar]
Mi_Maleta->Items=new Item[10];

Creas un array de 10 punteros de tipo Item en... donde?? si Mi_Maleta es un array de 10 punteros lo lógico hubiese sido un acceso del tipo:

Código (cpp) [Seleccionar]
Mi_Maleta[0]->Items = new Item[10];

Lo que sucede es que esta línea puesta tal cual te va a dar error porque tu únicamente has definido el array de punteros... no has creado ni un solo objeto de tipo Maleta.

Tendrías que haber hecho algo así:

Código (cpp) [Seleccionar]

Maleta *Mi_Maleta=new Maleta[10];
for ( int i=0; i<10; i++ )
  Mi_Maleta[ i ] = new MiMaleta( );


Ya que una cosa es crear un array de punteros y otra muy diferente crear los objetos en sí.

En el caso del array de items te pasa exactamente lo mismo, pero con lo que te he dicho ya deberías ser capaz de resolverlo tu mismo.

Un saludo.

#863
Cita de: csp en 15 Octubre 2013, 15:19 PM
Buenas,

Como std::endl aparte de hacer un salto de línea también limpia el buffer, mi duda es si hay alguna manera (Ya sea con C++, asm, o a través de un depurador) de 'ver' los valores actuales en el buffer, para visualizar de una manera un poco más gráfica el estado del mismo antes y después de usar esta instrucción.

No se si se podrá hacer o si estoy diciendo cualquier cosa, pero me quiero sacar la duda.

Muchas gracias a ambos.
Un saludo.

PD: Gracias por leer el mp EI.

puedes mirar la posición de la memoria de vídeo, "sacarle una foto", ejecutar el comando, "sacar otra foto" y comparar los dos estados para comprobar las diferencias.
#864
Código (cpp) [Seleccionar]

Punto& operator= (const Punto& p);

Punto& operator+ (const Punto& p);


Fíjate que en las dos declaraciones, el valor de retorno es una referencia.

No puedes devolver como referencia una variable o clase cuyo ámbito sea la función que define el operador. Me explico:

Código (cpp) [Seleccionar]

int& GetValor( )
{
  int i;
  i=5;
  return i;
}

void main( )
{
  int valor = GetValor( );
}


Aquí se reproduce el mismo problema. El ámbito de "i" es GetValor... fuera de dicha función, "i" no tiene ni sentido ni valor. Si devuelves una referencia a "i"... y después "i" se libera, cualquier lectura y/o escritura sobre la referencia será, cuanto menos, insegura. Lo mejor que te puede pasar en estos casos es que o bien te falle al compilar o bien se caiga la aplicación.

Además, el operador= tiene un problema. Si tu sobrecargas el operador de asignación se presupone que quieres modificar la instancia actual de la clase... y tu ahí estás haciendo una copia de p para devolverla y sin modificar "this"... eso no tiene sentido.

el operador de asignación debería tener más bien esta forma:

Código (cpp) [Seleccionar]

Punto& operator= (const Punto& p)
{
    _coord = p._coord;
    return *this;
}


Ahora fíjate que en el return, en vez de devolver una referencia a una clase propia de la función, estoy devolviendo una referencia a la instancia de la clase "modificada", que sí existirá después del return.

En cuanto al operador suma, lo mejor es que no devuelvas una referencia.

Un saludo.
#865
Estupendo ejemplo sobre cómo no se debe de programar.

No quito el mérito de programarlo, ya que tiene su curro... pero desde luego el código no es capaz de leerlo cualquiera.
#866
Tu código presenta algunos problemas de diseño:

1. Las variables de una clase deberían ser privadas.

Esto es así porque uno de los objetivos que se persigue con la programación orientada a objetos es la encapsulación, que entre otras cosas intenta que el acceso al estado de un objeto ( sus variables ) pase a través de determinados filtros que garanticen su consistencia.

Dejar las variables en public permite que desde cualquier parte del código se pueda modificar su valor sin rendir cuentas a nadie, lo que podría desembocar en un mal funcionamiento del código.

2. Las clases que "almacenan" información no deberían tener interfaz de usuario

Este punto básicamente intenta que tu código sea lo más versátil posible. Imagínate que un buen día decides que tu programa funcione en un entorno gráfico... te va a tocar reescribir la mitad de tus clases para que en vez de trabajar con la consola pasen a utilizar la interfaz gráfica.

Es mejor que, por ejemplo, la clase "puntos" únicamente se preocupe por almacenar los puntos y que sea alguna otra clase, o código del main, la que se encargue de requerir los datos al usuario y almacenarlos en "puntos".

3. Si quieres almacenar una serie de valores, necesitas vectores.

Esto te ha quedad claro pero a medias... no tiene mucho sentido que "puntos" almacene el número de puntos y no almacene los puntos en sí... desde mi punto de vista sería más lógico que v[] estuviese en "puntos". Entre otras cosas N no tiene sentido por sí misma ( porque no tienes los valores ) y v[] tampoco ( porque no sabes cuántos puntos son.

Un detalle a anotar en este apartado es que, dado que estás en c++, quizás deberías decantarte por el uso de la clase "vector"... ya puestos a programar en c++ aprende a sacarle todo el partido.

Además, si haces uso de la clase "vector", te puedes ahorrar el uso de "n".

4. Los nombres de las variables son gratuítos

Lo comento porque tener variables con nombres tan identificativos como "n" o "v" es muy cutre. Usa nombres descriptivos, te ayudarán a identificar mejor lo que hacen las variables.

Vaaaale si, me puedes decir que en este programa lo entiendes... pero si quieres te paso un código fuente de 1000 líneas con todas las variables con nombres tipo a, b, c, ... y el mismo con nombres válidos... a ver cuál entiendes mejor.

5. Una clase, si no tiene variables, o es una clase con utilidades, o está mal planteado el diseño.

Si revisas el código te darás cuenta de que la clase "centro" no es capaz de hacer nada por sí misma... todos sus miembros necesitan los mismos parámetros... n y v. Esto te está indicando algunas cosas:

* Reafirma que n y v deberían estar juntas ( por ejemplo en "puntos" ). De hecho, si estuviesen en "puntos" te ahorrarías un parámetro en todos los miembros de "centro".
* Lo que hace "centro" podría estar implementado en "puntos" sin problema.
* Todos los miembros de "centro" son utilidades

6. Los includes de c++ no llevan .h

Los includes por defecto de las librerías de c++ van sin extensión. Te recomiendo no añadir esas extensiones porque entonces te arriesgas a que tu código no sea portable. Básicamente es porque los .h de la stl de c++ no es algo que venga con el estándar.

7. SIEMPRE hay que inicializar las clases.

Es un requisito que ahorra muchos problemas futuros. Las clases, por definición, disponen de constructores... úsalos para inicializar todas las variables miembro de la clase.

Una variable sin inicializar ( sobretodo si son punteros ) puede suponer un problema complicado de resolver, ya que te va a fallar muy lejos del origen del problema, por lo que solucionarlo te puede llevar bastante tiempo.

Resumen

Para no apabullar solo con datos, te propongo una arquitectura algo más acorde con buenas prácticas de programación:

Código (cpp) [Seleccionar]

#include <iostream>
#include <vector>

enum Hemisferio
{
 Ninguno,
 HemisferioNorte,
 HemisferioSur
};

class Punto
{
 public:
   Punto( ); // Constructor por defecto

   float GetLatitud( ) const;

   float GetTemperatura( ) const;

   void SetLatitud( float latitud );

   void SetTemperatura( float temperatura );

 private:

   float latitud;
   float temperatura;
};

class Centro
{
 public:
   Centro( );

   const std::vector< Punto >& GetPuntos( ) const;

   // Calculo de los promedios de temperatura por latitud
   // devuelve un vector de puntos en el que la temperatura es la temperatura promedio
   std::vector< Punto > PromediosLatitud( ) const;

   // Calculo de los promedios de temperatura por hemisferio
   // devuelve un vector de temperaturas con dos elementos. El primero corresponde al hemisferio norte y el segundo al sur.
   std::vector< float > PromediosHemisferio( ) const;

   void SetPuntos( const std::vector< Punto >& puntos );

   // Indica cual es el hemisferio mas calido.
   Hemisferio HemisferioMasCaliente( ) const;

 private:

   std::vector< Punto > puntos;
};


Y ahora parte de la implementación:



EI: la implementacion que la haga el, acordate que aca no hacemos tareas.
#867
Programación C/C++ / Re: Ayuda con esto porfavor
10 Octubre 2013, 17:15 PM
Cita de: davidmr92 en 10 Octubre 2013, 16:47 PM
uppp

uppp no.

La gente no puede estar toda la vida limpiándote el culo... tienes que aprender a valerte por ti mismo.

* Tan complicado es usar un depurador??

* Acaso crees que vas a aprender a programar si te resolvemos dudas tan básicas ??

* Te parece casualidad que tu mensaje haya estado sin respuestas durante un par de días ???

* Crees que alguien te va a hacer un programa por la cara ??

Espero que las únicas respuesta afirmativas sean las dos primeras.

Si no te apetece aprender y prefieres tomar la vía rápida, que es que alguien te haga la práctica y se moleste en explicártelo por detalle... sin problemas... yo te paso una factura y te prometo que en una o dos hora tienes el ejercicio hecho y explicado.

Últimamente, desgraciadamente, lo repito demasiado... una cosa es resolver dudas y otra muy distinta hacer los deberes a alguien.
#868
Si la lista es circular, el primer elemento que metas tendrá que apuntarse a sí mismo... hasta ahí todo claro.

A la hora de insertar el segundo elemento se dará la particularidad de que, como tiene que seguir siendo una lista circular, el anterior y el posterior del primer elemento será el segundo elemento y viceversa:

A <-> B <-> A

Y ya de ahí en adelante la lista tiene el formato que tú ya conoces:

A <-> B <-> C <-> A

La única situación diferente es insertar el primer elemento, que tienes que hacer que se apunte a sí mismo... en el resto de casos sólo tienes que decidir la posición en la que vas a insertarlo y asignar los punteros anterior y posterior de los elementos que estén delante y detrás ( recuerda que al ser circular no habrá punteros nulos y, por tanto, todos los punteros serán válidos )
#869
char *input_nombre()
{
    char *nombre;
    printf("Indica el nombre: ");
    fgets(nombre, 30, stdin);
    return nombre;
}


Por pasar pasa lo siguiente:

char * nombre;

Declaras un puntero de tipo char... pero el puntero apunta a... ... exacto!!! a ninguna parte. Bueno, realmente sí apunta a algún sitio, por eso es puntero, lo que sucede es que apunta a una dirección de memoria que, en el mejor de los casos, no te pertenece. Y sí, esto implica que cualquier escritura sobre el puntero puede desembocar en violación de segmento o en otros problemas de graves consecuencias.

NUNCA se te ocurra utilizar un puntero sin inicializar... lo mejor que te puede pasar es que la aplicación finalice con error... lo peor es que corrompas datos de otra aplicación y pierdas datos importantes.
#870
Aparte de lo comentado por erest0r un par de consejos:

1. En el foro, encapsula el texto con las etiquetas GeSHi. Así los que intentamos ayudarte no nos dejaremos los ojos intentando leer tu código.

2. Intenta optimizar. Cuando tienes que poner una secuencia larga de ifs, en la mayoría de los casos, deberías pensar que hay una solución mejor. Me explico:

Código (cpp) [Seleccionar]
if((st>=1)&&(st<=9))
            {
               ds=10;
            }
         else
            if((st>=10)&&(st<=19))
               {
                  ds=20;
               }
            else
               if((st>=20)&&(st<=29))
                  {
                     ds=30;
                  }
               else
                  if((st>=30)&&(st<=39))
                     {
                        ds=40;
                     }
                  else
                     if((st>=40)&&(st<=49))
                        {
                           ds=50;
                        }
                     else
                        if((st>=50)&&(st<=59))
                           {
                              ds=60;
                           }
                        else
                           if((st>=60)&&(st<=79))
                              {
                                 ds=70;
                              }
                           else
                              if((st>=70)&&(st<=89))
                                 {
                                    ds=80;
                                 }
                              else
                                 if((st>=80)&&(st<=89))
                                 {
                                    ds=90;
                                 }


Lo primero de este código ( por cuestión de estilo y legibilidad ), sería evitar tantos niveles de tabulado, ya que su legibilidad mejora enormemente si los niveles de tabulación no son excesivos. Esto lo puedes conseguir poniendo el else y el if en la misma línea:

Código (cpp) [Seleccionar]

if((st>=1)&&(st<=9))
{
    ds=10;
}
else if((st>=10)&&(st<=19))
{
    ds=20;
}
else if((st>=20)&&(st<=29))
{
    ds=30;
}
else if((st>=30)&&(st<=39))
{
    ds=40;
}
else if((st>=40)&&(st<=49))
{
     ds=50;
}
else if((st>=50)&&(st<=59))
{
     ds=60;
}
else if((st>=60)&&(st<=79))
{
     ds=70;
}
else if((st>=70)&&(st<=89))
{
     ds=80;
}
else if((st>=80)&&(st<=89))
{
     ds=90;
}


Se lee mejor así, no crees ?

Aún así, llegados a este punto, podrías simplificar aún más este código.

Una opción sería quitar de los else la condición que sobra. Si te fijas, empiezas preguntando si st está en el rango {1, 9}, después si está en el rango {10, 19}... La primera parte de la condición te sobra, ya que si llega al segundo if está claro que st es mayor que 9:

Código (cpp) [Seleccionar]

if ( st <= 0 || st >= 90 )
  // Gestiona aqui el error si quieres hacerlo
else if ( st < 10 )
  ds = 10;
else if ( st < 20 )
  ds = 20;
else if ( st < 30 )
  ds = 30;
else if ( st < 40 )
  ds = 40;
else if ( st < 50 )
  ds = 50;
else if ( st < 60 )
  ds = 60;
else if ( st < 70 )
  ds = 70;
else if ( st < 80 )
  ds = 80;
else // Aqui nos podemos ahorrar la condicion
  ds = 90;


Y luego, para este caso, hay otra opción muy sencilla. Si te das cuenta, ds es siempre el múltiplo de diez que está inmediatamente por encima de st... puedes reducirlo todo a una operación matemática:


if ( st <= 0 || st >= 90 )
  // Gestiona aqui el error si quieres hacerlo
else
  ds = ( ( st / 10 ) + 1 ) * 10;


3. Usa nombres que signifiquen algo

A la hora de declarar variables intenta buscarles un nombre significativo. Entiendo que para contadores se suelen usar i, j, k, ... todo el mundo lo entiende... pero que el número de cedula lo guardes en una variable de nombre c... eso no, por favor.

Imagínate un archivo con 3.000 líneas plagado de variables tipo a, b, c, d ... el código sería ilegible.

Además el programa no va a ser más largo ni más lento... elige nombres significativos, el rendimiento será el mismo, el programa ocupará exactamente lo mismo y tu código pasará a ser bastante más legible.

4. Usa el tipo de variable adecuado

No tiene sentido que para almacenar un entero utilices un double. double es para números en coma flotante ( con decimales ). Los cálculos con números decimales son bastante más costosos que con números enteros... además, tanto float como double pueden presentar problemas de precisión si pones números con muchos dígitos significativos.

Si vas a usar enteros, usa int. El tipo int lo inventaron para algo...

5. En C++ las variables deberían ser privadas por defecto

Una de las gracias de la programación orientada a objetos es que puedes encapsular el código o, dicho de otra forma, puedes restringir y limitar tanto el uso que se le da al código como el acceso a las variables.

Si creas una clase y, por defecto, declaras todas las variables como públicas estás haciendo algo mal. Fíjate que fuera de la clase no se accede directamente a ninguna variable... todas podrían y deberían ser privadas.

Una ventaja de la encapsulación es que, al tener que usar funciones para recuperar / modificar las variables de una clase, es fácil implementar filtros que eviten que las variables contenidas en la clase tengan valores incorrectos ( a esto se le denomina inconsistencia )

Además, si las variables se usan solo dentro de una función miembro, dichas variables deberían estar declaradas única y exclusivamente dentro de dicha función. Las variables que declaras dentro de una clase tienen que tener algún sentido para la propia clase ( como una variable nombre dentro de la clase "Persona", sin embargo, la variable "i", que se usa como contadores en algunas funciones, no aporta nada a la clase "Persona" como tal )

La declaración de tu clase debería tener un aspecto más parecido a éste:

Código (cpp) [Seleccionar]

class ccedula
{
  public:

    // Constructor por defecto... hay que inicializar las variables miembro.
    // Los constructores son MUY importantes.
    ccedula( );

    //solicitar el ingreso de la cedula sin guion
    void leer( );

    int validar( ) const; // le pongo el const porque no deberia modificar "cedula"

    void imprimir( ) const; // le pongo el const porque no deberia modificar "cedula"

  private:
    int cedula; // He cambiado tanto el tipo como el nombre
};


Y ya está, la declaración no necesita nada más. Todas las variables que faltan deberían estar definidas en la función correspondiente que las usa, no en el cuerpo de la clase.

En cuanto a la implementación...

Código (cpp) [Seleccionar]


ccedula::ccedula( )
  : cedula( 0 ) // Inicializamos cedula a cero, es mejor que dejarla con un valor aleatorio
{
}

void ccedula::leer( )
{
  // tu implementacion
}

int ccedula::validar( ) const
{
  // tu implementacion
}

void ccedula::imprimir( ) const
{
  // tu implementacion
}


Y bueno, hay cosas que programaría diferente, pero eso ya es el diseño de cada uno.

Un saludo.