2010-09-09 4 views
0

J'essaie d'utiliser la fonction getopt_long() pour la première fois seulement J'ai des problèmes avec les arguments qui ne sont pas des drapeaux. Par exemple, dans mon code quand un argument inconnu est donné, je veux l'utiliser comme un fichier d'entrée. Quand je cours ceci avec seulement un nom de fichier il n'est pas imprimé, si j'utilise d'abord un drapeau, n'importe quel drapeau, alors je peux l'imprimer.getopt_long() et les paramètres qui ne sont pas des drapeaux?

Comment puis-je résoudre ce problème?

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

static struct option long_options[] = { 
    {"help", no_argument,  0, 'h'}, 
    {"input", required_argument, 0, 'i'}, 
    {"output", required_argument, 0, 'o'}, 
    {"algorithm", required_argument, 0, 'a'}, 
    {0, 0, 0, 0} 
}; 

int main(int argc, char *argv[]) { 
    int c; 
    int option_index = 0; 

    while(42) { 
    c = getopt_long(argc, argv, "hi:o:a:", long_options, 
    &option_index); 
    if(c == -1) 
    break; 

    switch(c) { 
    case 'h': /* --help */ 
    printf("--help flag\n"); 
    break; 
    case 'i': /* --input */ 
    printf("--input flag\n"); 
    break; 
    case 'o': /* --output */ 
    printf("--output flag\n"); 
    break; 
    case 'a': /* --algorithm */ 
    printf("--algorithm flag \n"); 
    break; 
    default: /* ??? */ 
    fprintf(stderr, "Invalid option"); 
    return 1; 
    } 

    if(optind < argc) { 
    printf("other arguments: "); 

    while(optind < argc) { 
    printf ("%s ", argv[optind]); 
    optind++; 
    } 

    printf("\n"); 
    } 
    } 

    return 0; 
} 

Répondre

5

La boucle ne doit contenir que le commutateur. Traiter les arguments résiduels dans une boucle séparée (non imbriquée):

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

static struct option long_options[] = 
{ 
    {"help", no_argument,  0, 'h'}, 
    {"input", required_argument, 0, 'i'}, 
    {"output", required_argument, 0, 'o'}, 
    {"algorithm", required_argument, 0, 'a'}, 
    {0, 0, 0, 0} 
}; 

int main(int argc, char *argv[]) 
{ 
    int opt; 
    int option_index = 0; 
    int i; 

    while ((opt = getopt_long(argc, argv, "hi:o:a:", long_options, &option_index)) != -1) 
    { 
     switch(opt) 
     { 
      case 'h': /* --help */ 
       printf("--help flag\n"); 
       break; 
      case 'i': /* --input */ 
       printf("--input flag (%s)\n", optarg); 
       break; 
      case 'o': /* --output */ 
       printf("--output flag (%s)\n", optarg); 
       break; 
      case 'a': /* --algorithm */ 
       printf("--algorithm flag (%s)\n", optarg); 
       break; 
      default: /* ??? */ 
       fprintf(stderr, "Invalid option %c\n", opt); 
       return 1; 
     } 
    } 

    for (i = optind; i < argc; i++) 
     printf("Process: %s\n", argv[i]); 

    return 0; 
} 

Il est un moyen d'avoir GNU getopt() et getopt_long() retour arguments de nom de fichier comme si elles étaient des options avec la « lettre »^A « \ 1 » ; utiliser '-' comme premier caractère de la chaîne d'options courtes, et intercepter '\1' dans le commutateur; la valeur de optarg est le nom du fichier.

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

static struct option long_options[] = 
{ 
    {"help", no_argument,  0, 'h'}, 
    {"input", required_argument, 0, 'i'}, 
    {"output", required_argument, 0, 'o'}, 
    {"algorithm", required_argument, 0, 'a'}, 
    {0, 0, 0, 0} 
}; 

int main(int argc, char *argv[]) 
{ 
    int opt; 
    int option_index = 0; 
    int i; 

    while ((opt = getopt_long(argc, argv, "-hi:o:a:", long_options, &option_index)) != -1) 
    { 
     switch(opt) 
     { 
      case 'h': /* --help */ 
       printf("--help flag\n"); 
       break; 
      case 'i': /* --input */ 
       printf("--input flag (%s)\n", optarg); 
       break; 
      case 'o': /* --output */ 
       printf("--output flag (%s)\n", optarg); 
       break; 
      case 'a': /* --algorithm */ 
       printf("--algorithm flag (%s)\n", optarg); 
       break; 
      case '\1': 
       printf("File: %s\n", optarg); 
       break; 
      default: /* ??? */ 
       fprintf(stderr, "Invalid option %c\n", opt); 
       return 1; 
     } 
    } 

    for (i = optind; i < argc; i++) 
     printf("Process: %s\n", argv[i]); 

    return 0; 
} 

Cependant, vous avez besoin de la boucle après la boucle de traitement des arguments dans le cas où vos types d'utilisateurs acariâtre:

program -- abc def 

Le « -- » termine la boucle while() sans traiter les arguments de nom de fichier.

3

Cela ne fonctionne pas parce que vous sortez de la boucle externe while lorsque getopt_long renvoie -1 (ce qui indique qu'il n'y a plus d'options). Vous devez déplacer le bloc if (optind < argc) de la boucle externe while; ça ne lui appartient pas de toute façon. Cela pourrait être plus clair si vous avez écrit cette boucle externe while comme:

while ((c = getopt_long(...)) != -1) 
{ 
    switch (c) 
    { 
     /* Deal with flags. */ 
    } 
} 
Questions connexes