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

#221
Chachi ^^. Un paso curioso sería hacerlas animadas (borrando y reescribiendola con otra posición cada x tiempo).

Yo de florituras en la pantalla, ni se me dan bien ni me gustan mucho. Por no dejar el tema a medias he hecho algo más de mi gusto: Una class Triangulo_Pascal:

Código (cpp) [Seleccionar]
/** Resumen de los metodos públicos:

- Constructor(int n = 0): Genera un triangulo de pascal de tamanyo N
- Constructor(triangulo_pascal): Constructor copia.
- getPosicion(int x,int y): Devuelve el valor en la posicion en la posicion x,y. Lanza una excepcion si es una posición incorrecta
- getSize(): Devuelve el tamanyo actual del triangulo
- resize(int n): Reconstruye el triangulo para un ancho n
- clear(): Borra el triangulo dejandolo con un tamanyo 0.
- toString(): Obtiene una expresion escrita del triangulo.

Operadores:

triangulo_pascal = triangulo_pascal   /** asignacion *
triangulo_pascal == triangulo_pascal  /** iguales? *
triangulo_pascal != triangulo_pascal  /** diferentes? *
**/

class triangulo_pascal
{
   int** Matriz;
   int TAM;
   string texto;

   int contar_cifras() const
   {
       int cifras = 1;
       int aux = Matriz[TAM-1][TAM/2];

       while (aux > 9)
       {
           cifras++;
           aux /= 10;
       }

       return cifras;
   }

   void generar(const int n)
   {
       TAM = n;
       Matriz = new int*[n];
       Matriz[0] = new int[1];
       Matriz[0][0] = 1;

       for (int i = 1; i < n;i++)
       {
           Matriz[i] = new int[i+1];

           Matriz[i][0] = 1;
           for (int j = 1; j < i;j++)
           {
               Matriz[i][j] = Matriz[i-1][j-1]+Matriz[i-1][j];
           }
           Matriz[i][i] = 1;
       }

       generarString();
   }

   void generarString()
   {
       stringstream ss;

       const int size = contar_cifras();

       for (int i = 0; i < TAM;i++)
       {
           for (int k = 0; k <= (TAM-i-2);k++)
               ss<<" ";

           ss<<Matriz[i][0];

           for (int j = 1; j <= i;j++)
           {
               ss<<" ";

               ss<<setw(size)<<Matriz[i][j];
           }

           ss<<endl;
       }

       texto = ss.str();
   }
public:
   triangulo_pascal(int n = 0)
   {
       if (n != 0)
       {
           generar(n);
       }
       else Matriz = NULL;
   }

   triangulo_pascal(const triangulo_pascal &a)
   {
       if (a.getSize() != 0)
           generar(a.getSize());
       else Matriz = NULL;
   }

   triangulo_pascal& operator=(const triangulo_pascal &a)
   {
       if (a.getSize() != 0)
           generar(a.getSize());
       else Matriz = NULL;
   }

   bool operator==(const triangulo_pascal &b)
   {
       return TAM == b.TAM;
   }

   bool operator!=(const triangulo_pascal &c)
   {
       return TAM != c.TAM;
   }

   int getPosicion(int x,int y) const
   {
       if (y < TAM || (x > y)) throw "Error, fuera de rango";
       return Matriz[x][y];
   }

   int getSize() const { return TAM;}

   void resize(int n)
   {
       if (n < 0) throw "Error, tamanyo negativo";

       clear();

       if (n == 0){return;}

       generar(n);
   }

   void clear()
   {
       if (Matriz == NULL) return;

       for (int i = 0; i < TAM;i++)
           delete[] Matriz[i];

       delete[] Matriz;

       Matriz = NULL;
       TAM = 0;
   }

   string toString() const
   {
       return texto;
   }

   operator string()
   {
       return toString();
   }

   ~triangulo_pascal()
   {
       clear();
   }
};


De la cual, podemos hacer algunas pruebas:

