Comment implémenter les éléments suivants (pseudocode Python) en C ++?
if argv[1].startswith('--foo='):
foo_value = int(argv[1][len('--foo='):])
(Par exemple, si argv[1]
c'est le cas --foo=98
, alors l' foo_value
est 98
.)
Mise à jour: j'hésite à étudier Boost, car je cherche simplement à apporter une toute petite modification à un simple petit outil en ligne de commande (je préfère ne pas avoir à apprendre à me connecter et à utiliser Boost pour un mineur changement).
Réponses:
Utilisez une surcharge
rfind
dont lepos
paramètre est:Qui a besoin d'autre chose? Pure STL!
Beaucoup ont mal interprété cela pour signifier "rechercher en arrière dans toute la chaîne à la recherche du préfixe". Cela donnerait le mauvais résultat (par exemple
string("tititito").rfind("titi")
retourne 2 donc par rapport à contre== 0
retournerait faux) et ce serait inefficace (regarder à travers la chaîne entière au lieu du simple début). Mais il ne le fait pas car il transmet lepos
paramètre as0
, ce qui limite la recherche à une correspondance uniquement à cette position ou plus tôt . Par exemple:la source
find
ne sera nulle que si elletiti
est au début de la chaîne. S'il est trouvé ailleurs, vous obtiendrez une valeur de retour non nulle et, s'il n'est pas trouvé, vous obtiendreznpos
également une valeur non nulle. En supposant que j'ai raison, je préférerais cette réponse car je n'ai pas à apporter de choses non standard (oui, je sais que Boost est partout, je préférerais simplement les bibliothèques C ++ de base pour des choses simples comme celle-ci).titi
, mais la partie conversion est manquante.rfind()
qui ne prend pas depos
paramètre. Si vous utilisez la surcharge qui prend unpos
paramètre, il ne recherchera pas la chaîne entière, seulement cette position et plus tôt. (Tout comme normalfind()
avecpos
paramètre ne regarde que dans cette position ou plus tard.) Donc, si vous passezpos == 0
, comme indiqué dans cette réponse, il ne considérera littéralement que les correspondances à cette position. Cela était déjà expliqué dans la réponse et les commentaires.Vous le feriez comme ceci:
La recherche d'une bibliothèque telle que Boost.ProgramOptions qui le fait pour vous est également une bonne idée.
la source
atoi("123xyz")
retours123
, tandis que Pythonint("123xyz")
lève une exception.atoi
parstrtol
oustrtoll
, ce qui nous permet de détecter les conditions d'erreur dans la valeur d'entrée.rfind
celle qui dépend de l'optimisation pour fonctionner.Juste pour être complet, je mentionnerai la manière C de le faire:
(initialement publié par Yaseen Rauf ici , balisage ajouté)
Pour une comparaison insensible à la casse, utilisez
strnicmp
au lieu destrncmp
.C'est la façon C de le faire, pour les chaînes C ++, vous pouvez utiliser la même fonction comme ceci:
la source
memcmp()
Si vous utilisez déjà Boost, vous pouvez le faire avec des algorithmes de chaîne boost + boost cast lexical:
Ce type d'approche, comme la plupart des autres réponses fournies ici, convient aux tâches très simples, mais à long terme, il est généralement préférable d'utiliser une bibliothèque d'analyse de ligne de commande. Boost en a un ( Boost.Program_options ), ce qui peut avoir du sens si vous utilisez déjà Boost.
Sinon, une recherche de «analyseur de ligne de commande c ++» donnera un certain nombre d'options.
la source
Code que j'utilise moi-même:
la source
substr
conduit à une copie inutile. Lastr.compare(start, count, substr)
méthode utilisée dans la réponse de Thomas est plus efficace. La réponse de razvanco13 a une autre méthode qui évite la copie en utilisantstd::equal
.Thomas uses atoi which is only for windows
Huh?atoi
est une fonction de bibliothèque standard C depuis ... depuis toujours. En effet,atoi
est mauvais- pas parce qu'il est Windows specific- mais parce qu'il est (1) C, pas C ++, et (2) dépréciée même en C (vous devez utiliserstrtol
ou l' une des autres fonctions connexes. Commeatoi
a pas de gestion d'erreur. Mais, encore une fois, ce n'est qu'en C, de toute façon).Personne n'a encore utilisé l' algorithme STL / la fonction de non-concordance . Si cela retourne vrai, prefix est un préfixe de 'toCheck':
Exemple de prog complet:
Éditer:
Comme le suggère @James T. Huggett, std :: equal est mieux adapté à la question: A est-il un préfixe de B? et est un code légèrement plus court:
Exemple de prog complet:
la source
std::equal
de chaînes a l'inconvénient de ne pas détecter la fin de la chaîne, vous devez donc vérifier manuellement si le préfixe est plus court que la chaîne entière. (Comme correctement fait dans l'exemple de prog, mais omis dans le one-liner ci-dessus.)Étant donné que les deux chaînes -
argv[1]
et"--foo"
- sont des chaînes C, @ FelixDombek's answer la meilleure solution.En voyant les autres réponses, cependant, j'ai pensé qu'il valait la peine de noter que, si votre texte est déjà disponible en tant que
std::string
, il existe une solution simple, sans copie et à efficacité maximale qui n'a pas été mentionnée jusqu'à présent:Et si foo est déjà une chaîne:
la source
rfind(x, 0) == 0
devrait vraiment être défini dans la norme asstarts_with
rfind()
(à la place destartswith()
) est très inefficace - il continue de chercher jusqu'à la fin de la chaîne.Avec C ++ 17, vous pouvez utiliser
std::basic_string_view
& avec C ++ 20std::basic_string::starts_with
oustd::basic_string_view::starts_with
.L'avantage de
std::string_view
par rapport àstd::string
- en ce qui concerne la gestion de la mémoire - est qu'il ne détient qu'un pointeur vers une "chaîne" (séquence contiguë d'objets de type char) et connaît sa taille. Exemple sans déplacer / copier les chaînes source juste pour obtenir la valeur entière:la source
std::atoi
c'est très bien. Il lève des exceptions sur une mauvaise entrée (qui est gérée dans ce code). Aviez-vous autre chose en tête?atoi
de<cstdlib>
? La documentation dit "ça ne lève jamais d'exceptions".atoi
au lieu destd::atoi
. Le premier n'est pas sûr à utiliser, tandis que le second est très bien. J'utilise ce dernier dans le code ici.std::atoi
jette en effet une exception, en citant une référence appropriée. Jusqu'à ce que vous le fassiez, je ne vous crois pas, car ce serait très déroutant d'avoir les deux::atoi
et d'std::atoi
agir d'une manière complètement différente.std::atoi
été utilisé à la placestd::stoi
. J'ai corrigé ça.la source
if (one-liner)
En utilisant STL, cela pourrait ressembler à:
la source
if (prefix.size()<=arg.size() && std::equal(...))
.Au risque d'être critiqué pour l'utilisation de constructions C, je pense que cet
sscanf
exemple est plus élégant que la plupart des solutions Boost. Et vous n'avez pas à vous soucier de la liaison si vous exécutez n'importe où qui a un interpréteur Python!Voici un exemple de sortie qui montre que la solution gère les ordures de début / fin aussi correctement que le code Python équivalent, et plus correctement que tout ce qui utilise
atoi
(qui ignorera par erreur un suffixe non numérique).la source
argv[i]
est le cas"--foo=9999999999999999999999999"
, le comportement n'est pas défini (bien que la plupart ou la totalité des implémentations doivent se comporter correctement). Je suppose9999999999999999999999999 > INT_MAX
.J'utilise
std::string::compare
enveloppé dans une méthode utilitaire comme ci-dessous:la source
Pourquoi ne pas utiliser les getopts gnu? Voici un exemple de base (sans contrôles de sécurité):
Pour la commande suivante:
Tu auras
la source
Dans le cas où vous avez besoin de la compatibilité C ++ 11 et ne pouvez pas utiliser boost, voici un drop-in compatible avec boost avec un exemple d'utilisation:
la source
Vous pouvez également utiliser
strstr
:mais je pense que c'est bon uniquement pour les chaînes courtes, car il doit parcourir toute la chaîne lorsque la chaîne ne commence pas réellement par «substr».
la source
Ok pourquoi l'utilisation compliquée des bibliothèques et des trucs? Les objets C ++ String surchargent l'opérateur [], vous pouvez donc simplement comparer les caractères .. Comme ce que je viens de faire, car je veux répertorier tous les fichiers dans un répertoire et ignorer les fichiers invisibles et les .. et. pseudofiles.
C'est si simple..
la source
la source
Avec C ++ 11 ou supérieur, vous pouvez utiliser
find()
etfind_first_of()
Exemple utilisant find pour trouver un seul caractère:
Exemple utilisant find pour trouver une chaîne complète et à partir de la position 5:
Exemple utilisant le
find_first_of()
et uniquement le premier caractère, pour rechercher uniquement au début:Bonne chance!
la source
Depuis C ++ 11
std::regex_search
peut également être utilisé pour fournir des expressions encore plus complexes. L'exemple suivant gère également les nombres flottantsstd::stof
et une conversion ultérieure enint
.Cependant, la
parseInt
méthode illustrée ci-dessous peut lever unestd::invalid_argument
exception si le préfixe n'est pas mis en correspondance; cela peut être facilement adapté en fonction de l'application donnée:Le type de magie du modèle d'expression régulière est bien détaillé dans la réponse suivante .
EDIT: la réponse précédente n'a pas effectué la conversion en entier.
la source
À partir de C ++ 20, vous pouvez utiliser la
starts_with
méthode.la source
Ceci est complètement non testé. Le principe est le même que celui de Python. Nécessite Boost.StringAlgo et Boost.LexicalCast.
Vérifiez si la chaîne commence par l'autre chaîne, puis récupérez la sous-chaîne («tranche») de la première chaîne et convertissez-la à l'aide d'une conversion lexicale.
la source