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

#281
Cita de: vangodp en 29 Julio 2014, 14:02 PM
Edit:
En main: creas un objeto llamando el constructor con 2 parámetros:   ScrollBar scroll( 0, 20 );

Pero el constructor solo tiene definido uno. El otro es _position?  :huh:

Vaya, al final se me olvidó actualizar el main... hice un cambio de última hora y le quité el primer parámetro a ScrollBar... ya que una barra de scroll únicamente se mueve en un plano. Elimina el 0 y listo.
#282
La idea puede ser el disponer de un "viewport" que te facilite los datos del área visible en todo momento. Los datos de este viewport se verán afectados en el momento en el que se modifique el estado de la barra de scroll

Para empezar, el control de scroll. Este puede ser todo lo complejo que quieras, pero lo básico sería algo tal que:

Código (cpp) [Seleccionar]

class ScrollBar
{
  public:

    ScrollBar( int max )
      : _max( max ),
        _position( 0 )
   { }

    void Slide( int value )
    {
      _position += value;

      _position = std::max( _position, 0 );
      _position = std::min( _position, _max );
    }

    void SlideUp( )
    { Slide( -5 ); }

    void SlideDown( )
    { Slide( +5 ); }

    int Position( ) const
    { return _position; }

  private:

    int _position;
    int _max;
};


Como se ve, te limita la posición dentro de un rango determinado. Incluye un par de funciones para hacer desplazamientos rápidos, por ejemplo si pones los botones "arriba" y "abajo" característicos de las barras de scroll.

Ahora necesitamos definir el "viewport"... básicamente no deja de ser un rectángulo que podemos desplazar al gusto:

Código (cpp) [Seleccionar]

class ViewPort
{
  public:

    ViewPort( int x, int y, int width, int height )
      : _x( x ), _y( y ), _width( width ), _height( height )
   { }

    int X( ) const
    { return _x; }

    int Y( ) const
    { return _y; }

    int Width( ) const
    { return _width; }

    int Height( ) const
    { return _height; }

    int Left( ) const
    { return _x; }

    int Right( ) const
    { return _x + _width; }

    int Top( ) const
    { return _y; }

    int Bottom( ) const
    { return _y + _height; }

     void MoveTo( int x, int y )
    {
      _x = x;
      _y = y;
    }

  private:

    int _x;
    int _y;
    int _width;
    int _height;
};


Si ahora "cosemos" un poco los elementos, podemos tener un pequeño ejemplo... eso si... sin partes gráficas:

Código (cpp) [Seleccionar]

int main( )
{
  ScrollBar scroll( 0, 20 );

  ViewPort viewPort( 0, 0, 800, 600 );

  std::cout << "Desplazamiento hacia abajo:" <<  std::endl;
  for ( int i = 0; i < 5; i++ )
  {
    scroll.SlideDown( );
    viewPort.MoveTo( 0, scroll.Position( ) );
    std::cout << "Posición: x=" << viewPort.X( ) << " y=" << viewPort.Y( ) << std::endl;
  }

  std::cout << std::endl;
  std::cout << "Desplazamiendo hacia arriba: " << std::endl;
  for ( int i = 0; i < 5; i++ )
  {
    scroll.SlideUp( );
    viewPort.MoveTo( 0, scroll.Position( ) );
    std::cout << "Posición: x=" << viewPort.X( ) << " y=" << viewPort.Y( ) << std::endl;
  }
}


Como se puede apreciar... la barra de scroll limita el desplazamiento del área visible, impidendo que salga de los márgenes definidos.

Una vez echo esto queda "pintar" de forma efectiva el área apuntada por "ViewPort", pero eso ya debería ser facil conociendo las coordenadas del área a pintar... lo que tienes que hacer es coger todos los elementos de ese área y "desplazarlos". Me explico. Imagina que tienes un elemento en (20, 10) y el viewport tiene como coordenada superior (0, 2)... el elemento deberás desplazarlo ese (0, 2), es decir, deberás pintarlo en (20, 8) para que aparezca correctamente pintado en la ventana.