Código (cpp) [Seleccionar]
int main()
{
   triangulo_pascal mi_triangulo(5);

   cout<<mi_triangulo.toString()<<endl;
   mi_triangulo.resize(4);
   cout<<mi_triangulo.toString()<<endl;

   triangulo_pascal segundo(1);

   if (mi_triangulo != segundo)
   {
       cout<<"Son diferentes :("<<endl<<endl;
   }

   cout<<(string)segundo<<endl; // otra forma de pasarlo a string es usando los casts
   return 0;
}


El mayor fallo que tiene es la función para pasarlo a string, que aunque siempre genera el triangulo, lo hace un poco "raro" para algunos valores de N.
#222
Programación C/C++ / Re: Ayuda con programa
16 Marzo 2014, 13:25 PM
Cita de: leosansan en 16 Marzo 2014, 13:20 PM
Creo que dejaste atrás const:
Me lo dejé aposta, si le pongo el const no puedo aumentar el puntero ;)
#223
Programación C/C++ / Re: Ayuda con programa
16 Marzo 2014, 02:08 AM
Incluso más todavía:
Código (cpp) [Seleccionar]
char coincidencia(const char letra,char* diccionario)
{
    while (*diccionario)
        if (letra == *diccionario) return 1;
        else diccionario++;
    return 0;
}


^^
#224
La línea de comandos es muy util a la hora de comunicarse entre programas. Por eso todavía se sigue usando en la mayoría de programas de consola (linux mayormente xD).

Los comandos simplemente son cadenas de texto separadas por espacios:
Citartexto 1 2 3

De esa forma le pasaría al programa 4 cadenas: "texto","1","2" y "3".

De todas formas y con permiso, traduzco para que no tengas que usar linea de comandos:
Código (cpp) [Seleccionar]
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

int ** pascal( const int );
int ** tartaglia( const int );
void destroy_pascal( int **, const int );
void destroy_tartaglia( int **, const int );
int digits( int );

int main(int argc, char* argv[])
{

   int **A, N;
   int i;
   int width, col;
   char *board[2];
   puts("Introduce el valor de N: ");
   scanf("%d",&N);
   putchar('\n');

   if ( N < 0 )
   {
       printf("Solo para N >= 0\n");
       return -1;
   }
   if ( N == 0 )
   {
       printf("a + b\n");
       return -1;
   }

   /* Coeficientes de pascal */
   A = pascal( N );

   /* Calculamos el ancho total de la cadena */
   width = 0;
   for ( i = 0; i <= (float)N/2; i++ )
   {
       if ( i == 0 ) /* terminos a^N, y b^N */
           width += 2 * ( 1 + digits(N) );
       if ( i == 1 ) /* terminos a^(N-1)*b, y a*b^(N-1) */
           width += 2 * ( 2 + digits(A[N][i]) + digits(N-1) );
       if ( i > 1 ) /* terminos a^(N-i)*b^i */
           if ( !(N % 2) && i == (float)N/2 )
               /* termino central se suma solo una vez */
               width += 2 + digits(A[N][i]) + digits(N-1) + digits(i);
           else
               /* y los restantes, dos veces */
               width += 2 * ( 2 + digits(A[N][i]) + digits(N-1) + digits(i) );
   }
   /* cadenas " + " */
   width += 3 * N;

   /* Representacion final */
   if ( ( board[0] = malloc( (width + 1) * sizeof(char) ) ) == NULL )
       return -1;
   if ( ( board[1] = malloc( (width + 1) * sizeof(char) ) ) == NULL )
       return -1;

   memset( board[0], ' ', width + 1);
   memset( board[1], ' ', width + 1);
   col = 0;
   for ( i = 0; i <= N; i++)
   {
       if ( A[N][i] != 1 )   /* binomial N sobre i */
       {
           col += sprintf( board[1] + col, "%d", A[N][i] );
           board[1][col] = ' ';
       }
       if ( N - i > 0 ) /* base 'a' */
           board[1][col++] = 'a';
       if ( N - i > 1 )   /* exponente N - i */
       {
           col += sprintf( board[0] + col, "%d", N - i);
           board[0][col] = ' ';
       }
       if ( i > 0 ) /* base 'b' */
           board[1][col++] = 'b';
       if ( i > 1 )   /* exponente i */
       {
           col += sprintf( board[0] + col, "%d", i);
           board[0][col] = ' ';
       }
       if ( i < N )
       {
           col += sprintf( board[1] + col, " + ");
           board[1][col] = ' ';
       }
   }
   board[0][width] = '\0';
   board[1][width] = '\0';
   printf( "(a + b)^%d es:\n\n%s\n%s\n", N, board[0], board[1] );

   /* Liberando memoria, y saliendo */
   free( board[0] );
   free( board[1] );
   destroy_pascal( A, N);
   return 0;
}

