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

#541
.NET (C#, VB.NET, ASP) / Re: ayuda con textbox
21 Abril 2014, 13:38 PM
Con ese código estás haciendo que la marca de agua aparezca siempre que no haya texto en el control... es un tratamiento más refinado pero da más problemas.

En teoría con la gestión del foco te debería servir... además no tendrías que lidiar con las pulsaciones del teclado... con la opción "pegar" del menú contextual... etc.

Si quieres seguir con tu idea de que sea sensible al contenido del TextBox en edición quizás sería más sencillo "pintar" la marca de agua en el evento OnPaint en vez de pasarla al Text... la ventaja que consigues es que no saltan eventos cada vez que pones / quitas la marca de agua y no tienes que preocuparte por la posición del "caret".
#542
Cita de: ank3r en 21 Abril 2014, 03:25 AM
Con un programita en C estoy creando un archivo con la siguiente estructura:

struct t_config {
   char ip[13];
   int puerto;
};struct t_config t_config;


Error. Esa es una estructura de datos que usa un programa... los ficheros no entienden de eso.

Entre otras cosas porque esa información se puede almacenar en mil formatos diferentes, binario, XML, Json, XDR, ASN.1, texto plano, ...

Esa definición tampoco indica si los dos datos están en la misma línea o en líneas diferentes... vamos, que la definición de una estructura sirve más bien para poco a la hora de conocer la estructura de los datos en un fichero.

Cita de: ank3r en 21 Abril 2014, 03:25 AM
Es un archivo que tiene una IP (la puse como string) y un puerto de 4 numeros (un int)

Error. el puerto puede ser de 4 dígitos... pero nunca de 4 números... ( la IP sí tiene 4 números ).

Quisquilloso... depende... con 4 números se puede interpretar que estás guardando el número de puerto separando cada dígito en un número independiente... hay que ser más conciso.

Cita de: ank3r en 21 Abril 2014, 03:25 AM
Ahora tengo otro programa que abre este archivo. Lo que me gustaría es que tome la ip y la guarde en una variable y por otro lado que guarde en otra variable el puerto. Intente con fscanf, fseek, fread y no me sale. Cuando lee el puerto, por ejemplo le pongo 5000 (con ceros) me pone otros números..

Sin saber cómo está guardada la información en el fichero y cómo estás intentando recuperarla es imposible saber qué está mal.

Así a bote pronto puede ser que el dato esté almacenado en formato texto y tú estés leyéndolo como un int o al revés... pero son tiros al aire.
#544
La idea está genial. Enhorabuena.

Lo que no veo del todo claro es que en "cannyAlgorithm" tenga que ser todo público.

Quizás sería mejor crear una clase para gestionar la imagen y pasar una instancia de dicha clase a cannyAlgoritm para hacer el trabajo... incluso cannyAlgoritm podría almacenar los resultados en una nueva instancia de imagen y devolverla con un return... así la imagen original no sufre cambios.

Otra idea puede ser la utilización de "interfaces", que en C++ son clases virtuales puras. La idea es poder tener una colección de filtros y usarlos a discrección sin importar su tipo.

La cosa es tener una clase base con un método virtual puro para forzar a sus derivadas a implementarlo... después se hace que los diferentes filtros hereden de la clase base y así puedes usarlos todos de la misma forma ( incluso meterlos en un vector para poder ejectuar diferentes filtros en un orden concreto sin importar su tipo ).

Un ejemplo:

Código (cpp) [Seleccionar]

class Filtro
{
  public:

    Filtro( );

    // El destructor virtual, esto es importante en herencia
    virtual ~Filtro( );

    // Imagen es la clase que te he comentado, se pasa por referencia porque asi
    // te aseguras de que no te pasan punteros nulos
    // el '= 0' es para indicar que esta clase no implementa esta funcion, es
    // responsabilidad de las hijas implementarla.
    // En este caso la imagen que se pasa como argumento se modifica segun el filtro.
    virtual void Filtrar( Imagen& imagen ) = 0;   
};

class FiltroCanny
  : public Filtro
{
  public:

    FiltroCanny( );

    // Este destructor ya no es necesario declararlo virtual, pero tampoco hace ningun mal
    // Es buena idea acostumbrarse a declarar los destructores siempre virtuales
    // para evitar problemas
    virtual ~FiltroCanny( );

    // Esta funcion sera la que implemente tu algoritmo de deteccion de bordes
    // Luego en private puedes poner todas las funciones auxiliares que necesites
    virtual void Filtrar( Imagen& imagen );
};

// Esta clase representa un filtro que convierte una imagen a escala de grises
class FiltroGrayScale
  : public Filtro
{
  public:

    FiltroGrayScale( );

    virtual ~FiltroGrayScale( );

    virtual void Filtrar( Imagen& imagen );
};

// En esta funcion se supone que se va a convertir una imagen en escala de grises
// y despues se va a pasar tu algoritmo
// Es un ejemplo sencillo para ilustrar un poco la flexibilidad de este diseño.
void func( Imagen& imagen )
{
  std::vector< Filtro* > filtros;
  filtros.push_back( new FiltroGrayScale( ) );
  filtros.push_back( new FiltroCanny( ) );

  for ( int i = 0; i < filtros.size( ); i++ )
    filtros[ i ]->Filtrar( imagen );

  for ( int i = 0; i < filtros.size( ); i++ )
    delete filtros[ i ]; 
}
#545
Programación C/C++ / Re: guardar nodos en txt
21 Abril 2014, 10:17 AM
Nota 1.

Una lista enlazada es, por definición, dinámica... luego la dificultad es siempre la misma. No?

Nota 2.

Estás trabajando con C++, luego no termino de entender por qué el nombre lo almacenas con un array de chars en vez de usar la clase string.

Código (cpp) [Seleccionar]

class nodo {
  public:
   nodo(int num, const std::string& name, nodo *sig = NULL)



Nota 3.

No tiene sentido que pongas includes de C... los includes de C++ no llevan la extensión .h. La STL es suficientemente amplia y completa, no necesitas los includes de C para nada.

Nota 4.

Por qué motivo cola es clase friend de nodo??? Es mucho mejor que pongas los getters y setters correspondientes en nodo... pocas veces es necesario usar friend y este no es el caso ( además puede ser una fuente de problemas ).

Código (cpp) [Seleccionar]

class nodo {
  public:
   nodo(int num, const std::string& name, nodo *sig = NULL)
     : numero( num ),
       nombre( name ),
       siguiente( sig )
   {
   }//constructor
   
   int Numero( ) const
   { return numero; }
   
   std::string Nombre( ) const
   { return nombre; }
   
   nodo* Siguiente( ) const
   { return siguiente; }
   
   void SetSiguiente( nodo* sig )
   { siguiente = sig; }
   
  private:
   int numero;
   std::string nombre;
   nodo *siguiente;
};


Nota 5.

Código (cpp) [Seleccionar]
typedef nodo *pnodo; //definimos un tipo de dato personalizaodo. Tipo puntero de la clase NODO

Ya que usas un typedef... por qué no lo pones al principio y lo usas también en "nodo"??

Yo personalmente no soy partidario de usar alias para ahorrarte un asterisco... bueno, no te lo ahorras, lo cambias por una "p"... pero si lo usas, al menos intenta aprovecharlo al máximo:

Código (cpp) [Seleccionar]


class nodo; // declaration forward para el typedef

typedef nodo *pnodo; //definimos un tipo de dato personalizaodo. Tipo puntero de la clase NODO

class nodo {
  public:
   nodo(int num, const std::string& name, pnodo sig = NULL)
     : numero( num ),
       nombre( name ),
       siguiente( sig )
   {
   }//constructor
   
   int Numero( ) const
   { return numero; }
   
   std::string Nombre( ) const
   { return nombre; }
   
   pnodo Siguiente( ) const
   { return siguiente; }
   
   void SetSiguiente( pnodo sig )
   { siguiente = sig; }
   
  private:
   int numero;
   std::string nombre;
   pnodo siguiente;
};


Nota 6.

Código (cpp) [Seleccionar]
cola paciente;

No solo es muy mala idea usar variables globales sino que, además, la has metido entre medias de la implementación de "cola"... mi consejo es no usar variables globales, pero si las usas, al menos que estén en sitios concretos y correctamente identificadas.

Nota 7.

Como te comenté al principio, la STL tiene una colección bastante decente y completa de utilidades que te permiten "olvidar" las viejas funciones de C.

En el caso de acceso y manipulación de ficheros, tienes las clases ostream e istream ( y sus derivadas ) que simplifican la gestión de ficheros. Además vienen con opciones especiales para poder trabajar con clases nativas de C++, como la clase string.

Nota 8.

A la hora de guardar clases en ficheros no es buena idea guardar la clase "a pelo" volcando su memoria al fichero. La razón es que en ese volcado puede viajar información RTTI ( la que se usa en dynamic_cast y que gestiona la herencia )... y no creo que quieras exportar eso porque puedes tener problemas si cambia la estructura de las clases. La forma correcta de trabajar es guardar las cosas miembro a miembro. Lo mejor es crear una clase que sepa como "serializar" cada elemento "nodo" para almacenar / recuperar un nodo a partir de un archivo.

Por supuesto, lo que no puedes hacer es volcar el contenido de la cola literalmente... la cola almacena punteros... y lo que vas a almacenar en el fichero es el valor de los punteros, no el contenido apuntado por dichos punteros...

Nota 9.

Yo soy partidario de seguir la norma "1 clase = 1 responsabilidad"... simplifica el diseño, evita dependencias absurdas y facilita la depuración y el mantenimiento.

En tu caso, "cola" tiene 2 responsabilidades. Por un lado gestiona una lista de nodos y, por otra, permite volcar dichos nodos a la salida estándar... Yo habría optado por quitar esta segunda responsabilidad de "cola" y la habría puesto o bien en una clase creada para la ocasión o bien en una función independiente.

No hay que tener miedo a tener decenas de clases sencillas... al contrario de la creencia popular entre los que van aprendiendo, tener clases sencillas facilita muchísimo el proceso de crear software... es como usar piezas de Lego...

Si caes en la tentación de juntar múltiples responsabilidades en una sola clase o función al final acabarás gestionando clases gigantescas las cuales te van a devorar al intentar hacer modificaciones o correcciones... quedas avisado.
#546
.NET (C#, VB.NET, ASP) / Re: ayuda con textbox
21 Abril 2014, 09:19 AM
Cita de: ivancea96 en 21 Abril 2014, 01:22 AM
Bueno yo en C++ aún no hice este tipo de formularios, pero te digo:

Ese texto es el "Placeholder".

MSDN-Textbox.placeholdertext

Eso es si está trabajando con XAML, que no creo que sea el caso.

Por la pinta de ese formulario, yo diría que está trabajando con los controles nativos de .NET... lo que no queda claro es con qué versión.

En este caso, una opción sencilla es controlar los eventos de "foco" del control.

Lo suyo es crear una clase que derive de "TextBox" y controle los eventos de "foco", de tal forma que:

* si el control pierde el foco y no tiene contenido, se escriba ese texto en el fondo ( puedes empezar por hacer una versión sencilla escribiendo el contenido en su propiedad "Text" y cambiar el color de la fuente por un gris ).

* al recibir el foco el control, si su contenido es éste que tiene por defecto, se borre su contenido, permitiéndole al usuario una entrada limpia.

Este comportamiento es muy básico y se puede perfeccionar, por supuesto, pero como base sirve.
#547
Si quieres que las matrices sean de tamaño variable tienes dos opciones:

opción 1: Añades a la firma de la función un par "filas-columnas" por cada una de las 3 matrices ( o bien asumes que la matriz donde almacenas el resultado va a tener el tamaño correcto )

void multiplicacion(float **M1, int filasM1, int colsM1, float **M2, int filasM2, int colsM2, float **M3, int filasM3, int colsM3 );

opción 2: Creas una estructura para facilitar la gestión de las matrices y así te aseguras que las dimensiones de cada matriz viajan siempre junto a la matriz:

Código (cpp) [Seleccionar]

typedef struct
{
  float** datos;
  int filas;
  int columnas;
} Matriz;

void multiplicacion( Matriz* M1, Matriz* M2, Matriz* M3 )
{
  int i,j,k;
  float a,b;

  // Se comprueba que las matrices se puedan multiplicar ( falta comprobar M3 )
  if ( M1->columnas != M2->filas )
    return;

  for (i=0; i < M3->filas; i++)
  {
    for (j=0; j < M3->columnas; j++)
    {
      M3->datos[ i ][ j ] = 0.0;
      for(k=0; k < M1->columnas; k++)
      {   
        a = M1->datos[ i ][ k ];
        b = M2->datos[ k ][ j ];
        M3->datos[ i ][ j ] += ( a * b );
      }
    printf( "%f  ", M3[ i ][ j ] );
  }
  printf( "\n" );
}


Obviamente, en este caso, las matrices son dinámicas, por lo que tendrás que reservar la memoria necesaria para poder construir las matrices... en este caso lo recomendable es crear una función que permita inicializar dichas matrices y otra para liberar la memoria:

Código (cpp) [Seleccionar]


void EliminarMatriz( Matriz* m )
{
  if ( m->filas > 0 && m->columnas > 0 )
  {
    int i;
    for ( i = 0; i < m->filas; i++ )
      free( m->datos[ i ];

    free( m->datos );
  }

  m->filas = 0;
  m->columnas = 0;
  m->datos = 0;
}

void InicializarMatriz( Matriz* m, int filas, int columnas )
{
  if ( filas == 0 || columnas == 0 )
  {
    filas = 0;
    columnas = 0;
  }

  m->filas = filas;
  m->columnas = columnas;

  if ( filas > 0 )
  {
    matriz.datos = (float**)calloc( filas, sizeof( float* ) );

    int i;
    for ( i = 0; i < filas; i++ )
      matriz.datos[ i ] = (float*)calloc( columnas, sizeof( float ) );
  }
}


Con estas funciones auxiliares, la creación y eliminación de matrices se convierte en algo trivial.
#548
La forma correcta que debería tener un archivo de cabecera es:

Código (cpp) [Seleccionar]

#ifndef TABLERO_H
#define TABLERO_H

#include <iostream>
#include <stdlib.h>
#include <windows.h>

using namespace std;

class tablero
{
    public:
        tablero(){}
        tablero(string tablelimpio);
        ~tablero();
        string dartablero();
     protected:
    private:
        string vacio;
        int i, j, k;
        string tavacio;

};

#endif // TABLERO_H


O en su defecto

Código (cpp) [Seleccionar]

#pragma once

#include <iostream>
#include <stdlib.h>
#include <windows.h>

using namespace std;

class tablero
{
    public:
        tablero(){}
        tablero(string tablelimpio);
        ~tablero();
        string dartablero();
     protected:
    private:
        string vacio;
        int i, j, k;
        string tavacio;

};


La protección ifndef debería abarcar todo el fichero, ya que así evitas que en el proceso de compilación y linkado y se carguen los includes de ese fichero varias veces seguidas.

Además, en el caso de esta clase, no usas las variables i,j,k y vacio... deberías eliminarlas.

Código (cpp) [Seleccionar]

    tablero t( vacio={"-","-","-","-","-","-","-","-","-"});


¿¿¿??? qué sentido tiene "vacio" en este contexto?? si quieres definir el "tablero" de esta forma, perfecto, pero no emplees un miembro de "menu" específicamente para eso... usa mejor variables locales:

Código (cpp) [Seleccionar]

Menu::Menu()
{
    string strTablero = {"-","-","-","-","-","-","-","-","-"};
    t1 = tablero( strTablero );
    //ctor
}


O mejor aún:

Código (cpp) [Seleccionar]

Menu::Menu( )
  : t1( "---------" )
{
    //ctor
}


Recuerda que con cada pareja de comillas estás definiendo una cadena, no un carácter suelto ( y las cadenas terminan todas con '\0', mientras que un carácter es... solo un carácter ).

En los ejemplos que has puesto tu, primero se llama al constructor de t1, después se crea t y después se hace una asignación... en este último caso únicamente se llama al constructor de t1. Es más bonito y eficiente.

Código (cpp) [Seleccionar]

            cout << "|"  << t1.dartablero()[i][0] << "|" << "\t";


A ver, si dartablero( ) devuelve un string, no puedes usarlo como si fuese una matriz... porque no lo es... en tal caso podrías usarlo como un vector, pero poco más. Puedes emular una matriz con un vector... pero recuerda que es una emulación, en ningún caso sería una matriz real:

Código (cpp) [Seleccionar]

    for (int i=0; i <3; i++)
        {
            cout << "|"  << t1.dartablero()[i * filasPorColumna] << "|" << "\t";
        }
    cout << endl;

    for (int j=0; j<3;j++)
        {
            cout << "|" << t1.dartablero()[j * filasPorCoumna + 1] << "|" << "\t";
        }
    cout << endl;

    for(int k=0; k<3; k++)
        {
            cout << "|" << t1.dartablero()[k * filasPorColumna + 2]<< "|" <<"\t" ;
        }


Y por cierto, podrías reutilizar i en cada bucle... no vas a tener ningún problema:

Código (cpp) [Seleccionar]

    for (int i=0; i <3; i++)
        {
            cout << "|"  << t1.dartablero()[i * filasPorColumna] << "|" << "\t";
        }
    cout << endl;

    for (int i=0; i <3; i++)
        {
            cout << "|" << t1.dartablero()[i * filasPorCoumna + 1] << "|" << "\t";
        }
    cout << endl;

    for (int i=0; i <3; i++)
        {
            cout << "|" << t1.dartablero()[i * filasPorColumna + 2]<< "|" <<"\t" ;
        }


O, ya puestos, combinarlos, que no tiene sentido tanto bucle:

Código (cpp) [Seleccionar]

for (int fila=0; fila <3; fila++)
{
  for ( int col = 0; col < 3; col++ )
    cout << "|"  << t1.dartablero()[ fila * filasPorColumna + col ] << "|" << "\t";
  cout << endl;
}


el valor de filasPorColumna, en tu caso, debería valer 3, por si acaso dudas.

En cualquier caso, lo suyo es que usases una matriz de tipo char y así te evitas tener que emular el comportamiento de una matriz... la clase string no es la mejor opción en tu caso.
#549
Cuando tu compilas una DLL también se genera la correspondiente librería estática ( .a o .lib, dependiendo del compilador ). Esta librería estática la puedes añadir a tu ejecutable sin ningún problema y te va a funcionar igual de bien que  enlazar con la librería dinámica.

El problema que esto plantea es que puede que entre en conflicto con la licencia de la librería... algunas licencias no permiten este tipo de enlace salvo que publiques el código fuente de tu aplicación o pagues, por ejemplo.
#550
Una función recursiva que reciba dos parámetros: la cadena (un puntero) y el paso (un entero).

La llamada a la función desde el main se hace pasando como paso un 0.

La función calcula, en base al paso, la posición desde la que debe empezar a comprobar, la cantidad de cifras a chequear y si éstas deben ser pares o impares:

* paso 0: 1 cifra, empieza en 0 y debe ser par
* paso 1: 2 cifras, empieza en 1 y deben ser impares
* paso 2: 3 cifras, empieza en 3 y deben ser pares
...

Si la comprobación es correcta se vuelve a llamar a sí misma incrementando el paso en 1 y retornando la salida de esta última llamada.

Si, en cambio, ha llegado al final de la cadena, retorna un 1.

Si no se cumple la validación, retorna un 0.

Después de todo el proceso, si tienes un 1 es que el número es M-Alternante y si es un 0... pues no.