web-dev-qa-db-fra.com

Analyser les arguments de ligne de commande en C?

J'essaie d'écrire un programme capable de comparer deux fichiers ligne par ligne, Word par Word ou caractère par caractère en C. Il doit être capable de lire les options de ligne de commande -l -w -i or --...

  • si l'option est -l, les fichiers sont comparés ligne par ligne.
  • si l'option est -w, elle compare les fichiers Word à Word.
  • si les options sont - cela suppose automatiquement que l'argument suivant est le premier nom de fichier.
  • si l'option est -i, elle les compare sans tenir compte de la casse.
  • par défaut, les fichiers sont comparés caractère par caractère.

Le nombre de fois où les options sont entrées n'a aucune importance tant que -w et -l ne sont pas saisis en même temps et qu'il n'y a pas plus de 2 fichiers.

Je ne sais même pas par où commencer pour analyser les arguments de la ligne de commande. VEUILLEZ AIDER :(

C'est donc le code que j'ai mis au point pour tout. Je n'ai pas encore vérifié l'erreur, mais je me demandais si j'écrivais des choses de manière trop compliquée.

/*
 * Functions to compare files.
 */
int compare_line();
int compare_Word();
int compare_char();
int case_insens();

/*
 * Program to compare the information in two files and print message saying 
 * whether or not this was successful.
 */
int main(int argc, char* argv[])
{
/*Loop counter*/
  size_t i = 0;

  /*Variables for functions*/
  int caseIns = 0;
  int line = 0;
  int Word = 0;

  /*File pointers*/
  FILE *fp1, *fp2;

  /*
   * Read through command-line arguments for options.
   */
  for (i = 1; i < argc; i++) {
    printf("argv[%u] = %s\n", i, argv[i]);
    if (argv[i][0] == '-') {
       if (argv[i][1] == 'i') 
       {
           caseIns = 1;
       }
       if (argv[i][1] == 'l')
       {
           line = 1;
       }
       if (argv[i][1] == 'w')
       {
           Word = 1;
       }
       if (argv[i][1] == '-')
       {
           fp1 = argv[i][2];
           fp2 = argv[i][3];
       }
       else 
       {
           printf("Invalid option.");
           return 2;
       }
    } else {
       fp1(argv[i]);
       fp2(argv[i][1]);
    }
  }

  /*
   * Check that files can be opened.
   */
  if(((fp1 = fopen(fp1, "rb")) ==  NULL) || ((fp2 = fopen(fp2, "rb")) == NULL))
  {
      perror("fopen()");
      return 3;
  }
  else{
        if (caseIns == 1)
        {
            if(line == 1 && Word == 1)
            {
                printf("That is invalid.");
                return 2;
            }
            if(line == 1 && Word == 0)
            {
                if(compare_line(case_insens(fp1, fp2)) == 0)
                        return 0;
            }
            if(line == 0 && Word == 1)
            {
                if(compare_Word(case_insens(fp1, fp2)) == 0)
                    return 0;
            }
            else
            {
                if(compare_char(case_insens(fp1,fp2)) == 0)
                    return 0;
            }
        }
        else
        {
            if(line == 1 && Word == 1)
            {
                printf("That is invalid.");
                return 2;
            }
            if(line == 1 && Word == 0)
            {
                if(compare_line(fp1, fp2) == 0)
                    return 0;
            }
            if(line == 0 && Word == 1)
            {
                if(compare_Word(fp1, fp2) == 0)
                    return 0;
            }
            else
            {
                if(compare_char(fp1, fp2) == 0)
                    return 0;
            }
        }

  }
    return 1;
    if(((fp1 = fclose(fp1)) == NULL) || (((fp2 = fclose(fp2)) == NULL)))
        {
            perror("fclose()");
            return 3;
        }
        else
        {
            fp1 = fclose(fp1);
            fp2 = fclose(fp2);
        }
}

/*
 * Function to compare two files line-by-line.
 */
int compare_line(FILE *fp1, FILE *fp2)
{
    /*Buffer variables to store the lines in the file*/
    char buff1 [LINESIZE];
    char buff2 [LINESIZE];

    /*Check that neither is the end of file*/
    while((!feof(fp1)) && (!feof(fp2)))
    {
        /*Go through files line by line*/
        fgets(buff1, LINESIZE, fp1);
        fgets(buff2, LINESIZE, fp2);
    }
    /*Compare files line by line*/
    if(strcmp(buff1, buff2) == 0)
    {
        printf("Files are equal.\n");
        return 0;
    }
    printf("Files are not equal.\n");
    return 1;
}   

/*
 * Function to compare two files Word-by-Word.
 */
int compare_Word(FILE *fp1, FILE *fp2)
{
    /*File pointers*/
    FILE *fp1, *fp2;

    /*Arrays to store words*/
    char fp1words[LINESIZE];
    char fp2words[LINESIZE];

    if(strtok(fp1, " ") == NULL || strtok(fp2, " ") == NULL)
    {
        printf("File is empty. Cannot compare.\n");
        return 0;
    }
    else
    {
        fp1words = strtok(fp1, " ");
        fp2words = strtok(fp2, " ");

        if(fp1words == fp2words)
        {
            fputs(fp1words);
            fputs(fp2words);
            printf("Files are equal.\n");
            return 0;
        }
    }
    return 1;
}

/*
 * Function to compare two files character by character.
 */
int compare_char(FILE *fp1,FILE *fp2)
{
    /*Variables to store the characters from both files*/
    int c;
    int d;

    /*Buffer variables to store chars*/
    char buff1 [LINESIZE];
    char buff2 [LINESIZE];

    while(((c = fgetc(fp1))!= EOF) && (((d = fgetc(fp2))!=EOF)))
    {
        if(c == d)
        {
            if((fscanf(fp1, "%c", buff1)) == (fscanf(fp2, "%c", buff2)))
            {
                printf("Files have equivalent characters.\n");
                return 1;
                break;
            }
        }

    }
        return 0;
}

/*
 * Function to compare two files in a case-insensitive manner.
 */
int case_insens(FILE *fp1, FILE *fp2, size_t n)
{
    /*Pointers for files.*/
    FILE *fp1, *fp2;

    /*Variable to go through files.*/
    size_t i = 0;

    /*Arrays to store file information.*/
    char fp1store[LINESIZE];
    char fp2store[LINESIZE];

    while(!feof(fp1) && !feof(fp2))
    {
         for(i = 0; i < n; i++)
         {
                fscanf(fp1, "%s", fp1store);
                fscanf(fp2, "%s", fp2store);

                fp1store = tolower(fp1store);
                fp2store = tolower(fp2store);

                return 1;
         }
    }
    return 0;
}
80
user1251020

À ma connaissance, les trois méthodes les plus courantes d'analyse des arguments de ligne de commande en C sont:

  • Getopt (#include <unistd.h> de la bibliothèque POSIX C), ce qui permet de résoudre l'analyse d'arguments simples tâches. Si vous connaissez un peu bash, basics, getopt est basé sur Getopt à partir de GNU libc.
  • Argp (#include <argp.h> de la GNU C), qui peut résoudre davantage tâches complexes et s'occupe de choses comme, par exemple:
    • -?, --help pour message d'aide, y compris adresse e-mail
    • -V, --version pour informations de version
    • --usage pour message d'usage
  • Faites-le vous-même , ce que je ne recommande pas pour les programmes qui seraient donnés à quelqu'un d'autre, car il y en a trop qui pourraient mal tourner ou être de moins bonne qualité . L'erreur populaire consistant à oublier "-" pour arrêter l'analyse des options en est un exemple.

La documentation de la bibliothèque C de GNU C) contient quelques exemples intéressants pour Getopt et Argp.

Exemple d'utilisation Getopt

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

int main(int argc, char *argv[])
{
    bool isCaseInsensitive = false;
    int opt;
    enum { CHARACTER_MODE, Word_MODE, LINE_MODE } mode = CHARACTER_MODE;

    while ((opt = getopt(argc, argv, "ilw")) != -1) {
        switch (opt) {
        case 'i': isCaseInsensitive = true; break;
        case 'l': mode = LINE_MODE; break;
        case 'w': mode = Word_MODE; break;
        default:
            fprintf(stderr, "Usage: %s [-ilw] [file...]\n", argv[0]);
            exit(EXIT_FAILURE);
        }
    }

    // Now optind (declared extern int by <unistd.h>) is the index of the first non-option argument.
    // If it is >= argc, there were no non-option arguments.

    // ...
}

Exemple d'utilisation Argp

#include <argp.h>
#include <stdbool.h>

const char *argp_program_version = "programname programversion";
const char *argp_program_bug_address = "<[email protected]>";
static char doc[] = "Your program description.";
static char args_doc[] = "[FILENAME]...";
static struct argp_option options[] = { 
    { "line", 'l', 0, 0, "Compare lines instead of characters."},
    { "Word", 'w', 0, 0, "Compare words instead of characters."},
    { "nocase", 'i', 0, 0, "Compare case insensitive instead of case sensitive."},
    { 0 } 
};

struct arguments {
    enum { CHARACTER_MODE, Word_MODE, LINE_MODE } mode;
    bool isCaseInsensitive;
};

static error_t parse_opt(int key, char *arg, struct argp_state *state) {
    struct arguments *arguments = state->input;
    switch (key) {
    case 'l': arguments->mode = LINE_MODE; break;
    case 'w': arguments->mode = Word_MODE; break;
    case 'i': arguments->isCaseInsensitive = true; break;
    case ARGP_KEY_ARG: return 0;
    default: return ARGP_ERR_UNKNOWN;
    }   
    return 0;
}

static struct argp argp = { options, parse_opt, args_doc, doc, 0, 0, 0 };

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

    arguments.mode = CHARACTER_MODE;
    arguments.isCaseInsensitive = false;

    argp_parse(&argp, argc, argv, 0, 0, &arguments);

    // ...
}

Exemple pour Faites-le vous-même

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

int main(int argc, char *argv[])
{   
    bool isCaseInsensitive = false;
    enum { CHARACTER_MODE, Word_MODE, LINE_MODE } mode = CHARACTER_MODE;
    size_t optind;
    for (optind = 1; optind < argc && argv[optind][0] == '-'; optind++) {
        switch (argv[optind][1]) {
        case 'i': isCaseInsensitive = true; break;
        case 'l': mode = LINE_MODE; break;
        case 'w': mode = Word_MODE; break;
        default:
            fprintf(stderr, "Usage: %s [-ilw] [file...]\n", argv[0]);
            exit(EXIT_FAILURE);
        }   
    }   

    // *argv points to the remaining non-option arguments.
    // If *argv is NULL, there were no non-option arguments.

    // ...
}   

Avertissement: je suis nouveau sur Argp, l'exemple peut contenir des erreurs.

153
Christian Hujer

Utilisez getopt() , ou peut-être getopt_long() .

int iflag = 0;
enum { Word_MODE, LINE_MODE } op_mode = Word_MODE;  // Default set
int opt;

while ((opt = getopt(argc, argv, "ilw") != -1)
{
    switch (opt)
    {
    case 'i':
        iflag = 1;
        break;
    case 'l':
        op_mode = LINE_MODE;
        break;
    case 'w':
        op_mode = Word_MODE;
        break;
    default:
        fprintf(stderr, "Usage: %s [-ilw] [file ...]\n", argv[0]);
        exit(EXIT_FAILURE);
    }
}

/* Process file names or stdin */
if (optind >= argc)
    process(stdin, "(standard input)", op_mode);
else
{
    int i;
    for (i = optind; i < argc; i++)
    {
        FILE *fp = fopen(argv[i], "r");
        if (fp == 0)
            fprintf(stderr, "%s: failed to open %s (%d %s)\n",
                    argv[0], argv[i], errno, strerror(errno));
        else
        {
            process(fp, argv[i], op_mode);
            fclose(fp);
        }
    }
 }

Notez que vous devez déterminer les en-têtes à inclure (je lui donne 4 qui sont nécessaires), et la façon dont j'ai écrit le type op_mode Signifie que vous avez un problème dans la fonction process() - vous ne peut pas accéder à l'énumération là-bas. Il est préférable de déplacer l'énumération en dehors de la fonction; vous pourriez même faire de op_mode une variable de portée de fichier sans lien externe (une manière élégante de dire static) pour éviter de la transmettre à la fonction. Ce code ne gère pas - Comme synonyme pour une entrée standard, un autre exercice pour le lecteur. Notez que getopt() prend automatiquement soin de -- Pour marquer la fin des options pour vous.

Je n'ai exécuté aucune version du typage ci-dessus après un compilateur; il pourrait y avoir des erreurs.


Pour un crédit supplémentaire, écrivez une fonction (bibliothèque):

int filter(int argc, char **argv, int idx, int (*function)(FILE *fp, const char *fn));

qui encapsule la logique de traitement des options de nom de fichier après la boucle getopt(). Il devrait gérer - Comme entrée standard. Notez que cela indiquerait que op_mode Devrait être une variable de portée de fichier statique. La fonction filter() prend argc, argv, optind et un pointeur sur la fonction de traitement. Il doit renvoyer 0 (EXIT_SUCCESS) s'il est capable d'ouvrir tous les fichiers et tous les appels de la fonction signalés par 0, sinon 1 (ou EXIT_FAILURE). Avoir une telle fonction simplifie l’écriture de programmes "filtres" de style Unix qui lisent les fichiers spécifiés sur la ligne de commande ou l’entrée standard.

16
Jonathan Leffler

J'ai trouvé Gengetopt très utile - vous spécifiez les options souhaitées avec un simple fichier de configuration, qui génère une paire .c/.h que vous incluez simplement et que vous liez à votre application. Le code généré utilise getopt_long, semble gérer les types de paramètres de ligne de commande les plus courants et permet de gagner beaucoup de temps.

Un fichier d'entrée gengetopt pourrait ressembler à ceci:

version "0.1"
package "myApp"
purpose "Does something useful."

# Options
option "filename" f "Input filename" string required
option "verbose" v "Increase program verbosity" flag off
option "id" i "Data ID" int required
option "value" r "Data value" multiple(1-) int optional 

Générer le code est facile et crache cmdline.h et cmdline.c:

$ gengetopt --input=myApp.cmdline --include-getopt

Le code généré est facilement intégré:

#include <stdio.h>
#include "cmdline.h"

int main(int argc, char ** argv) {
  struct gengetopt_args_info ai;
  if (cmdline_parser(argc, argv, &ai) != 0) {
    exit(1);
  }
  printf("ai.filename_arg: %s\n", ai.filename_arg);
  printf("ai.verbose_flag: %d\n", ai.verbose_flag);
  printf("ai.id_arg: %d\n", ai.id_arg);
  int i;
  for (i = 0; i < ai.value_given; ++i) {
    printf("ai.value_arg[%d]: %d\n", i, ai.value_arg[i]);
  }
}

Si vous devez effectuer une vérification supplémentaire (par exemple, vous assurer que les indicateurs sont mutuellement exclusifs), vous pouvez le faire assez facilement avec les données stockées dans le fichier gengetopt_args_info struct.

9
davidA

Je suis très surpris que personne n'ait évoqué le paquet "opt" de James Theiler.

Vous pouvez trouver opt sur http://public.lanl.gov/jt/Software/

et un post flatteur avec quelques exemples de la façon dont c'est tellement plus simple que d'autres approches est ici:

http://www.decompile.com/not_invented_here/opt/

5
markgalassi

Docopt a une implémentation en C que j’ai trouvée assez agréable: https://github.com/docopt/docopt.c

À partir d'un format standard de page de manuel décrivant les options de ligne de commande, docopt déduit et crée un analyseur d'arguments. Cela a commencé en python; la version de python ne fait qu'analyser la docstring et renvoie un dict. Pour ce faire, le travail en C demande un peu plus de travail, mais son utilisation est claire et il n'y a pas de dépendances externes.

3
gvoysey

Il existe une excellente bibliothèque C polyvalente libUCW qui inclut soignée analyse des options en ligne de commande et chargement du fichier de configuration .

La bibliothèque est également fournie avec une bonne documentation et inclut quelques autres éléments utiles (E/S rapides, structures de données, allocateurs, ...), mais ceux-ci peuvent être utilisés séparément.

Exemple d'analyseur d'options libUCW (à partir des documents de la bibliothèque)

#include <ucw/lib.h>
#include <ucw/opt.h>

int english;
int sugar;
int verbose;
char *tea_name;

static struct opt_section options = {
  OPT_ITEMS {
    OPT_HELP("A simple tea boiling console."),
    OPT_HELP("Usage: teapot [options] name-of-the-tea"),
    OPT_HELP(""),
    OPT_HELP("Options:"),
    OPT_HELP_OPTION,
    OPT_BOOL('e', "english-style", english, 0, "\tEnglish style (with milk)"),
    OPT_INT('s', "sugar", sugar, OPT_REQUIRED_VALUE, "<spoons>\tAmount of sugar (in teaspoons)"),
    OPT_INC('v', "verbose", verbose, 0, "\tVerbose (the more -v, the more verbose)"),
    OPT_STRING(OPT_POSITIONAL(1), NULL, tea_name, OPT_REQUIRED, ""),
    OPT_END
  }
};

int main(int argc, char **argv)
{
  opt_parse(&options, argv+1);
  return 0;
}
2
Tomáš Gavenčiak

J'ai écrit une petite bibliothèque qui analyse des arguments similaires à POpt, avec lesquels j'ai eu plusieurs problèmes, appelés XOpt . Utilise l'analyse des arguments de style GNU et a une interface très similaire à POpt.

Je l'utilise de temps en temps avec beaucoup de succès et cela fonctionne à peu près n'importe où.

1
Qix

Modèle d'instruction pour l'analyse des arguments de ligne de commande en C.

C:> nom_programme -w - fileOne.txt fichierTwo.txt

BOOL argLine = FALSE;
BOOL argWord = FALSE;
BOOL argChar = FALSE;
char * fileName1 = NULL;
char * fileName2 = NULL;

int main(int argc, char * argv[]) {
    int i;
    printf("Argument count=%d\n",argc);
    for (i = 0; i < argc; i++) {
        printf("Argument %s\n",argv[i]);
        if (strcmp(argv[i],"-l")==0) {
            argLine = TRUE;
            printf("    argLine=TRUE\n");
        }
        else if (strcmp(argv[i],"-w")==0) {
            argWord = TRUE;
            printf("    argWord=TRUE\n");
        }
        else if (strcmp(argv[i],"-c")==0) {
            argChar = TRUE;
            printf("    argChar=TRUE\n");
        }
        else if (strcmp(argv[i],"--")==0) {
            if (i+1 <= argc) {
                fileName1 = argv[++i];
                printf("    fileName1=%s\n",fileName1);
            }
            if (i+1 <= argc) {
                fileName2 = argv[++i];
                printf("    fileName2=%s\n",fileName2);
            }
        }
    }
    return 0;
}
0
Java42
    /*
      Here's a rough one not relying on any libraries.
      Example:
      -wi | -iw //Word case insensitive
      -li | -il //line case insensitive
      -- file  //specify the first filename (you could just get the files
      as positional arguments in the else statement instead)
      PS: don't mind the #define's, they're just pasting code :D
    */
    #ifndef OPT_H
    #define OPT_H

    //specify option requires argument
    #define require \
      optarg = opt_pointer + 1; \
      if (*optarg == '\0') \
      { \
        if (++optind == argc) \
          goto opt_err_arg; \
        else \
          optarg = argv[optind]; \
      } \
      opt_pointer = opt_null_terminator;

    //start processing argv
    #define opt \
    int   optind                 = 1; \
    char *opt_pointer            = argv[1]; \
    char *optarg                 = NULL; \
    char  opt_null_terminator[2] = {'\0','\0'}; \
    if (0) \
    { \
      opt_err_arg: \
        fprintf(stderr,"option %c requires argument.\n",*opt_pointer); \
        return 1; \
      opt_err_opt: \
        fprintf(stderr,"option %c is invalid.\n",*opt_pointer); \
        return 1; \
    } \
    for (; optind < argc; opt_pointer = argv[++optind]) \
      if (*opt_pointer++ == '-') \
      { \
        for (;;++opt_pointer) \
          switch (*opt_pointer) \
          {

    //stop processing argv
    #define done \
          default: \
            if (*opt_pointer != '\0') \
              goto opt_err_opt; \
            else \
              goto opt_next; \
            break; \
          } \
        opt_next:; \
      }
    #endif //opt.h

    #include <stdio.h>
    #include "opt.h"
    int
    main (int argc, char **argv)
    {
      #define by_character 0
      #define by_Word      1
      #define by_line      2
      int cmp = by_character;
      int case_insensitive = 0;
      opt
      case 'h':
        puts ("HELP!");
        break;
      case 'v':
        puts ("fileCMP Version 1.0");
        break;
      case 'i':
        case_insensitive = 1;
        break;
      case 'w':
        cmp = by_Word;
        break;
      case 'l':
        cmp = by_line;
        break;
      case '-':required
        printf("first filename: %s\n", optarg);
        break;
      done
      else printf ("Positional Argument %s\n", argv[optind]);
      return 0;
    }
0
Anonymous
#include <stdio.h>

int main(int argc, char **argv)
{
    size_t i;
    size_t filename_i = -1;

    for (i = 0; i < argc; i++)
    {
        char const *option =  argv[i];
        if (option[0] == '-')
        {
            printf("I am a flagged option");
            switch (option[1])
            {
                case 'a':
                    /*someting*/
                    break;
                case 'b':
                    break;
                case '-':
                    /* "--" -- the next argument will be a file.*/
                    filename_i = i;
                    i = i + 1;
                    break;
                default:
                    printf("flag not recognised %s", option);
                    break;
            }
        }
        else
        {   
            printf("I am a positional argument");
        }

        /* At this point, if -- was specified, then filename_i contains the index
         into argv that contains the filename. If -- was not specified, then filename_i will be -1*/
     }
  return 0;
}
0
Pod

Si je peux me permettre, je voudrais aussi suggérer de jeter un coup d'œil à une bibliothèque d'analyse syntaxique d'options que j'ai écrite: dropt .

  • C'est une bibliothèque C (avec un wrapper C++ si vous le souhaitez).
  • C'est léger.
  • Il est extensible (les types d'arguments personnalisés peuvent être facilement ajoutés et ont la même valeur avec les types d'arguments intégrés).
  • Il devrait être très portable (c'est écrit en C standard) sans aucune dépendance (autre que la bibliothèque standard C).
  • Il a une licence très restrictive (zlib/libpng).

Une fonctionnalité proposée par beaucoup d'autres n'est pas la possibilité de remplacer les options précédentes. Par exemple, si vous avez un alias Shell:

alias bar="foo --flag1 --flag2 --flag3"

et vous voulez utiliser bar mais avec--flag1 désactivé, il vous permet de faire:

bar --flag1=0
0
jamesdlin

D'accord, c'est le début de l'histoire longue - fait court 'bort en analysant une ligne de commande en C ...

/**
* Helper function to parse the command line
* @param argc Argument Counter
* @param argv Argument Vector
* @param prog Program Instance Reference to fill with options
*/
bool parseCommandLine(int argc, char* argv[], DuplicateFileHardLinker* prog) {
  bool pathAdded = false;

  // iterate over all arguments...
  for ( int i = 1; i<argc; i++ ) {

    // is argv a command line option ?
    if ( argv[i][0] == '-' || argv[i][0] == '/' ) {

// ~~~~~~ Optionally Cut that part vvvvvvvvvvvvv for sake of simplicity ~~~~~~~
      // check for longer options
            if ( stricmp( &argv[i][1], "NoFileName"  ) == 0
              ||  strcmp( &argv[i][1], "q1"          ) == 0 ) {

        boNoFileNameLog = true;
      } else if ( strcmp( &argv[i][1], "HowAreYou?"    ) == 0 ) {
          logInfo( "SECRET FOUND: Well - wow I'm glad ya ask me.");
      } else {

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Now here comes the main thing:
//
        // check for one char options
        while ( char option = *++argv[i] ) {

          switch ( option ) {
          case '?':
            // Show program usage

            logInfo(L"Options:");
            logInfo(L"  /q\t>Quite mode");
            logInfo(L"  /v\t>Verbose mode");
            logInfo(L"  /d\t>Debug mode");
            return false;

            // Log options
          case 'q':
            setLogLevel(LOG_ERROR);
            break;

          case 'v':
            setLogLevel(LOG_VERBOSE);
            break;

          case 'd':
            setLogLevel(LOG_DEBUG);
            break;

          default:
            logError(L"'%s' is an illegal command line option!"
                      "  Use /? to see valid options!", option);
            return false;
          } // switch one-char-option
        } //while one-char-options
      }  //else one vs longer options
    } // if isArgAnOption

// 
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^  So that's it! ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// What follows now is are some usefull extras...
//
    else {


      // the command line options seems to be a path...
      WCHAR tmpPath[MAX_PATH_LENGTH];
      mbstowcs(tmpPath, argv[i], sizeof(tmpPath));

      // check if the path is existing!
      //...

      prog->addPath(tmpPath); //Comment or remove to get a working example
      pathAdded = true;
    }
  }

  // check for parameters
  if ( !pathAdded ) {
    logError("You need to specify at least one folder to process!\n"
             "Use /? to see valid options!");
    return false;
  }

  return true;
}



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

  try {
    // parse the command line
    if ( !parseCommandLine(argc, argv, prog) ) {
      return 1; 
    }

// I know that sample is just to show how the nicely parse commandline Arguments
// So Please excuse more Nice useful C-glatter that follows now...
  }
  catch ( LPCWSTR err ) {
    DWORD dwError = GetLastError();
    if ( wcslen(err) > 0 ) {
      if ( dwError != 0 ) {
        logError(dwError, err);
      }
      else {
        logError(err);
      }
    }
    return 2;
  }
}

#define LOG_ERROR               1
#define LOG_INFO                0
#define LOG_VERBOSE             -1
#define LOG_DEBUG               -2

/** Logging Level for the console output */
int logLevel = LOG_INFO;

void logError(LPCWSTR message, ...) {
  va_list argp;
  fwprintf(stderr, L"ERROR: ");
  va_start(argp, message);
  vfwprintf(stderr, message, argp);
  va_end(argp);
  fwprintf(stderr, L"\n");
}


void logInfo(LPCWSTR message, ...) {
  if ( logLevel <= LOG_INFO ) {
    va_list argp;
    va_start(argp, message);
    vwprintf(message, argp);
    va_end(argp);
    wprintf(L"\n");
  }
}

Notez que cette version supportera également la combinaison des arguments: Ainsi, au lieu d’écrire / h/s -> / hs fonctionnera également.

Désolé d'être la nième personne à avoir posté ici - mais je n'étais pas vraiment satisfait de toutes les versions autonomes que j'ai vues ici. Eh bien, les libéraux ont quitté Nice. Donc, je préférerais libUCW analyseur d'options, Arg ou Getopt à ceux faits maison.

Notez que vous pouvez changer:

*++argv[i] -> (++argv*)[0] plus moins crypté mais toujours crypté.

Okay, décomposons-le: 1. argv [i] -> accéder au i-ème élément du champ pointeur argv-char

  1. ++ * ... -> fera suivre le pointeur argv d'un caractère

  2. ... [0] -> suivra le pointeur lu le caractère

  3. ++ (...) -> crochet existe, nous allons donc augmenter le pointeur et non la valeur de caractère elle-même.

Si gentil qu'en C ## les pointeurs 'sont morts' - vive les pointeurs !!!

0
Nadu