Parámetros Línea de Comandos. C, C++ y Objective-C
SOLUCIONARIO
Parámetros Línea de Comandos. C, C++ y Objective-C
2025-09-14
Por
Occam's Razor

#include <stdio.h>
#include <stdlib.h>

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

  printf ("%d Parametros...\n", argc);
  
  for (i = 0; i < argc; i++)
    printf ("Parámetro %d: %s\n", i , argv[i]);

  /* Primer Parametro (0) es el nombre del programa */
  if (argc != 2)
    {
      fprintf (stderr, "Solo un parámetro por facor\n");
      exit (1);
    }
  printf ("Hola %s\n", argv[1]);

  return 0;
}

C y C++ (de hecho, Objective-C también) recibe los parámetros que pasamos a través de la línea de comandos como dos parámetros en la función main.

Estos parámetros se conocen tradicionalmente como argc (Argument Counter o contador de argumentos) que indica el número de parámetros que vamos a recibir, y argv (Arguments Vector o vector de argumentos). Los argumentos siempre se reciben en el programa como un array (vector) de cadenas de caracteres.

¿SABÍAS QUE?

Existe un tercer parámetro que recibimos en main pero que normalmente no se utiliza. Se trata de un array con las variables de entorno definidas para este proceso. Para poder utilizar este parámetro debemos declarar nuesta función main de la siguiente forma.

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

Los nombre de las parámetros son arbitrarios y podéis llamarlos como queráis, por ejemplo:

int main (int contador, char *los_parametros[])

Si bien, ver eso hará sangrar los ojos de cualquier desarrollador de C.

En condiciones generales, el primer parámetro de argv contendrá el nombre del programa ejecutado, o si lo preferís, el primer argumento que pasamos al intérprete de comandos cuando ejecutamos un programa… el cual no es otra cosa que el nombre del programa que queremos ejecutar:

$ ls /tmp
  ^  ^
  |  +-------- Argumento 1 "/tmp"
  +----------- Argumento 0 "ls"
  

Esto es así siempre y cuando nuestro programa se ejecute desde una shell estándard. Sin embargo, esto no tiene que ser cierto y lo que el estándard dice es que los valores en argv son implementation-defined o que deben ser definidos por la implementación.

SOY NOVATO

En un sistema Linux los procesos se ejecutan utilizando la llamada al sistema execve, la cual tiene el siguiente prototipo:

 int execve(const char *pathname, char *const _Nullable argv[],
                  char *const _Nullable envp[]);

El primer parámetro es el nombre del fichero a ejecutar. El segundo es el contenido de argv que como véis se puede inicializar de forma totalmente arbitraria, es decir, podemos poner en argv[0] lo que nos de la gana. Finalmente las variables de entorno de las que hablamos, las cuales, una vez más, pueden ser cualquier cosa. Cuando ejecutamos un programa desde bash, el propio bash realiza la llamada a execve y se asegura de que todos los parámetros tienen los valores esperado, sin embargo, si este proceso se realiza de forma manual podemos cambiar cada uno de ellos a nuestro antojo.

El hecho de que la shell asegure que el primer parámetro es el nombre del programa nos permite escribir programas denominados genéricamente: Multicall Binaries, los cuales realizan distintas acciones dependiendo del nombre con el que son invocados. Algo como:

...
   if (!strcmp(argv[0],"cifrador")) cifra ();
   else if (!strcmp(argv[1], "descifrador)) descrifra ();

Hay multiples librerías disponibles para procesar los parámetros que recibimos por la línea de comandos de forma fácil y sencilla. Algunos ejemplos song getopt (POSIX standard) o argp (GNU), con la que podemos fácilmente procesar flags con y sin parámetros. Este sería un ejemplo utilizando getopt más sencilla y compacta, pero más limitada que argp.


  int opt;

  while ((opt = getopt (argc, argv, "ho:i:")) != -1) {
    switch (opt) {
    case 'h': fprintf (stderr, "%s", "Ayuda\n");break;
    case 'i': printf ("Fichero de entrada: %s\n", optarg); break;
    case 'o': printf ("Fichero de salida: %s\n", optarg); break;
    case '?': fprintf (stderr, "Opcion desconocida : %c\n", optopt);
    default:  break;
    }
  }

El código anterior procesa tres flags:

  • -h que mostrará un texto de ayuda
  • -o que acepta un argumento y que mostrará el fichero de salida seleccionado
  • -i que acepta también un argumento y mostrará el fichero de entrada seleccionado.

Como podéis ver, el tercer parámetro a getopt recibe una cadena con los flags que se quieren procesar. Si añadimos dos punto (:) tras el flag le estaremos diciendo a getopt que ese flag espera una argumento, el cual estará disponible en la variable global optarg actualizada automáticamente por getopt.

SOY NOVATO

getopt reordena las entradas de argv según las va procesando, de esta forma, al terminar el bucle while, es decir, tras procesar todas las opciones que sabe procesar, el resto de parámetros pasados al programa estarán que no estén precedidos por el signo - se econtrarán al final de argv comenzando en el índice optind. Esto es útil, por ejemplo, para procesar nombres de ficheros que queremos pasar a nuestro programa. Pensad por ejemplo en una utilizad como cat.

La función getopt retorna ? en caso de encontrar una opción que no se haya indicado en la cadena que pasamos como tercer parámetro y almacena en la variable optopt la opción que no ha podido reconocer o a la que le falte un parámetro.

¿SABÍAS QUÉ?

Hay una versión de getopt llamada getopt_long que nos permite usar flag de más de un caracter, por ejemplo nos permite definir los flags -h y --help como la misma cosa y procesarla automáticamente. El código es un poco más largo que el que hemos visto antes, pero muy fácil de entender.

Esto es todo en lo referente a como acceder a los argumentos recibidos a través de la línea de comandos. Aquí tenéis un resumen.

Resumen

  • C recibe los argumentos de la línea de comando en dos parámetros de la función main.
  • El parámetro de main argc es el número de parámetros recibidos
  • El parámetro de main argv es una matriz de cadenas de caracteres conteniendo los argumentos que hemos pasado al programa
  • argv[0] normalmente contiene el nombre del programa ejecutado, si bien este comportamiento se puede modificar muy fácilmente
  • La librería C estándar ofrece funciones para procesar la línea de comandos fácilmente. getopt es la alternativa POSIX y argp es la alternativa GNU.

SOBRE Occam's Razor
Somos una revista libre que intenta explicar de forma sencilla conceptos tecnológicos y científicos de los que no podemos escapar. Al final, todo es más fácil de lo que parece!

 
Tu publicidad aquí :)