2009-01-31 39 views
27

Así que estoy en Linux y quiero que un programa acepte argumentos cuando lo ejecuta desde la línea de comandos.Pase argumentos al programa C desde la línea de comandos

Por ejemplo,

./myprogram 42 -b -s

Con esto, el programa habría almacenar ese número 42 como un int y ejecutar ciertas partes del código dependiendo de qué argumentos se pone como -b o -s.

+0

El formato canónico para una línea de comando pasa argumentos de opciones como '-b' y '-s' antes que cualquier argumento que no tenga opción, como '42'. Entonces, el formato de línea de comando estándar y ortodoxo sería "./myprogram -b -s 42". Evite desviarse de ese estándar. [... más en el próximo comentario ...] –

+0

Consulte la sección 12 (Convenciones de utilidad) de las Definiciones básicas del estándar POSIX en http://www.opengroup.org/onlinepubs/009695399/toc.htm. –

+1

@Jonathan Leffler: El orden no importa. La función 'getopt_long' hace lo correcto independientemente del orden. Ver mi respuesta – jfs

Respuesta

36

Puede usar getopt.

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

int 
main (int argc, char **argv) 
{ 
    int bflag = 0; 
    int sflag = 0; 
    int index; 
    int c; 

    opterr = 0; 

    while ((c = getopt (argc, argv, "bs")) != -1) 
    switch (c) 
     { 
     case 'b': 
     bflag = 1; 
     break; 
     case 's': 
     sflag = 1; 
     break; 
     case '?': 
     if (isprint (optopt)) 
      fprintf (stderr, "Unknown option `-%c'.\n", optopt); 
     else 
      fprintf (stderr, 
        "Unknown option character `\\x%x'.\n", 
        optopt); 
     return 1; 
     default: 
     abort(); 
     } 

    printf ("bflag = %d, sflag = %d\n", bflag, sflag); 

    for (index = optind; index < argc; index++) 
    printf ("Non-option argument %s\n", argv[index]); 
    return 0; 
} 
+0

He agregado un ejemplo de código. – jfs

+2

¿No debería él o ella entender primero los "argumentos principales que pasan" primero? ;) – OscarRyz

+0

Funciona en Linux porque la función getopt() es GNU getopt() y normalmente no se establece POSIXLY_CORRECT en el entorno, y GNU getopt() luego procesa los argumentos de opción antes de los argumentos 'file', incluso cuando siguen un argumento de archivo como en el ejemplo. En las plataformas POSIX, no funcionará ... –

25

En C, esto se hace usando argumentos pasados ​​a la función main():

int main(int argc, char *argv[]) 
{ 
    int i = 0; 
    for (i = 0; i < argc; i++) { 
     printf("argv[%d] = %s\n", i, argv[i]); 
    } 
    return 0; 
} 

Más información se puede encontrar en línea como este Arguments to main artículo.

+0

Lo siento, no es una x-ref terriblemente buena. Hay un error en la afirmación de que "la declaración del argumento argv suele ser el primer encuentro de un programador novato con punteros a matrices de punteros y puede resultar intimidante" (argv es una matriz de punteros, no un puntero a una serie de punteros). –

+1

Además, la página siguiente muestra un analizador de opciones ad hoc en lugar de utilizar los analizadores getopt() o getopt_long() estándar, lo cual es simplemente un mal consejo. No, no es una buena referencia. –

+2

En C, una referencia a una matriz es una dirección, al igual que un puntero es una dirección. Por lo tanto, se puede hacer referencia a argv como "una matriz" y "un puntero a una matriz". Esta es una de las bellas simplicidades de C, así como uno de los puntos de confusión. –

6

Eche un vistazo a la biblioteca getopt; es casi el estándar de oro para este tipo de cosas.

10

Considere el uso de getopt_long(). Permite opciones cortas y largas en cualquier combinación.

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

/* Flag set by `--verbose'. */ 
static int verbose_flag; 

int 
main (int argc, char *argv[]) 
{ 
    while (1) 
    { 
     static struct option long_options[] = 
    { 
     /* This option set a flag. */ 
     {"verbose", no_argument,  &verbose_flag, 1}, 
     /* These options don't set a flag. 
     We distinguish them by their indices. */ 
     {"blip", no_argument,  0, 'b'}, 
     {"slip", no_argument,  0, 's'}, 
     {0,   0,     0, 0} 
    }; 
     /* getopt_long stores the option index here. */ 
     int option_index = 0; 

     int c = getopt_long (argc, argv, "bs", 
       long_options, &option_index); 

     /* Detect the end of the options. */ 
     if (c == -1) 
    break; 

     switch (c) 
    { 
    case 0: 
     /* If this option set a flag, do nothing else now. */ 
     if (long_options[option_index].flag != 0) 
     break; 
     printf ("option %s", long_options[option_index].name); 
     if (optarg) 
     printf (" with arg %s", optarg); 
     printf ("\n"); 
     break; 
    case 'b': 
     puts ("option -b\n"); 
     break; 
    case 's': 
     puts ("option -s\n"); 
     break; 
    case '?': 
     /* getopt_long already printed an error message. */ 
     break; 

    default: 
     abort(); 
    } 
    } 

    if (verbose_flag) 
    puts ("verbose flag is set"); 

    /* Print any remaining command line arguments (not options). */ 
    if (optind < argc) 
    { 
     printf ("non-option ARGV-elements: "); 
     while (optind < argc) 
    printf ("%s ", argv[optind++]); 
     putchar ('\n'); 
    } 

    return 0; 
} 

relacionadas:

4

En lugar de getopt(), también se puede considerar el uso de argp_parse() (una interfaz alternativa a la misma biblioteca).

De libc manual:

getopt es más estándar (corto opción única versión de la misma es una parte del estándar POSIX), pero utilizando argp_parse es a menudo más fácil, tanto para muy simple y la opción muy compleja estructuras, porque hace más de el trabajo sucio para usted.

Pero siempre estuve contento con el estándar getopt.

N.B. GNU getopt con getopt_long es GNU LGPL.

+0

"getopt es GNU LGPL": Eso depende del getopt. Ha sido implementado varias veces. El de Mac OS X tiene licencia BSD. – dmckee

+0

Y AT & T lanzó uno a mediados de los 80 en el dominio público, o algo muy cercano al dominio público. El punto de D McKee es muy válido: GNU getopt() [y getopt_long()] son ​​LGPL (o, las versiones anteriores son GPL); no todas las versiones de getopt() son GPL o LGPL. –

+0

Acepto sus comentarios y edito mi publicación. Gracias. – sastanin

4

Otros han golpeado éste en la cabeza:

  • los argumentos estándar para main(int argc, char **argv) le dan acceso directo a la línea de comandos (después de haber sido mutilado y tokens por el shell)
  • hay muy instalación estándar para analizar la línea de comandos: getopt() y getopt_long()

pero como se ha visto el código de usarlos es un poco prolijo, y bastante idiomáticas. Yo por lo general empujo fuera de la vista con algo como:

typedef 
struct options_struct { 
    int some_flag; 
    int other_flage; 
    char *use_file; 
} opt_t; 
/* Parses the command line and fills the options structure, 
* returns non-zero on error */ 
int parse_options(opt_t *opts, int argc, char **argv); 

A continuación, a primera hora de principal:

int main(int argc, char **argv){ 
    opt_t opts; 
    if (parse_options(&opts,argc,argv)){ 
     ... 
    } 
    ... 
} 

o puede utilizar una de las soluciones sugeridas en Argument-parsing helpers for C/UNIX.

Cuestiones relacionadas