Si no queda muy clara la explicación avísame y te lo comento con más tranquilidad... me tengo que ir a comer XDDDD
#283
Cita de: Jorge_ en 28 Julio 2014, 00:19 AM
Hola alguien tiene idea de cómo programar en C++ el reconocimiento de voz, desde cero?

Yo te digo como empezar... el resto es cosa tuya:

Código (cpp) [Seleccionar]

int main( int argc, char** argv )
{
  // Tu codigo aqui
}


Ahora en serio... crees que esa pregunta es seria??
#284
Una guia sobre esto... hay varias formas de hacer esto... cada una con sus ventajas y sus inconvenientes.

Yo personalmente "recompilaria" la función. Un polinomio se puede encapsular fácilmente como una sucesión de monomios del tipo:

Código (cpp) [Seleccionar]

class Monomio
{
  public:

    Monomio( double multiplicador, double exponente )
      : _multiplicador( multiplicador),
        _exponente( exponente )
    {
    }

    double operator( )( double x) const
    {
      return pow( x * multiplicador, _exponente );
    }

    friend std::ostream& operator << ( std::ostream& out, const Monomio& monomio )
    {
      if ( monomio.multiplicador > 0 )
        out << "+";

      out << monomio.multiplicador;

      if ( monomio._exponente != 0.0 )
      {
        out << "x";
        if ( monomio._exponente != 1.0 )
          out << "^" << monomio._exponente;
      }

      return out;
    }

  private:

    double multiplicador;
    double _exponente;
};


Y con esto el resto del proceso se simplifica enormemente:

Código (cpp) [Seleccionar]

class Polinomio
{
  public:

    Polinomio( const std::vector< Monomio >& monomios )
      : _monomios( monomios )
    { }

    double operator( )( double x) const
    {
      double resultado = 0.0f;

      for ( const auto& monomio : _monomios )
      {
        resultado += monomio( x);
      }

      return resultado;
    }

    friend std::ostream& operator<<( std::ostream& out, const Polinomio& poli )
    {
      out << "y=";

      for ( const auto& monomio : poli._monomios )
        out << monomio;

      return out;
    }

  private:

    std::vector< Monomio > _monomios;
};

int main()
{
  std::vector< Monomio > monomios { { 1.0, 2.0 }, { -14.0, 1.0 }, { 48.0, 0.0 } };

  Polinomio poli( monomios );

  std::cout << "Función: " << poli << std::endl;
  std::cout << "Resultados: " << std::endl;
  for ( double x = 0; x < 10; x++ )
  {
    std::cout << "x=" << x << " - y=" << poli( x ) << std::endl;
  }
}


Para graficar las funciones tendrás que pelearte con alguna librería gráfica... pero al menos ya tienes la pareja de valores (x,y)
#285
c = *s++;

Es equivalente a:


c = *s;
s++;


Es decir, asigno a 'c' el valor apuntado por 's' y después hago que 's' apunte al siguiente carácter.


if (c == sc)
{
  s[-1] = '\0';
}


Si 'c' se corresponde con el delimitador, entonces tengo que eliminar ese delimitador... pero claro, el único puntero que tengo, 's', está apuntando al siguiente carácter... bueno, pues retrocedo una posición y listo.
#286
Hasta donde llego, la única forma de detectarlo es procesar el fichero y localizar combinaciones propias de uno de los formatos. Me explico:

* ASCII: Define 128 caracteres y es la base para casi todas las codificaciones comunes.

* UTF8 tiene dos formatos diferentes, con BOM y sin BOM... BOM o "Bit Order Mask" es una identificación que se añade al principio del fichero... si te la encuentras pues está claro que la codificación es UTF8... si no te la encuentras puede que sea UTF8... o no, dependerá de las secuencias que encuentres en el archivo. Las primeras 128 posiciones de UTF8 coinciden con las ASCII.

* Etc: Cada codificación tiene sus peculiaridades, lo mejor es buscar en Internet o concretar un poco más la pregunta.
#287
Cita de: ivancea96 en 26 Julio 2014, 00:02 AM
Perdona una cosa 718208. El caso es que en todos los códigos que te veo publicar, usas clases, cuando lo más acertados ería una función. En caso de que solo muestres una parte del código, pues vale. Pero si ese es todo el código, recuerda que tus clases consumen memoria, y al final acaban haciendo lo mismo que una función.

