Publi

Número variable de argumentos en una función de C

photo-1416339212457-ef9ffadc2903_rSi habéis programado en C, seguramente la primera función que aprendisteis a utilizar era printf() ; y en todo el tiempo que pasasteis estudiando C no encontrasteis una función similar. Y es que esta función puede tener un número indeterminado de parámetros y es capaz de analizarlos todos.

Y es que quitando printf(), scanf() y derivadas de estas, la necesidad de una función con múltiples parámetros casi no se nos presenta. Aunque tal vez, alguna vez necesitemos crear una función con parámetros opcionales, es decir, si están presentes se tomarán y si no, se tomará un valor por defecto.

Esto lo podemos hacer con la biblioteca stdarg.h la cual nos proporciona macros para hacer esto posible.

Echemos un vistazo al siguiente código:

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

void poneargs(int nargs, ...)
{
  va_list ap;
  int i;
  int num;

  va_start(ap, nargs);
  for (i =0; i<nargs; i++)
    {
      num=va_arg(ap, int);
      printf("Argumento %d = %d\n", i, num);
    }
  va_end(ap);
  printf("\n");
}

int main(int argc, char *argv[])
{
  poneargs(5, 6, 77, 445, 34, 23, 12, 43, 32);
  poneargs(2, 23, 94);
  poneargs(0);

  return EXIT_SUCCESS;
}

Aquí vemos cómo la función poneargs() nos coloca los valores de los argumentos que le hemos pasado, siendo el primero de ellos el número total de argumentos que tenemos.
Con esto, hay que dejar claro que no tenemos forma de contar los argumentos que pasamos (igual que printf, podíamos pasar tantos argumentos como %[x] tuviéramos en la cadena de formato). Así que las técnicas para llegar al límite de los comandos son:

  • Poner un argumento indicando el número de argumentos a colocar.
  • Poner un argumento con un valor fijo al final que nos indique que hemos llegado al último parámetro.
  • Poner códigos con los argumentos que tenemos que leer. Idea de printf()

Lo que sí que tenemos que tener en cuenta es que, como estamos acostumbrados cada argumento tiene un tipo fijo, y se lo tenemos que decir a va_arg() en su segundo argumento; y va_arg() nos va a devolver una variable del mismo tipo que le dijimos (éste es el valor del argumento).

En el siguiente ejemplo creamos una función new_cliente() que puede tener hasta cuatro argumentos de tipo cadena de caracteres. De hecho son opcionales. Cuando creamos un cliente en un programa real puede que no tengamos todos sus datos y puede que algunos sean opcionales:

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

void new_cliente(int nargs, ...)
{
  va_list ap;

  char *valor;

  va_start(ap, nargs);

  switch (nargs)
    {
    case 4:
      valor=va_arg(ap, char*);
      printf("Twitter: %s\n", valor);      
    case 3:
      valor=va_arg(ap, char*);
      printf("URL: %s\n", valor);      
    case 2:
      valor=va_arg(ap, char*);
      printf("Blog: %s\n", valor);      
    case 1:
      valor=va_arg(ap, char*);
      printf("Nombre: %s\n", valor);
      break;
    default:
      printf("Número de parámetros incorrecto\n");
    }
 
  va_end(ap);
  printf("\n");
}

int main(int argc, char *argv[])
{
  printf("Un parámetro:\n");
  new_cliente(1, "Gaspy");

  printf("Dos parámetros:\n");
  new_cliente(2, "Gaspy", "Poesía Binaria");

  printf("Tres parámetros:\n");
  new_cliente(3, "Gaspy", "Poesía Binaria", "http://totaki.com/poesiabinaria/");

  printf("Cuatro parámetros:\n");
  new_cliente(4, "Gaspy", "Poesía Binaria", "http://totaki.com/poesiabinaria/", "http://twitter.com/blakeyed");

  return EXIT_SUCCESS;
}

Esto también podría valernos como una pequeña simulación de sobrecarga de funciones (estilo C++) aunque en C no cumpliría la tarea de hacer más legible el código ya que en la misma función tendríamos que incluir las opciones de los argumentos.

Foto principal: Jeff Seldon

También podría interesarte...

There are 8 comments left Ir a comentario

  1. Pingback: Bitacoras.com /

  2. kenkeiras /
    Usando Mozilla Firefox Mozilla Firefox 3.6.13 en Linux Linux

    Joe, cuanto me llevaré preguntando como hacer esto, muchas gracias :P, solo una duda, los ‘…’ que hay en el código son literales, es decir se copia y pega y funciona, después de los documentos fijos se ponen … en el código representando el resto ?

    Saludos y gracias otra vez

  3. Gaspar Fernández /
    Usando Mozilla Mozilla 1.9.1.8 en Linux Linux

    @kenkeiras
    Sí, exacto, tres puntos literales. El código debe funcionar nada más que copiando y pegando de aquí, luego puedes jugar como quieras 🙂

    Gracias a ti

  4. Pingback: Tweets that mention Poesía binaria » Número variable de argumentos en una función de C — Topsy.com /

  5. Pingback: BlogESfera.com /

  6. kenkeiras /
    Usando Mozilla Firefox Mozilla Firefox 3.6.13 en Linux Linux

    ok, de vicio 😛

  7. Pingback: Poesía binaria » Formateando la salida en Serial para Arduino [1ª parte] ( y no sólo para Arduino ) /

  8. Pingback: Encadenando comandos en C : ls | grep | wc | Poesía Binaria /

Leave a Reply