web-dev-qa-db-fra.com

Analyse la chaîne dans argv/argc

Existe-t-il un moyen en C d’analyser un texte et d’obtenir des valeurs pour argv et argc, comme si le texte avait été transmis à une application sur la ligne de commande? 

Cela ne doit pas forcément fonctionner sous Windows, mais uniquement sous Linux - je ne me soucie pas non plus de citer des arguments.

27
codebox

Si la solution Glib est excessive pour votre cas, vous pouvez envisager de la coder vous-même.

Ensuite vous pouvez:

  • scannez la chaîne et comptez le nombre d'arguments (et vous obtenez votre argument)
  • allouer un tableau de char * (pour votre argv)
  • analysez à nouveau la chaîne, attribuez les pointeurs dans le tableau alloué et remplacez les espaces par '\ 0' (si vous ne pouvez pas modifier la chaîne contenant les arguments, vous devez la dupliquer).
  • n'oubliez pas de libérer ce que vous avez alloué!

Le diagramme ci-dessous devrait clarifier (espérons-le):

             aa bbb ccc "dd d" ee         <- original string

             aa0bbb0ccc00dd d00ee0        <- transformed string
             |  |   |    |     |
   argv[0] __/  /   /    /     /
   argv[1] ____/   /    /     /
   argv[2] _______/    /     /
   argv[3] ___________/     /
   argv[4] ________________/ 

Une API possible pourrait être:

    char **parseargs(char *arguments, int *argc);
    void   freeparsedargs(char **argv);

Vous aurez besoin de considérations supplémentaires pour mettre en œuvre freeparsedargs () en toute sécurité.

Si votre chaîne est très longue et que vous ne voulez pas balayer deux fois, vous pouvez envisager des alternatives, telles que l'allocation de davantage d'éléments pour les tableaux argv (et la réaffectation si nécessaire).

EDIT: Solution proposée (ne pas gérer l'argument cité).

    #include <stdio.h>

    static int setargs(char *args, char **argv)
    {
       int count = 0;

       while (isspace(*args)) ++args;
       while (*args) {
         if (argv) argv[count] = args;
         while (*args && !isspace(*args)) ++args;
         if (argv && *args) *args++ = '\0';
         while (isspace(*args)) ++args;
         count++;
       }
       return count;
    }

    char **parsedargs(char *args, int *argc)
    {
       char **argv = NULL;
       int    argn = 0;

       if (args && *args
        && (args = strdup(args))
        && (argn = setargs(args,NULL))
        && (argv = malloc((argn+1) * sizeof(char *)))) {
          *argv++ = args;
          argn = setargs(args,argv);
       }

       if (args && !argv) free(args);

       *argc = argn;
       return argv;
    }

    void freeparsedargs(char **argv)
    {
      if (argv) {
        free(argv[-1]);
        free(argv-1);
      } 
    }

    int main(int argc, char *argv[])
    {
      int i;
      char **av;
      int ac;
      char *as = NULL;

      if (argc > 1) as = argv[1];

      av = parsedargs(as,&ac);
      printf("== %d\n",ac);
      for (i = 0; i < ac; i++)
        printf("[%s]\n",av[i]);

      freeparsedargs(av);
      exit(0);
    }
10
Remo.D

Je suis surpris que personne n'ait fourni la réponse la plus simple en utilisant les fonctionnalités POSIX standard:

http://www.opengroup.org/onlinepubs/9699919799/functions/wordexp.html

26
R..

Voici ma contribution. C'est sympa et court, mais il faut se méfier:

  • L'utilisation de strtok modifie la chaîne "commandLine" d'origine en remplaçant les espaces par\0 délimiteurs de fin de chaîne
  • argv [] finit par pointer sur "commandLine", donc ne le modifiez pas avant d'avoir fini avec argv [].

Le code:

enum { kMaxArgs = 64 };
int argc = 0;
char *argv[kMaxArgs];

char *p2 = strtok(commandLine, " ");
while (p2 && argc < kMaxArgs-1)
  {
    argv[argc++] = p2;
    p2 = strtok(0, " ");
  }
argv[argc] = 0;

Vous pouvez maintenant utiliser argc et argv, ou les transmettre à d'autres fonctions déclarées comme "foo (int argc, char ** argv)".

15
sstteevvee

Le toujours-merveilleux glib a g_Shell_parse_args() qui sonne comme ce que vous êtes après.

Si vous ne souhaitez même pas citer, cela pourrait être exagéré. Tout ce que vous avez à faire est de créer une marque, en utilisant un espace comme caractère de marque. Écrire une routine simple pour faire cela ne devrait pas prendre longtemps, vraiment.

Si vous n'êtes pas très avare de mémoire, le faire en un seul passage sans réaffectation devrait être facile; Supposons simplement que chaque deuxième caractère représente un espace, dans le cas le plus défavorable, supposant ainsi qu'une chaîne de caractères n contient au plus __ arguments (n + 1) / 2 et (bien entendu) au plus n octets de texte d'argument (à l'exclusion des terminateurs).

