Publi

  • Intercambiar valores

    Cuando queremos hacer que una variable a sea igual a una variable b y viceversa (intercambiar los valores), lo primero que se viene a la mente, es utilizar una variable auxiliar, como en este ejemplo:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    #include <stdio.h>
    void intercambia(int *x, int *y);
    int main()
    {
        int a=50;
        int b=90;
        printf("a=%d t b=%dn", a, b);
        intercambia(&a, &b);
        printf("a=%d t b=%dn", a, b);
    }
    void intercambia(int *x, int *y)
    {
        int tmp;
        tmp=*x;
        *x=*y;
        *y=tmp;
    }

    Aunque puede que queramos (o que nos pidan) hacerlo sin variable temporal, podemos hacer un intercambiador con sumas y restas:

    1
    2
    3
    4
    5
    6
    void intercambia2(int *x, int *y)
    {
        *x=*x+*y;           /* x=x+y */
        *y=*x-*y;           /* y=x-y */
        *x=*x-*y;           /* x=x-y */
    }

    Y con las propiedades de la operación XOR también podemos jugar:

    1
    2
    3
    4
    5
    6
    void intercambia3(int *x, int *y)
    {
        *x ^= *y;           /* x = x xor y */
        *y ^= *x;           /* y = y xor x */
        *x ^= *y;           /* x = x xor y */
    }

    Pero lo bueno de estos dos últimos métodos es que los podemos utilizar desde macros de preprocesador, y con eso nuestro código se ejecutará mucho más rápido:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    #define interc(x,y) x=x+y; y=x-y; x=x-y;
    int main()
    {
        int a=-50;
        int b=40;
        printf("a=%d t b=%dn", a, b); /* a=-50 b=40 */
        interc(a, b);
        printf("a=%d t b=%dn", a, b); /* a=40 b=-50 */
    }

    Para ver lo rápido que se ejecuta, he hecho el programa intercambiando continuamente en un bucle for de unos 300000000 (trescientos millones) de iteraciones lo siguiente:

    Para la macro de preprocesador interc(a,b),

    gaspy@XiKiTiN ~/proyectos/poesiabinaria $ time ./interc
    a=-50 b=40
    a=-50 b=40

    real 0m8.027s
    user 0m7.461s
    sys 0m0.022s

    Para intercambia(a,b) (con variable auxiliar):

    gaspy@XiKiTiN ~/proyectos/poesiabinaria $ time ./intvaux
    a=-50 b=40
    a=-50 b=40

    real 0m8.691s
    user 0m7.058s
    sys 0m0.022s

    Para intercambia2(a,b), con sumas y restas:

    gaspy@XiKiTiN ~/proyectos/poesiabinaria $ time ./intsyr
    a=-50 b=40
    a=-50 b=40

    real 0m12.331s
    user 0m10.508s
    sys 0m0.024s

    Para intercambia3(a,b) con xor:

    gaspy@XiKiTiN ~/proyectos/poesiabinaria $ time ./intxor
    a=-50 b=40
    a=-50 b=40

    real 0m11.882s
    user 0m10.516s
    sys 0m0.031s

    Por lo tanto vemos, que el método de la variable auxiliar es bastante rápido, mucho más que haciendo sumas y restas y xor (por lo tanto estos métodos no sirven de mucho, sobre todo ahora, que la memoria es barata), aunque, con las sumas y restas nos acercamos en tiempo al método de la variable auxiliar cuando lo hacemos desde una macro.… Leer artículo completo

  • Decimal a Binario (y negativos en Complemento a 2)

    Aquí traigo un fragmento de código que nos puede ayudar bastante a la hora de hacer cambios de base de decimal a binario, sobre todo porque para manejarnos con los números negativos utilizamos el Complemento a dos.

    En principio, antes de hacer esta función miré un poco el blog Static Zero, y luego me decidí simplificar un poco el código. Así ha quedado:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    int *decToBin(int decimal, int nBits, int binary[]) {
        int i;

        int flag = 0;
        /* Si es un número negativo, lo hacemos positivo y le restamos 1(*), */
        /* además activamos el flag para saber que es negativo */

        /* (*) El complemento a 2 es igual que el complemento a 1, que es cambiar */
        /* 1->0, 0->1, y luego sumando 1 en binario.
    Leer artículo completo
  • Correcciones

    He estado echando un vistazo a mis tres últimos posts y vi que no salieron bien algunas cosas, ahora creo que estan bien.

    Disculpad las molestias… Leer artículo completo

  • Depurando…

    A veces es muy útil saber el contenido de una variable en mitad de ejecución del programa, pero cuando queremos compilar la versión definitiva, eliminar todas las trazas de depuración de una vez, aunque cuando estemos desarrollando, es interesante volverlas a tener.

    Podemos hacerlo de forma sencilla con algunas macros de preprocesador de C; podemos poner un pequeño fragmento de código al empezar cada programa, y lo mejor de todo es que la versión definitiva seguirá ocupando lo mismo, ya que si desactivamos la depuración es como si en el código final no se escribieran las trazas.… Leer artículo completo

  • Colores y posicionamiento en terminales Linux (como conio.h en DOS)

    A veces, es un poco difícil que alguien que sólo conoce conio.h se pase a Linux, más que nada, porque se puede utilizar ncurses, pero hay que cambiar un poco de mentalidad para poder trabajar con la nueva biblioteca.

    Por eso, hace unos meses creé unas cuantas funciones que se podían utilizar para ir reemplazándolas poco a poco. Funcionan de forma muy parecida a conio.h (en los colores). Se basan en códigos ANSI, y las podemos utilizar para cualquier programa rápido en que necesitemos utilizar colores en terminal.… Leer artículo completo

  • Funciones que devuelven arrays

    Al principio, cuando empezaba a programar, yo me quejaba mucho de esa tonta manía de C que no me dejaba devolver arrays como resultado de una función.

    Aunque al final, devolver arrays es una tontería, gasta memoria, gasta tiempo y termina siendo más fácil solucionarlo todo con un puntero.

    Pero bueno, si realmente queremos devolver un array, siempre podemos meterlo dentro de un registro. Probando con una cadena de caracteres:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    #include <stdio.h>
    #include <string.h>

    typedef struct
    {
        char cadena[1000];
    } t_array;

    t_array devuelvo()
    {
        t_array otroarr;
        printf("\nDirección de cadena: %X\nCadena: %s\n", &otroarr, otroarr.
    Leer artículo completo
  • Decir la hora en palabras (v1)

    Si tenéis un equipo Linux que actúe como servidor y equipo de música (por poner algo), y no tenga un monitor conectado en todo momento; os puede ser útil este script:

    1
    2
    3
    4
    5
    6
    7
    8
    #!/bin/bash

    hora=`date +%H`
    min=`date +%M`

    decir="Son las "$hora" y "$min

    echo $decir | espeak -ves

    Si asociamos este script a una combinación de teclas, por los altavoces nos dirá la hora que es.… Leer artículo completo

  • Cronometrar código (matlab)

    Matlab® es un lenguaje muy utilizado en ingeniería, ya que permite hacer de forma más o menos sencilla cálculos matemáticos muy complejos, y a veces necesitamos procesar gran cantidad de datos y llega a ser desesperante ver cómo tarda sin tener tan siquiera una ligera idea de cuánto queda.

    El principio del código que voy a postear se basa en dos funciones: tic y toc. La primera de ellas marca el inicio de la cuenta de tiempo, y la segunda el final, indicándonos los segundos transcurridos entre tic y toc.… Leer artículo completo

  • Texto personalizado en matlab

    Cuando trabajamos con Matlab® a la hora de poner los datos de una variable en pantalla, basta con poner la variable (sin ; al final), pero si queremos escribir un texto cualquiera, debemos utilizar disp():

    1
    disp('Estoy escribiendo un mensaje en matlab');

    Pero si queremos intercalar información o escribir nuestras variables de una forma más elegante, debemos utilizar sprintf(), se comporta como el sprintf() de C, y acepta sus \n, \t, %d, %f, %s… incluso podemos formatear la salida como veremos en el ejemplo.… Leer artículo completo

  • Desea continuar? [(S)i, (N)o, (M)e lo pienso]

    Es común en los programas de consola hacer preguntas al usuario y éste responda, pero sólo una de las opciones válidas, si no, volver a preguntarle hasta que nos diga un valor correcto.

    Aquí os enseño un ejemplo sencillo de todo esto (utilizaré la función mygetch):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    #include <stdio.h>
    #include <termios.h>
    #include <unistd.h>
    #include <string.h>

    int mygetch(int echo)
    {
        struct termios oldt, newt;
        int ch;

        /* Obtenemos atributos del terminal */
        tcgetattr( STDIN_FILENO, &oldt );
        newt = oldt;
        /* Eliminamos el modo canónico: caracteres especiales */
        newt.
    Leer artículo completo