/* Construye una matriz que contiene los numeros del triangulo
* de Pascal o Tartaglia de orden N > = 0, con N + 1 filas.
* La matriz es tal que A[i][j] corresponde al binomial (i : j).
* Se devolverá NULL si N < 0, o si no se pudo asignar memoria
* para construir la matriz.
*/
int ** pascal( const int N )
{

   int **A;
   int i, j;

   if ( N < 0 ) return NULL;

   if ( ( A = malloc( (N + 1) * sizeof(int *) ) ) == NULL ) return NULL;
   for ( i = 0; i < N + 1; i++ )
       if ( ( A[i] = malloc( (i + 1) * sizeof(int) ) ) == NULL ) return NULL;

   for ( i = 0; i < N + 1; i++ )
   {
       A[i][0] = 1;
       A[i][i] = 1;
       /* solo se ejecuta si i > 1 */
       for ( j = 1; j < i; j++ )
           A[i][j] = A[i-1][j-1] + A[i-1][j];
   }

   return A;
}

/* Destruye el objeto creado por la función pascal() */
void destroy_pascal( int ** A, const int N )
{

   int i;

   if ( N < 0 ) return;

   for ( i = N; i >= 0; i-- )
   {
       free( A[i] );
       A[i] = NULL;
   }
   free( A );
   A = NULL;
}

/* Un sinónimo de pascal( N ) */
int ** tartaglia( const int N )
{

   return pascal( N );
}

/* Un sinónimo de destroy_pascal( N ) */
void destroy_tartaglia( int ** A, const int N )
{

   return destroy_pascal( A, N );
}

/* Calcula la cantidad de cifras o digitos que conforman un
* numero entero no negativo;
*/
int digits( int N )
{

   int count = 1;

   if ( N < 0 ) return 0;
   if ( N == 0 ) return 1;

   while ( ( N = (N / 10) ) > 0 )
       count++;

   return count;
}
#225
Programación C/C++ / Re: dudas con strcpy
16 Marzo 2014, 00:28 AM
Cita de: leosansan en 16 Marzo 2014, 00:11 AM
La salida que obtienes viene a corroborar el origen de mi duda:

Lo que queda en str1 es justo lo que cabe "oficialmente" en str2 .....
Vuelve a repasar mi mapa de memoria, ahi explico porque str2 puede almacenar una cadena mayor (comiendole memoria a otras variables ;D).

Cita de: leosansan en 16 Marzo 2014, 00:11 AM* En str1 "queda" lo que "teóricamente" no cabia en str1 por tener menor dimensión.
Podemos usar memoria dinamica, de esa forma nos aseguramos que no ocupan posiciones continuas y no se cumpla mi teoría:
Código (cpp) [Seleccionar]
#include <stdio.h>
#include <string.h>

int main ()
{
    int tam = strlen("Entrada larga");
   char* str1 = malloc(tam+1);
   strcpy (str1,"Entrada larga");

   char str2[5] = "abcd";

   strcpy (str2,str1);
   printf ("\n\nLo que queda en str1: %s\n\nCopiado, nuevo str2:\n%s\n\n",str1,str2);
   printf("\n\nY la cadena str2 impresa caracter a caracter:\n ");
   int i;
   for( i=0; str2[i]; i++)
       printf( "%c",str2[i] );
   return 0;
}