9
unwind

Voici une solution pour Windows et Unix (testée sur Linux, OSX et Windows). Testé avec Valgrind et Dr. Memory .

Il utilise wordexp pour les systèmes POSIX et CommandLineToArgvW pour Windows.

Notez que pour la solution Windows, la plupart du code est converti entre char ** et wchar_t ** avec la belle API Win32, car il n’existe pas de variable CommandLineToArgvA (version ANSI).

#ifdef _WIN32
#include <windows.h>
#else
#include <wordexp.h>
#endif

char **split_commandline(const char *cmdline, int *argc)
{
    int i;
    char **argv = NULL;
    assert(argc);

    if (!cmdline)
    {
        return NULL;
    }

    // Posix.
    #ifndef _WIN32
    {
        wordexp_t p;

        // Note! This expands Shell variables.
        if (wordexp(cmdline, &p, 0))
        {
            return NULL;
        }

        *argc = p.we_wordc;

        if (!(argv = calloc(*argc, sizeof(char *))))
        {
            goto fail;
        }

        for (i = 0; i < p.we_wordc; i++)
        {
            if (!(argv[i] = strdup(p.we_wordv[i])))
            {
                goto fail;
            }
        }

        wordfree(&p);

        return argv;
    fail:
        wordfree(&p);
    }
    #else // WIN32
    {
        wchar_t **wargs = NULL;
        size_t needed = 0;
        wchar_t *cmdlinew = NULL;
        size_t len = strlen(cmdline) + 1;

        if (!(cmdlinew = calloc(len, sizeof(wchar_t))))
            goto fail;

        if (!MultiByteToWideChar(CP_ACP, 0, cmdline, -1, cmdlinew, len))
            goto fail;

        if (!(wargs = CommandLineToArgvW(cmdlinew, argc)))
            goto fail;

        if (!(argv = calloc(*argc, sizeof(char *))))
            goto fail;

        // Convert from wchar_t * to ANSI char *
        for (i = 0; i < *argc; i++)
        {
            // Get the size needed for the target buffer.
            // CP_ACP = Ansi Codepage.
            needed = WideCharToMultiByte(CP_ACP, 0, wargs[i], -1,
                                        NULL, 0, NULL, NULL);

            if (!(argv[i] = malloc(needed)))
                goto fail;

            // Do the conversion.
            needed = WideCharToMultiByte(CP_ACP, 0, wargs[i], -1,
                                        argv[i], needed, NULL, NULL);
        }

        if (wargs) LocalFree(wargs);
        if (cmdlinew) free(cmdlinew);
        return argv;

    fail:
        if (wargs) LocalFree(wargs);
        if (cmdlinew) free(cmdlinew);
    }
    #endif // WIN32

    if (argv)
    {
        for (i = 0; i < *argc; i++)
        {
            if (argv[i])
            {
                free(argv[i]);
            }
        }

        free(argv);
    }

    return NULL;
}
6
Joakim

Je viens de faire cela pour un projet intégré en langage C où j'ai un petit CLI qui analyse l'entrée du port série et exécute un ensemble limité de commandes avec les paramètres.

Ce n’est probablement pas le mieux, mais il est aussi petit et efficace que possible:

int makeargs(char *args, int *argc, char ***aa) {
    char *buf = strdup(args);
    int c = 1;
    char *delim;
    char **argv = calloc(c, sizeof (char *));

    argv[0] = buf;

    while (delim = strchr(argv[c - 1], ' ')) {
        argv = realloc(argv, (c + 1) * sizeof (char *));
        argv[c] = delim + 1;
        *delim = 0x00;
        c++;
    }

    *argc = c;
    *aa = argv;

    return c;
}

tester:

int main(void) {
    char **myargs;
    int argc;

    int numargs = makeargs("Hello world, this is a test", &argc, &myargs);
    while (numargs) {
        printf("%s\r\n", myargs[argc - numargs--]);
    };

    return (EXIT_SUCCESS);
}
3
Andi

