#include <stdio.h>
#include <stdlib.h>
int
(int argc, char *argv[])
main {
int i;
("%d Parametros...\n", argc);
printf
for (i = 0; i < argc; i++)
("Parámetro %d: %s\n", i , argv[i]);
printf
/* Primer Parametro (0) es el nombre del programa */
if (argc != 2)
{
(stderr, "Solo un parámetro por facor\n");
fprintf (1);
exit }
("Hola %s\n", argv[1]);
printf
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 enmain
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ónmain
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 enargv[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 desdebash
, el propiobash
realiza la llamada aexecve
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 deargv
según las va procesando, de esta forma, al terminar el buclewhile
, 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 deargv
comenzando en el índiceoptind
. Esto es útil, por ejemplo, para procesar nombres de ficheros que queremos pasar a nuestro programa. Pensad por ejemplo en una utilizad comocat
.
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 degetopt
llamadagetopt_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 yargp
es la alternativa GNU.
■