Tu regla no se cumple ya que da un error de ejecución en el segundo strcpy. Probablemente porque estemos escribiendo fuera de nuestra memoria reservada.

Cita de: leosansan en 16 Marzo 2014, 00:11 AMFíjate que "da laZga" es justo la cadena str1 sin los 5 caracteres que "cabrían" en str2" de acuerdo a su dimensión. Curioso, ¿no?.
La Z fue introducida después del strcpy, eso quiere decir que esa letra era "común" en las dos cadenas (vuelvo a hacer referencia a mi esquema de la memoria).
#226
Cita de: leosansan en 15 Marzo 2014, 23:51 PM
Al ejecutar tu código tal como está me sale esto:


¿Alguna idea al respecto?, ¿O acaso funciona con comandos?. Lo he guardado por si acaso.

¡¡¡¡ Saluditos! ..... !!!!


Se te ha activado el primer if del código.

Y si, solo funcionaba por comandos. En el codeblocks se lo puedes meter en project -> "Set programs arguments".

Para que funcione tiene que ser un proyecto, no vale un archivo.
#227
Programación C/C++ / Re: dudas con strcpy
15 Marzo 2014, 23:50 PM
Cita de: leosansan en 15 Marzo 2014, 23:24 PMHe ahí mi gran duda, ¿será casualidad o es un comportamiento normal de la función strcpy "dejar" el resto de la cadena que no quepa en str2?. Y a los ejemplos me remito, claro que tan sólo son dos ejemplos y ya sabemos que no se puede pasr del particular al general, pero ....
Tengo una teoría.

Suponte este caso:

Código (cpp) [Seleccionar]
char inicia[] = "Entrada larga";
char destino[5] = "abcd";


La memoria podría ser:
Citar
00 a   --> Destino
01 b
02 c
03 d
04 '\0'
05 E   --> Original
06 n
07 t
08 r
09 a
10 ' '
11 l
12 a
13 r
14 g
15 a
16 '\0'

Y hacemos el strcpy:

Citar
00 E    --> Destino
01 n
02 t
03 r
04 a
05 d    --> Original
06 a
07 ' '
08 l
09 a
10 r
11 g
12 a
13 '\0'
14 g
15 a
16 '\0'

Fijate que el puntero "original" apunta a las ultimas posiciones de "destino".

No esque deje lo que sobre, esque estamos viendo los ultimos caracteres de la cadena destino!

Lo acabo de probar y efectivamente str1 da la salida que esperaba: "da larga"
Código (cpp) [Seleccionar]
#include <stdio.h>
#include <string.h>

int main ()
{
   char str1[] = "Entrada larga";
   char str2[5] = "abcd";

   strcpy (str2,str1);
   printf ("\n\nLo que queda en str1: %s\n\nCopiado, nuevo str2:\n%s\n\n",str1,str2);
   printf("\n\nY la cadena str2 impresa caracter a caracter:\n ");
   int i;
   for( i=0; str2[i]; i++)
       printf( "%c",str2[i] );
   return 0;
}


Podríamos "rematar" la teoría modificando un valor de str2. A ver si esos cambios aparecen en str1:

Código (cpp) [Seleccionar]
#include <stdio.h>
#include <string.h>

int main ()
{
   char str1[] = "Entrada larga";
   char str2[5] = "abcd";

   strcpy (str2,str1);
   

   str2[10] = 'Z';

   printf ("\n\nLo que queda en str1: %s\n\nCopiado, nuevo str2:\n%s\n\n",str1,str2);
   printf("\n\nY la cadena str2 impresa caracter a caracter:\n ");
   int i;
   for( i=0; str2[i]; i++)
       printf( "%c",str2[i] );
   return 0;
}


Cuya salida es:



¡La Z aparece en las dos cadenas! Parece que mi teoria tiene sentido : )