LIBTINYC de Matt Peitrek a un module appelé argcargv.cpp qui prend une chaîne et l'analyse dans le tableau d'arguments en prenant en compte les arguments cités. Notez que cela est spécifique à Windows, mais que c'est assez simple et qu'il devrait donc être facile de passer à la plate-forme de votre choix.

2
Michael Burr

J'ai fini par écrire une fonction pour le faire moi-même, je ne pense pas que ce soit très bien, mais cela fonctionne pour mon propos - n'hésitez pas à suggérer des améliorations pour ceux qui en ont besoin à l'avenir:

void parseCommandLine(char* cmdLineTxt, char*** argv, int* argc){
    int count = 1;

    char *cmdLineCopy = strdupa(cmdLineTxt);
    char* match = strtok(cmdLineCopy, " ");
 // First, count the number of arguments
    while(match != NULL){
        count++;
        match = strtok(NULL, " ");
    }

    *argv = malloc(sizeof(char*) * (count+1));
    (*argv)[count] = 0;
    **argv = strdup("test"); // The program name would normally go in here

    if (count > 1){
        int i=1;
        cmdLineCopy = strdupa(cmdLineTxt);
        match = strtok(cmdLineCopy, " ");
        do{
            (*argv)[i++] = strdup(match);
            match = strtok(NULL, " ");
        } while(match != NULL);
     }

    *argc = count;
}
2
codebox

Celui-ci que j'ai écrit considère également les guillemets

N'hésitez pas à contribuer.

/*
Tokenize string considering also quotes.
By Zibri <zibri AT zibri DOT org>
https://github.com/Zibri/tokenize
*/

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

int main(int argc, char *argv[])
{
  char *str1, *token;
  int j;
  char *qstart = NULL;
  bool quoted = false;

  if (argc != 2) {
    fprintf(stderr, "Usage: %s string\n", argv[0]);
    exit(EXIT_FAILURE);
  }

  for (j = 1, str1 = argv[1];; j++, str1 = NULL) {
    token = strtok(str1, " ");
    if (token == NULL)
      break;
    if ((token[0] == 0x27) || (token[0] == 0x22)) {
      qstart = token + 1;
      quoted = true;
    }
    if ((token[strlen(token) - 1] == 0x27) || (token[strlen(token) - 1] == 0x22)) {
      quoted = false;
      token[strlen(token) - 1] = 0;
      printf("%d: %s\n", j, qstart);
    } else {
      if (quoted) {
        token[strlen(token)] = 0x20;
        j--;
      } else
        printf("%d: %s\n", j, token);
    }
  }

  if (quoted) {
    fprintf(stderr, "String quoting error\n");
    return EXIT_FAILURE;
  } else
    return EXIT_SUCCESS;
}

Exemple de sortie:

$ ./tokenize "1 2 3 '4 5 6' 7 8 \"test abc\" 10 11"
1: 1
2: 2
3: 3
4: 4 5 6
5: 7
6: 8
7: test abc
8: 10
9: 11
1
Zibri

Solution pour ceux qui ne veulent pas utiliser l'allocation de mémoire dynamique (par exemple, intégrée)

J'ai écrit tokenise_to_argc_argv() pour un projet incorporé, qui utilise strtok_r() comme base pour la création d'une chaîne de commande sous la forme argc et argv. Contrairement à la plupart des réponses ici, j'alloue généralement de la mémoire de manière statique. Ainsi, mon implémentation suppose que vous avez une limite supérieure de argv_length. Pour la plupart des applications intégrées classiques, cela est largement suffisant. J'ai inclus un exemple de code ci-dessous pour que vous puissiez l'utiliser rapidement.

int tokenise_to_argc_argv(
        char     *buffer,     ///< In/Out : Modifiable String Buffer To Tokenise
        int      *argc,       ///< Out    : Argument Count
        char     *argv[],     ///< Out    : Argument String Vector Array
        const int argv_length ///< In     : Maximum Count For `*argv[]`
      )
{ /* Tokenise string buffer into argc and argv format (req: string.h) */
  int i = 0;
  for (i = 0 ; i < argv_length ; i++)
  { /* Fill argv via strtok_r() */
    if ( NULL == (argv[i] = strtok_r( NULL , " ", &buffer)) ) break;
  }
  *argc = i;
  return i; // Argument Count
}