Consumen memoria... esa clase consume el equivalente a un int... 4 bytes ... tampoco hay que dramatizar jejejeje

Yo es que soy partidario de poner todo en clases... permite organizar el código mejor... lo que sucede es que funciones como estas pueden perfectamente ser estáticas, no hace falta crear una instancia de la clase para manejarlas.
#288
Cita de: engel lex en 25 Julio 2014, 03:39 AM
ya que es la diferencia entre un ciclo con una división (operacion matematica simple posible de hacer por el procesador con un solo paso)

Perdón por la intromisión, pero la división es la operación más costosa con diferencia de las interpretadas como básicas: suma, resta, producto, división. Y cuando digo costosa me refiero en una proporción que puede llegar a ser de 8 a 1.

Dicho esto me ha surgido la duda de saber cual era el algoritmo más óptimo... manos a la obra salió algo tal que:

Código (cpp) [Seleccionar]

#include <iostream>
#include <chrono>
#include <math.h>

int DigitosV1( int numero )
{
 int digitos;
 for ( digitos = 0; numero > 0; digitos++, numero /= 10 ) ;
 return digitos;
}

int DigitosV2( int numero )
{
 return log( numero ) + 1;
}

const int NUMERO = 1234567890;
const int MAXBUCLE = 1000000000;

int main( )
{
 int temp;
 std::chrono::time_point<std::chrono::system_clock> start, end;
 start = std::chrono::system_clock::now( );
 for ( int i=0; i < MAXBUCLE; i++ )
 {
   temp = DigitosV1( NUMERO );
 }
 end = std::chrono::system_clock::now();

 std::chrono::duration<double> elapsed_seconds = end-start;

 std::cout << "Tiempo division: " << elapsed_seconds.count() << "s\n";

 start = std::chrono::system_clock::now( );
 for ( int i=0; i < MAXBUCLE; i++ )
 {
   temp = DigitosV2( NUMERO );
 }
 end = std::chrono::system_clock::now();

 elapsed_seconds = end-start;

 std::cout << "Tiempo logaritmo: " << elapsed_seconds.count() << "s\n";
}


¿Qué sucede con los resultados? Son contundentes (aviso, abstenerse personas sensibles):

Editado: Estos resultados son con el programa compilado en modo debug... lo siento.


Tiempo division: 43.1613s
Tiempo logaritmo: 29.538s


Luego por 5 cabezas de ventaja, la opción del logaritmo es más óptima que la opción de la división.




Edito: Para probar opciones menos extremistas, he reducido el número de prueba a uno con 5 dígitos y he ejecutado el programa... los resultados son los siguientes:

Editado: Estos resultados son con el programa compilado en modo debug... lo siento.


Tiempo division: 19.1429s
Tiempo logaritmo: 29.564s


Se ve por tanto que la opción del logaritmo es estable en el tiempo, mientras que la división, obviamente, ha reducido su tiempo a la mitad ( tiene la mitad de dígitos ).

Dicho esto me surgió una nueva duda... log trabaja con "double"... y si la idea es trabajar con números más grandeS??

Un poco de refactorización y listo:

Código (cpp) [Seleccionar]

#include <iostream>
#include <chrono>
#include <limits>
#include <math.h>

const int INT5 = 12345;
const int INT7 = 1234567;
const int INT10 = 1234567890;

const double DOUBLE5 = 12345.0;
const double DOUBLE7 = 1234567.0;
const double DOUBLE10 = 1234567890.0;

template< class T >
int DigitosDIV( T numero )
{
 int digitos;
 T divisor = 10;
 T min = 1; // para que el bucle funcione con decimales
 for ( digitos = 0; numero >= min; digitos++, numero /= divisor ) ;
 return digitos;
}

template< class T >
int DigitosLOG( T numero )
{
 return log( numero ) + 1;
}

template< class T >
std::chrono::duration< double > Bucle( T numero, int(*func)(T) )
{
 int temp;

 auto start = std::chrono::system_clock::now( );

 const int max = std::numeric_limits< int >::max( );
 for ( int i=0; i < max; i++ )
 {
   temp = func( numero );
 }
 auto end = std::chrono::system_clock::now( );

 return end - start;
}

