Comment convertir un paramètre de programme de argv
à int64_t
? atoi()
ne convient que pour les entiers 32 bits.
Une tentative conforme à C99.
[edit] employé @R. correction
// Note: Typical values of SCNd64 include "lld" and "ld".
#include <inttypes.h>
#include <stdio.h>
int64_t S64(const char *s) {
int64_t i;
char c ;
int scanned = sscanf(s, "%" SCNd64 "%c", &i, &c);
if (scanned == 1) return i;
if (scanned > 1) {
// TBD about extra data found
return i;
}
// TBD failed to scan;
return 0;
}
int main(int argc, char *argv[]) {
if (argc > 1) {
int64_t i = S64(argv[1]);
printf("%" SCNd64 "\n", i);
}
return 0;
}
Il y a plusieurs façons de le faire:
strtoll(str, NULL, 10);
Ceci est conforme à POSIX C99.
vous pouvez également utiliser strtoimax; qui a le prototype suivant:
strtoimax(const char *str, char **endptr, int base);
C'est bien parce que cela fonctionnera toujours avec l'intmax_t local ... C'est C99 et vous devez inclure <inttypes.h>
Faire ce portable à 100% est un peu délicat. long long
doit avoir au moins 64 bits, mais ne doit pas nécessairement être un complément de deux. Il ne sera donc peut-être pas en mesure de représenter -0x7fffffffffffffff-1
. Par conséquent, l'utilisation de strtoll
pourrait avoir un casse d'angle cassée. Le même problème s'applique à strtoimax
. Ce que vous pouvez faire à la place est de consommer de l’espace de début (si vous voulez autoriser l’espacement) et de rechercher d’abord le signe, puis d’utiliser strtoull
ou strtoumax
, l’un ou l’autre étant requis pour la prise en charge de valeurs allant jusqu’à la plage entière de int64_t
. Vous pouvez ensuite appliquer le signe:
unsigned long long x = strtoull(s, 0, 0);
if (x > INT64_MAX || ...) goto error;
int64_t y = negative ? -(x-1)-1 : x;
Cette logique est écrite pour éviter tous les cas de débordement.
strtoll
le convertit en un long long
qui est généralement un int de 64 bits.
Cela a fonctionné pour moi avec un autre type int64, et j'aime bien le style propre C++:
std::istringstream iss(argv[i]);
int64_t i64;
iss >> i64;
Vous pouvez obtenir une erreur de compilation: operartor << ... n'est pas défini.
Et je ne sais pas ce qui se passe si argv [i] contient "HALLO".
Les utilisateurs issus d'une recherche sur le Web doivent également considérer std::stoll
.
Il ne répond pas strictement à cette question initiale de manière efficace pour un const char*
mais de nombreux utilisateurs auront un std::string
de toute façon. Si vous ne vous souciez pas de l'efficacité, vous devriez obtenir une conversion implicite (basée sur la conversion définie par l'utilisateur à l'aide du constructeur à un seul argument std::string
) en std::string
même si vous avez un const char*
.
C'est plus simple que std::strtoll
qui nécessitera toujours 3 arguments.
Il devrait jeter si l’entrée n’est pas un nombre, mais voir ces commentaires .