Remarque:

  • Le tampon de caractères fourni doit être modifiable (strtok_r () insère \0 dans le tampon pour délimiter les jetons de chaîne).
  • dans cette fonction, strtok_r utilise actuellement le caractère " " espace comme seul séparateur. Ceci émule le comportement main(int argc, char *argv[]) dans les interfaces de ligne de commande typiques.
  • Cette fonction n'utilise ni malloc ni calloc, mais vous devrez allouer le tableau argv séparément et fournir explicitement la longueur de argv. C’est parce que j’ai l’intention de l’utiliser dans des appareils embarqués et que je préférerais donc l’allouer manuellement.
  • strtok_r() est utilisé parce qu'il est threadsafe (étant donné que strtok() utilise un pointeur statique interne). En outre, il fait partie de la bibliothèque standard C string.h est donc très portable.

Vous trouverez ci-dessous le code de démonstration ainsi que sa sortie. De plus, cela montre que tokenise_to_argc_argv () peut gérer la plupart des cas de chaîne et a donc été testé. De plus, cette fonction ne repose pas sur malloc ou calloc et convient donc à une utilisation intégrée (après utilisation de types stdint.h).


Code de démonstration

/*******************************************************************************
  Tokenise String Buffer To Argc and Argv Style Format
  Brian Khuu 2017
*******************************************************************************/
#include <stdio.h>  // printf()
#include <ctype.h>  // isprint()
#include <string.h> // strtok_r()

/**-----------------------------------------------------------------------------
  @brief Tokenise a string buffer into argc and argv format

  Tokenise string buffer to argc and argv form via strtok_r()
  Warning: Using strtok_r will modify the string buffer

  Returns: Number of tokens extracted

------------------------------------------------------------------------------*/
int tokenise_to_argc_argv(
        char     *buffer,     ///< In/Out : Modifiable String Buffer To Tokenise
        int      *argc,       ///< Out    : Argument Count
        char     *argv[],     ///< Out    : Argument String Vector Array
        const int argv_length ///< In     : Maximum Count For `*argv[]`
      )
{ /* Tokenise string buffer into argc and argv format (req: string.h) */
  int i = 0;
  for (i = 0 ; i < argv_length ; i++)
  { /* Fill argv via strtok_r() */
    if ( NULL == (argv[i] = strtok_r( NULL, " ", &buffer)) ) break;
  }
  *argc = i;
  return i; // Argument Count
}

/*******************************************************************************
  Demonstration of tokenise_to_argc_argv()
*******************************************************************************/

static void print_buffer(char *buffer, int size);
static void print_argc_argv(int argc, char *argv[]);
static void demonstrate_tokenise_to_argc_argv(char buffer[], int buffer_size);

int main(void)
{ /* This shows various string examples */
  printf("# `tokenise_to_argc_argv()` Examples\n");
  { printf("## Case0: Normal\n");
    char  buffer[] = "tokenising example";
    demonstrate_tokenise_to_argc_argv(buffer, sizeof(buffer));
  }
  { printf("## Case1: Empty String\n");
    char  buffer[] = "";
    demonstrate_tokenise_to_argc_argv(buffer, sizeof(buffer));
  }
  { printf("## Case2: Extra Space\n");
    char  buffer[] = "extra  space here";
    demonstrate_tokenise_to_argc_argv(buffer, sizeof(buffer));
  }
  { printf("## Case3: One Word String\n");
    char  buffer[] = "one-Word";
    demonstrate_tokenise_to_argc_argv(buffer, sizeof(buffer));
  }
}

static void demonstrate_tokenise_to_argc_argv(char buffer[], int buffer_size)
{ /* This demonstrates usage of tokenise_to_argc_argv */
  int   argc     = 0;
  char *argv[10] = {0};

  printf("* **Initial State**\n");
  print_buffer(buffer, buffer_size);

  /* Tokenise Command Buffer */
  tokenise_to_argc_argv(buffer, &argc, argv, sizeof(argv));

  printf("* **After Tokenizing**\n");
  print_buffer(buffer, buffer_size);
  print_argc_argv(argc,argv);
  printf("\n\n");
}

static void print_buffer(char *buffer, int size)
{
  printf(" - Buffer Content `");
  for (int i = 0 ; i < size; i++) printf("%c",isprint(buffer[i])?buffer[i]:'0');
  printf("` | HEX: ");
  for (int i = 0 ; i < size; i++) printf("%02X ", buffer[i]);
  printf("\n");
}