int main( )
{
 auto DivInt5  = Bucle( INT5,  DigitosDIV< int > );
 auto DivInt7  = Bucle( INT7,  DigitosDIV< int > );
 auto DivInt10 = Bucle( INT10, DigitosDIV< int > );

 auto LogInt5  = Bucle( INT5,  DigitosLOG< int > );
 auto LogInt7  = Bucle( INT7,  DigitosLOG< int > );
 auto LogInt10 = Bucle( INT10, DigitosLOG< int > );

 auto DivDouble5  = Bucle( DOUBLE5,  DigitosDIV< double > );
 auto DivDouble7  = Bucle( DOUBLE7,  DigitosDIV< double > );
 auto DivDouble10 = Bucle( DOUBLE10, DigitosDIV< double > );

 auto LogDouble5  = Bucle( DOUBLE5,  DigitosLOG< double > );
 auto LogDouble7  = Bucle( DOUBLE7,  DigitosLOG< double > );
 auto LogDouble10 = Bucle( DOUBLE10, DigitosLOG< double > );

 std::cout << "Tiempo division (int 5):     " << DivInt5.count( )     << " s\n";
 std::cout << "Tiempo division (int 7):     " << DivInt7.count( )     << " s\n";
 std::cout << "Tiempo division (int 10):    " << DivInt10.count( )    << " s\n\n";
 std::cout << "Tiempo log (int 5):          " << LogInt5.count( )     << " s\n";
 std::cout << "Tiempo log (int 7):          " << LogInt7.count( )     << " s\n";
 std::cout << "Tiempo log (int 10):         " << LogInt10.count( )    << " s\n\n";
 std::cout << "Tiempo division (double 5):  " << DivDouble5.count( )  << " s\n";
 std::cout << "Tiempo division (double 7):  " << DivDouble7.count( )  << " s\n";
 std::cout << "Tiempo division (double 10): " << DivDouble10.count( ) << " s\n\n";
 std::cout << "Tiempo log (double 5):       " << LogDouble5.count( )  << " s\n";
 std::cout << "Tiempo log (double 7):       " << LogDouble7.count( )  << " s\n";
 std::cout << "Tiempo log (double 10):      " << LogDouble10.count( ) << " s\n\n";
}


Y su correspondiente resultado (ahora sí en modo release):

Código (bash) [Seleccionar]

Tiempo division (int 5):     23.6144 s
Tiempo division (int 7):     33.9994 s
Tiempo division (int 10):    49.798 s

Tiempo log (int 5):          60.28 s
Tiempo log (int 7):          60.415 s
Tiempo log (int 10):         60.8651 s

Tiempo division (double 5):  81.3541 s
Tiempo division (double 7):  113.471 s
Tiempo division (double 10): 162.253 s

Tiempo log (double 5):       60.7651 s
Tiempo log (double 7):       60.8521 s
Tiempo log (double 10):      60.7481 s


La conclusión final... cada uno que saque las suyas... pero simplificando yo obtengo las siguientes:

* El logaritmo es más estable... ideal para tareas de tiempo real.
* La división es, de media, más rápida si se trabaja con enteros... el logaritmo es más eficiente con decimales.
* Es curioso como se nota la bajada de tiempos de la división en modo release frente a modo debug
#289
Blaster, perfectamente podrías ahorrarte la variable "escala". Además, teniendo en cuenta que "numero" es una especie de "engendro" por almacenar un número en base 2 como si estuviese en base 10, el código incluso se podría optimizar un poquito más:

Código (cpp) [Seleccionar]
void Binario::confirmarNumero(int numero)
{
    int decimal = 0;

    while (numero > 0)
    {
        int numeroSacado = numero & 0x01;

        decimal = decimal * 2 + numeroSacado;

        numero /= 10;
    }
    cout << "El equivalente decimal es: " << decimal << endl;
}


Cita de: 718208 en 25 Julio 2014, 02:23 AM
Pero no logo entender cual es el error ahora  :-\

