Publi

  • Generador de números primos en C

    Un ejercicio de estos típicos de lenguaje C, es la generación de números primos y la comprobación de éstos. Ni que decir tiene que esta es sólo una de las 13.485,72 maneras (o más) de solucionar este problema. Y es más estamos complicando un poco la cosa, ya que sólo generaremos 10 números, que se almacenarán en un fichero binario, y a la siguiente vez que ejecutamos el programa, se leerá ese último número y seguiremos generando primos a partir de ahí:

    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 <math.h>

    // Comprobamos si un número es primo o no
    int es_primo(int numero)
    {
      int res=0;
      int divs=2;
      int mitad;
      if (numero>2)    // Si el número es mayor a 2, comprobamos si es primo.
    Leer artículo completo
  • Capicúa recursivo en C

    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
    #include <stdio.h>
    #include <stdlib.h>

    int alreves(int n, int digitos)
    {
      int resto, cocie;

      if (n<10)     // Si tenemos un número de dígitos menor a 2, devolvemos n
        return n;
      else
        {
          resto = n % 10;
          cocie = n / 10;
          return resto*digitos + alreves(cocie, digitos/10);
        }
    }

    int main()
    {
      int num, rev;
      int digitos = 1;
      int tmp;
      printf("Dame un numero: ");
      scanf("%d", &num);
      // Hacemos un número 10^(numero de cifras-1) con esto alreves determinará el
      // número de cifras que tiene el número dado.
    Leer artículo completo
  • Tuberías con nombre para comunicación entre procesos

    photo-1428585227457-326f25f9cee2
    Las tuberías con nombre son un método de comunicación FIFO entre procesos (también se les llama fifos). FIFO son las siglas de First In First Out, es decir, el primero que llega es que primero que se marcha, como en una cola, el primero que llega es el que antes termina.

    Normalmente las tuberías son anónimas, aunque el hecho de tenerlas con un nombre en nuestro sistema de ficheros puede sernos de gran utilidad.… Leer artículo completo

  • Controlar señales

    A veces, se nos presenta la necesidad de modificar el comportamiento de nuestro programa por ejemplo cuando el usuario pulse Control+C, o cuando terminemos nuestra aplicación, o cuando… dividamos por 0, o más cosas… podemos ver un listado de las diferentes señales con:

    man 7 signal

    Podemos utilizar para probar este programa (signals.c):

    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
    #include <signal.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    void salir(int recib);
    void alarma(int que);
    int tmp=0;
    int divi=5;
    int main()
    {
        signal(SIGINT, salir);  /* Control+C */
        signal(SIGKILL, salir); /* kill */
        signal(SIGFPE, salir);  /* división por 0 */
        signal(SIGALRM, alarma);    /* alarma */
        signal(SIGUSR1, alarma);    /* definido por el usuario */
        int numero=4;
        while (1)
            {
                usleep(1000);       /* Le damos un respiro a la CPU mientras estamos en el bucle */
                tmp++;
                if (tmp%1000==0)
                {
                    tmp=tmp/divi;
                    printf("tmp = %d\n", tmp);
                }
            }
    }
    void salir(int recib)
    {
        printf("Salgo porque ");
        switch (recib)
            {
            case SIGINT: printf("has pulsado Control+C...
    Leer artículo completo
  • 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
  • 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
  • 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