static void print_argc_argv(int argc, char *argv[])
{ /* This displays the content of argc and argv */
  printf("* **Argv content** (argc = %d): %s\n", argc, argc ? "":"Argv Is Empty");
  for (int i = 0 ; i < argc ; i++) printf(" - `argv[%d]` = `%s`\n", i, argv[i]);
}

Sortie

tokenise_to_argc_argv() Exemples

Cas 0: normal

  • Etat initial
    • Contenu de la mémoire tampon tokenising example0 | HEX: 74 6F 6B 65 6E 69 73 69 6E 67 20 65 78 61 6D 70 6C 65 00 
  • Après la création de jetons
    • Contenu de la mémoire tampon tokenising0example0 | HEX: 74 6F 6B 65 6E 69 73 69 6E 67 00 65 65 61 61 6 D 70 6 C 65 00 
  • Contenu argv (argc = 2):
    • argv[0] = tokenising
    • argv[1] = example

Cas 1: chaîne vide

  • Etat initial
    • Contenu de la mémoire tampon 0 | HEX: 00 
  • Après la création de jetons
    • Contenu de la mémoire tampon 0 | HEX: 00 
  • Argv content (argc = 0): Argv est vide

Cas 2: espace supplémentaire

  • Etat initial
    • Contenu de la mémoire tampon extra space here0 | HEX: 65 78 74 72 61 20 20 73 70 61 63 65 20 68 65 72 65 00 
  • Après la création de jetons
    • Contenu de la mémoire tampon extra0 space0here0 | HEX: 65 78 74 72 61 00 20 73 70 61 63 65 00 68 65 72 65 00 
  • Contenu argv (argc = 3):
    • argv[0] = extra
    • argv[1] = space
    • argv[2] = here

Case3: une chaîne de mots

  • Etat initial
    • Contenu de la mémoire tampon one-Word0 | HEX: 6F 6E 65 2D 77 6F 72 64 00 
  • Après la création de jetons
    • Contenu de la mémoire tampon one-Word0 | HEX: 6F 6E 65 2D 77 6F 72 64 00 
  • Contenu argv (argc = 1):
    • argv[0] = one-Word

String.h ou strtok_r () manquants dans votre chaîne d'outils?

Si pour une raison quelconque votre chaîne d’outils n’a pas strtok_r (). Vous pouvez utiliser cette version simplifiée de strtok_r () . Il s'agit d'une version modifiée de l'implémentation GNU C de strtok_r (), mais simplifiée pour ne prendre en charge que les caractères d'espace.

Pour l'utiliser, placez-le simplement au-dessus de tokenise_to_argc_argv(), puis remplacez strtok_r( NULL, " ", &buffer) Par strtok_space(&buffer)

/**-----------------------------------------------------------------------------
  @brief Simplied space deliminated only version of strtok_r()

  - save_ptr : In/Out pointer to a string. This pointer is incremented by this
                function to find and mark the token boundry via a `\0` marker.
                It is also used by this function to find mutiple other tokens
                via repeated calls.

  Returns:
    - NULL  : No token found
    - pointer to start of a discovered token

------------------------------------------------------------------------------*/
char * strtok_space(char **save_ptr)
{ /* strtok_space is slightly modified from GNU C Library `strtok_r()`  implementation. 
      Thus this function is also licenced as GNU Lesser General Public License*/
  char *start = *save_ptr;
  char *end = 0;

  if (*start == '\0') {
    *save_ptr = start;
    return NULL;
  }

  /* Scan leading delimiters.  */
  while(*start == ' ') start++;
  if (*start == '\0') {
    *save_ptr = start;
    return NULL;
  }

  /* Find the end of the token.  */
  end = start;
  while((*end != '\0') && (*end != ' ')) end++;
  if (*end == '\0') {
    *save_ptr = end;
    return start;
  }

  /* Terminate the token and make *SAVE_PTR point past it.  */
  *end = '\0';
  *save_ptr = end + 1;
  return start;
}
1
Brian

Considérons encore une autre implémentation. Courir .

#include <cctype>  // <ctype.h>  for isspace()

/** 
 * Parse out the next non-space Word from a string.
 * @note No nullptr protection
 * @param str  [IN]   Pointer to pointer to the string. Nested pointer to string will be changed.
 * @param Word [OUT]  Pointer to pointer of next Word. To be filled.
 * @return  pointer to string - current cursor. Check it for '\0' to stop calling this function   
 */
