web-dev-qa-db-fra.com

comment prendre des entiers comme arguments de ligne de commande?

J'ai lu un exemple de getopt () mais cela ne montre pas comment accepter les entiers comme options d'argument, comme cvalue serait dans le code de l'exemple:

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

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

   opterr = 0;

   while ((c = getopt (argc, argv, "abc:")) != -1)
     switch (c)
       {
       case 'a':
         aflag = 1;
         break;
       case 'b':
         bflag = 1;
         break;
       case 'c':
         cvalue = optarg;
         break;
       case '?':
         if (optopt == 'c')
           fprintf (stderr, "Option -%c requires an argument.\n", optopt);
         else 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 ("aflag = %d, bflag = %d, cvalue = %s\n",
           aflag, bflag, cvalue);

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

Si j’exécutais ce qui précède comme testop -c foo, cvalue serait foo, mais que se passerait-il si je voulais testop -c 42? Puisque cvalue est de type char *, pourrais-je simplement transtyper optarg pour être (int)? J'ai essayé de le faire sans utiliser getopt(), ni accéder directement à argv[whatever], ni le convertir en tant qu'entier, mais je finis toujours avec un grand nombre négatif lors de l'impression avec %d. Je suppose que je ne suis pas en train de déréférencer argv[] correctement ou quelque chose comme ça, je ne suis pas sûr ...

17
Andrew

Vous devez utiliser atoi() pour convertir une chaîne en entier.

36
Vlad H

Toutes les réponses ci-dessus sont globalement correctes (Vikram.exe obtient des accessoires pour expliquer pourquoi vous devez appeler une fonction de bibliothèque, ce que personne d'autre n'a pris la peine de faire). Cependant, personne n'a appelé la fonction de bibliothèque correct à appeler. Ne pas utiliser atoi. Ne pas utiliser sscanf

Utilisez strtol , ou son parent strtoul si vous ne souhaitez pas autoriser les nombres négatifs. Seules ces fonctions vous donnent suffisamment d’informations lorsque l’entrée était pas un nombre. Par exemple, si l'utilisateur tape

./a.out 123cheesesandwich

atoi et sscanf renverront joyeusement 123, ce qui n'est certainement pas ce que vous voulez. Seule strtol vous dira (via la endptr) qu'elle n'a traité que les premiers caractères de la chaîne.

(Il n'y a pas strtoi, mais il y a strtod si vous devez lire un nombre à virgule flottante.)

16
zwol

Comme vous l'avez déjà utilisé dans votre code, le prototype de la fonction main est

int main (int argc, char** argv)

Quels que soient les arguments fournis en tant qu'arguments de ligne de commande, ils sont transmis à votre 'programme' sous la forme d'un tableau de caractères char * (ou simplement de chaînes). donc, si vous appelez un prog sous la forme foo.exe 123, le premier argument de foo.exe sera une chaîne 123 et non une valeur entière de 123.

Si vous essayez de transformer l'argument en entier (comme vous l'avez dit) en utilisant probablement quelque chose comme: (int) argv[1], vous n'obtiendrez pas la valeur entière du premier argument, mais une adresse mémoire où le premier argument est stocké dans votre espace adresse. . Pour obtenir une valeur entière, vous devez convertir explicitement la valeur de chaîne en valeur entière. Pour cela, vous pouvez utiliser la fonction atoi. Consultez la page de manuel THIS pour connaître les fonctions similaires pouvant être utilisées pour la conversion.

10
Vikram.exe

Utilisez atoi.

cvalue = atoi( optarg );

Et déclarer cvalue en tant que int.

4
Mark Loeser

atoi(), ce qui signifie ascii en entier est la fonction à utiliser. De même, atof() peut être utilisé pour obtenir des valeurs flottantes.

4
Sulla

Dans cette situation, j'irais pour un sscanf().

1
stefan

Non, vous ne pouvez pas simplement convertir pour le convertir en une valeur entière. Vous devez le transformer en utilisant sscanf, atoi, atol ou une fonction similaire.

0
Pablo Santa Cruz