Código (cpp) [Seleccionar]
while ((numero / numero) != 0)

¿Qué intentabas ahí exactamente?

A ver, esta parte concreta, lo que se dice funcionar... funciona, pero no es la mejor manera de hacerlo.Si tu idea es que el bucle se repita hasta que "numero sea 0" ¿por qué no usas los operadores de comparación ('==', '!=', '>', '<', '>=', '<=')??

Hay varias alternativas para expresar lo mismo y de forma mucho más clara. Que al final es de lo que se trata, hacer código legible. Te presento tres alternativas ordenadas de la más clara a la menos clara desde mi punto de vista:

* Opción 1: Comprobar si el número es distinto de 0
Código (cpp) [Seleccionar]
while ( numero != 0 )

* Opción 2: Comprobar si el número es mayor de 0
Código (cpp) [Seleccionar]
while( numero > 0 )

* Opción 3: Comprobar si el número es igual o mayor que 1
Código (cpp) [Seleccionar]
while( numero >= 1 )

El problema en sí, que hace qeu no te funcione, es que no estás utilizando en ningún momento la variable "escala"... le asignas valores, eso sí... pero no haces uso de esos valores en ningún momento.

Y luego te faltaría sacar por pantalla el número final.

Cita de: 718208 en 25 Julio 2014, 02:23 AM
PD: con respecto a lo que me dijiste sobre string no entendí muy bien a qué te refieres

101 (10 = 1100101 (2 <-- Queda claro que representar un número en base 2 ocupa más memoria que representarlo en base 10.

El número más alto que puedes almacenar en un int es el 2147483647 (2^31 - 1). Si usas este mismo int para almacenar un número en representación binaria, entonces no podrás almacenar números mayores que el 1111111111, que en decimal quedaría representado por el número 1023. Queda claro que el código de tu programa limita muchísimo el rango de números con el que es capaz de trabajar.

La idea que propongo es almacenar el número en una cadena de caracteres y recorrer esos caracteres para ir calculando el número final. Algo del tipo:

Código (cpp) [Seleccionar]

std::string cadena;
std::cout << "Introduce un número en binario" << std::endl;
std::cin >> cadena;

int numero = 0;
for ( unsigned int i = 0; i < cadena.length( ); i++ )
{
  numero *= 2;
  if ( cadena[ i ] == '1' )
    numero++;
}

std::cout << "El equivalente en decimal es: " << numero << std::endl;


Creo que el código resultante es bastante sencillo y fácil de entender.
#290
Programación C/C++ / Re: ayuda con strings
24 Julio 2014, 17:40 PM
El tamaño de los arrays solo hay que ponerlo, salvo que se me olvide algún caso concreto, en las siguientes circunstancias:

* Cuando los declaras en el stack (es decir, no usas memoria dinámica):

char cadena[200];

* Cuando pasas un array multidimensional ubicado en el stack como parámetro de una función:

void procesarMatriz( int matriz[10][20] );

Cuando usas un arreglo, una vez creado, el compilador ya sabe qué es lo que está manejando... no necesitas recordárselo cada dos líneas. Además que tu código es peligroso:


char cadena[4];
strcpy( cadena, "abc" ); // Ok

printf( "%c %c %c", cadena[ 0 ], cadena[ 1 ], cadena[ 2 ] );


Fíjate que al pasar el índice recupero uno de los elementos del arreglo... funciones como strstr, strcpy... necesitan un puntero que indice dónde deben empezar a leer / escribir... si en vez de eso les pasas otra cosa acabarán escribiendo en zonas de memoria que no te corresponden y el programa, en el mejor de los casos, fallará estrepitosamente.

En el ejemplo que te he puesto, si hubieses puesto

strcpy( cadena[4], "abc" );

Estarías indicando que quieres que se copie en la dirección apuntada por el cuarto elemento de cadena, la secuencia "abc"... puedes acabar escribiendo en cualquier parte de la memoria por error.

Si no eres capaz de entender lo que intento explicarte no te asustes, eso únicamente quiere decir que deberías comprarte un buen libro de C y seguirlo desde el principio antes de continuar con este tipo de prácticas... los inicios en la programación nunca son fáciles.