web-dev-qa-db-fra.com

Comment convertir un argument de ligne de commande en int?

Je dois obtenir un argument et le convertir en int. Voici mon code jusqu'à présent:

#include <iostream>


using namespace std;
int main(int argc,int argvx[]) {
    int i=1;
    int answer = 23;
    int temp;

    // decode arguments
    if(argc < 2) {
        printf("You must provide at least one argument\n");
        exit(0);
    }

    // Convert it to an int here

}
44
nosedive25

Puisque cette réponse a été acceptée et apparaîtra donc en haut, bien que ce ne soit pas la meilleure, je l'ai améliorée en fonction des autres réponses et des commentaires.

La voie C; le plus simple, mais traitera n'importe quel nombre invalide comme 0:

#include <cstdlib>

int x = atoi(argv[1]);

La voie C avec contrôle de saisie:

#include <cstdlib>

errno = 0;
char *endptr;
long int x = strtol(argv[1], &endptr, 10);
if (endptr == argv[1]) {
  std::cerr << "Invalid number: " << argv[1] << '\n';
} else if (*endptr) {
  std::cerr << "Trailing characters after number: " << argv[1] << '\n';
} else if (errno == ERANGE) {
  std::cerr << "Number out of range: " << argv[1] << '\n';
}

La manière i ++ de C++ avec la vérification des entrées:

#include <sstream>

std::istringstream ss(argv[1]);
int x;
if (!(ss >> x)) {
  std::cerr << "Invalid number: " << argv[1] << '\n';
} else if (!ss.eof()) {
  std::cerr << "Trailing characters after number: " << argv[1] << '\n';
}

Manière alternative C++ depuis C++ 11:

#include <stdexcept>
#include <string>

std::string arg = argv[1];
try {
  std::size_t pos;
  int x = std::stoi(arg, &pos);
  if (pos < arg.size()) {
    std::cerr << "Trailing characters after number: " << arg << '\n';
  }
} catch (std::invalid_argument const &ex) {
  std::cerr << "Invalid number: " << arg << '\n';
} catch (std::out_of_range const &ex) {
  std::cerr << "Number out of range: " << arg << '\n';
}

Les quatre variantes supposent que argc >= 2. Tous acceptent les grands espaces; Cochez isspace(argv[1][0]) si vous ne le souhaitez pas. Tous sauf atoi rejettent les espaces finaux.

75
Thomas

Notez que vos arguments main ne sont pas corrects. Le formulaire standard devrait être:

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

ou équivalent:

int main(int argc, char **argv)

Il y a plusieurs façons de réaliser la conversion. C'est une approche:

#include <sstream>

int main(int argc, char *argv[])
{
    if (argc >= 2)
    {
        std::istringstream iss( argv[1] );
        int val;

        if (iss >> val)
        {
            // Conversion successful
        }
    }

    return 0;
}
21
CB Bailey

std :: stoi from string pourrait également être utilisé.

    #include <string>

    using namespace std;

    int main (int argc, char** argv)
    {
         if (argc >= 2)
         {
             int val = stoi(argv[1]);
             // ...    
         }
         return 0;
    }
5
HelloWorld

Comme WhirlWind l’a fait remarquer, les recommandations d’utiliser atoi ne sont pas vraiment très bonnes. atoi n'a aucun moyen d'indiquer une erreur, vous obtenez donc le même retour depuis atoi("0"); que vous le faites avec atoi("abc");. Le premier est clairement significatif, mais le second est une erreur évidente.

Il a également recommandé strtol, ce qui est parfaitement correct, même s’il est un peu maladroit. Une autre possibilité serait d'utiliser sscanf, quelque chose comme: 

if (1==sscanf(argv[1], "%d", &temp))
    // successful conversion
else
    // couldn't convert input

notez que strtol donne cependant des résultats légèrement plus détaillés - en particulier, si vous avez un argument tel que 123abc, l'appel sscanf dira simplement qu'il a converti un nombre (123), alors que strtol vous transmettrait non seulement le nombre , mais aussi un pointeur sur la a (c’est-à-dire le début de la partie qu’elle pourrait pas convertir en nombre).

Puisque vous utilisez C++, vous pouvez également envisager d'utiliser boost::lexical_cast. Ceci est presque aussi simple à utiliser que atoi, mais fournit également (à peu près) le même niveau de détail dans les erreurs de rapport que strtol. La dépense la plus importante est qu'elle puisse générer des exceptions. Par conséquent, pour l'utiliser, votre code doit être protégé contre les exceptions. Si vous écrivez en C++, vous devriez le faire quand même, mais cela force le problème.

3
Jerry Coffin

L'approche avec istringstream peut être améliorée afin de vérifier qu'aucun autre caractère n'a été inséré après l'argument attendu:

#include <sstream>

int main(int argc, char *argv[])
{
    if (argc >= 2)
    {
        std::istringstream iss( argv[1] );
        int val;

        if ((iss >> val) && iss.eof()) // Check eofbit
        {
            // Conversion successful
        }
    }

    return 0;
}
1
andrey

Regardez strtol () si vous utilisez la bibliothèque standard C.

1
WhirlWind

Comme ça on peut faire ....

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

    int a, b, c;
    *// Converting string type to integer type
    // using function "atoi( argument)"* 

    a = atoi(argv[1]);     
    b = atoi(argv[2]);
    c = atoi(argv[3]);

 }
0
Ramanand Yadav