Cita de: yoel_alejandro en 15 Marzo 2014, 23:26 PMNo lo se porque en lo particular siempre trato de programar de forma "segura", atendiendo a las especificaciones de la biblioteca estándar de C, y la verdad pocas veces me he puesto a ver qué pasa si hago tal o cuál cosa de manera insegura. Prefiero irme de una vez por lo sano, y así evitar crasheos, etc.
Eso está bien ^^

Cita de: yoel_alejandro en 15 Marzo 2014, 23:26 PMPero respecto a lo de varios lenguajes lo que quise decir es que específicamente en el aprendizaje de C/C++, me parece más adecuado aprender primero a programar correctamente en C, y luego pasarse a C++ el cual básicamente amplica las capacidades del primero. Eso en lugar de mezclar el C y el C++, lo que constituye una mala costumbre según el criterio unánime creo que todos los que opinamos aquí.
Bueno yo hize eso, aunque mucha gente empezó a programar en Python o en Java.

Luego no tuvieron problema en pasar de un lenguaje a otro. Como siempre, lo importante no es el lenguaje sino en saber describir la solución a un problema.

Cita de: yoel_alejandro en 15 Marzo 2014, 23:26 PMOtra mala costumbre, y lamentablemente extendida entre algunos maestros, es no guiarse por el C estándar. Referirse a gotoxy(), getch(), etc., de la manera más natural (y descarada), sin especificar ni aclarar que son no funciones estándares. No digo que no usen esas funciones, pero deben dejar en claro que son privativas y generalmente usadas en Windows.
+1, totalmente de acuerdo.
#228
Programación C/C++ / Re: Ayuda con programa
15 Marzo 2014, 23:19 PM
Me he dado cuenta que no hace falta la funcion strlen, simplemente basta con cambiar la condición funcion coincidencia:

Código (cpp) [Seleccionar]
char coincidencia(const char letra,const char* diccionario)
{
   int i = 0;
   for (;diccionario[i];i++)
   {
       if (letra == diccionario[i]) return 1;
   }
   return 0;
}


Un parametro menos ^^
#229
El programa es muy bonito y elegante ^^. ¡Good job!


Aunque si la función pascal devuelve NULL, el main no lo comprueba y lo usa de todas formas. Lo que generaría un error de ejcución.

Por estos olvidos se inventaron las excepciones de C++ ^^
#230
Programación C/C++ / Re: Ayuda con programa
15 Marzo 2014, 22:55 PM
La función original no escribe en la pantalla ;D, sino que "fragmenta" una cadena en varios trozos.

Presento la mía que hace lo mismito que la strtok:
Código (cpp) [Seleccionar]
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>

char* mi_strtok( char *frase,const char* delim);
char coincidencia(const char letra,const char* diccionario,const int tam);

int main( )
{
   char frase[101];

   printf("Intro frase: ");
   fflush( stdout );
   fgets(frase, 101, stdin);
   char* s;

   if ( ( s = mi_strtok( frase, ",") ) != NULL )
       printf( "%s\n", s );

   while ( ( s = mi_strtok( NULL, ",") ) != NULL )
       printf( "%s\n", s );

   return 0;
}

char* mi_strtok( char *frase,const char*delim )
{
   static char* frase_actual = NULL;
   char* principio;

   if (frase != NULL)
   {
       frase_actual = frase;
   }
   else if (frase_actual == NULL) return NULL;

   principio = frase_actual;

   const int tam = strlen(delim);
   char c;

   while ( ( c = *frase_actual ) != '\0' )
   {
       if (coincidencia(c,delim,tam))
       {
           *frase_actual = '\0';
           frase_actual++;
           return principio;
       }

       frase_actual++;
   }

   frase_actual = NULL;

   return principio;
}

char coincidencia(const char letra,const char* diccionario,const int tam)
{
   int i = 0;
   for (; i < tam;i++)
   {
       if (letra == diccionario[i]) return 1;
   }
   return 0;
}


La entrada: "1,2,3,4" me genera:
Citar1
2
3
4