static char* splitArgv(char **str, char **Word)
{
    constexpr char QUOTE = '\'';
    bool inquotes = false;

    // optimization
    if( **str == 0 )
        return NULL;

    // Skip leading spaces.
    while (**str && isspace(**str)) 
        (*str)++;

    if( **str == '\0')
        return NULL;

    // Phrase in quotes is one arg
    if( **str == QUOTE ){
        (*str)++;
        inquotes = true;
    }

    // Set phrase begining
    *Word = *str;

    // Skip all chars if in quotes
    if( inquotes ){
        while( **str && **str!=QUOTE )
            (*str)++;
        //if( **str!= QUOTE )
    }else{
        // Skip non-space characters.
        while( **str && !isspace(**str) )
            (*str)++;
    }
    // Null terminate the phrase and set `str` pointer to next symbol
    if(**str)
        *(*str)++ = '\0';

    return *str;
}


/// To support standart convetion last `argv[argc]` will be set to `NULL`
///\param[IN]  str : Input string. Will be changed - splitted to substrings
///\param[IN]  argc_MAX : Maximum a rgc, in other words size of input array \p argv
///\param[OUT] argc : Number of arguments to be filled
///\param[OUT] argv : Array of c-string pointers to be filled. All of these strings are substrings of \p str
///\return Pointer to the rest of string. Check if for '\0' and know if there is still something to parse. \
///        If result !='\0' then \p argc_MAX is too small to parse all. 
char* parseStrToArgcArgvInsitu( char *str, const int argc_MAX, int *argc, char* argv[] )
{
    *argc = 0;
    while( *argc<argc_MAX-1  &&  splitArgv(&str, &argv[*argc]) ){
        ++(*argc);
        if( *str == '\0' )
            break;
    }
    argv[*argc] = nullptr;
    return str;
};

Code d'utilisation

#include <iostream>
using namespace std;

void parseAndPrintOneString(char *input)
{
    constexpr size_t argc_MAX = 5;
    char* v[argc_MAX] = {0};
    int c=0;

    char* rest = parseStrToArgcArgvInsitu(input,argc_MAX,&c,v);
    if( *rest!='\0' )  // or more clear `strlen(rest)==0` but not efficient
        cout<<"There is still something to parse. argc_MAX is too small."<<endl;

    cout << "argc : "<< c << endl;
    for( int i=0; i<c; i++ )
        cout<<"argv["<<i<<"] : "<<v[i] <<endl;
    /*//or condition is `v[i]`
    for( int i=0; v[i]; i++ )
        cout<<"argv["<<i<<"] : "<<v[i] <<endl;*/
}



int main(int argc, char* argv[])
{
    char inputs[][500] ={
              "Just another TEST\r\n"
            , "  Hello my world 'in quotes' \t !"
            , "./hi 'Less is more'"
            , "Very long line with \"double quotes\" should be parsed several times if argv[] buffer is small"
            , "   \t\f \r\n"
    };

    for( int i=0; i<5; ++i ){
        cout<<"Parsing line \""<<inputs[i]<<"\":"<<endl;
        parseAndPrintOneString(inputs[i]);
        cout<<endl;
    }
}

Sortie:

Parsing line "Just another TEST\r\n":
argc : 3
argv[0] : Just
argv[1] : another
argv[2] : TEST

Parsing line "  Hello my world 'in quotes'   !":
There is still something to parse. argc_MAX is too small.
argc : 4
argv[0] : Hello
argv[1] : my
argv[2] : world
argv[3] : in quotes

Parsing line "./hi 'Less is more'":
argc : 2
argv[0] : ./hi
argv[1] : Less is more

Parsing line "Very long line with "double quotes" should be parsed several times if argv[] buffer is small":
There is still something to parse. argc_MAX is too small.
argc : 4
argv[0] : Very
argv[1] : long
argv[2] : line
argv[3] : with

Parsing line "       

":
argc : 0
0
kyb

Malheureusement, C++, mais pour les autres qui pourraient rechercher ce type de bibliothèque, je recommande:

ParamContainer - Analyseur de paramètres en ligne de commande facile à utiliser

Vraiment petit et très facile.

p.addParam("long-name", 'n', ParamContainer::regular, 
           "parameter description", "default_value");  

nom du programme - long-nom = valeur

cout << p["long-name"];
>> value

Selon mon expérience:

  • très utile et simple
  • stable sur la production
  • bien testé (par moi)
0
bua