Permettez-moi de dire que c'est - bien que cela semble intelligent - un hack vraiment, vraiment stupide. Si quelqu'un vous recommande cela en 2019, frappez-le. Frappez-le aussi fort que vous le pouvez.
Vous pouvez, bien sûr, le faire dans votre propre logiciel que vous et personne d'autre n'utilise si vous savez que vous n'utiliserez jamais d'autre langue que l'anglais de toute façon. Sinon, pas question.
On peut dire que le piratage était "correct" il y a 30 ou 35 ans, lorsque les ordinateurs ne faisaient pas grand-chose d'autre que de l'anglais en ASCII. peut-être une ou deux grandes langues européennes. Mais... ce n'est plus le cas.
Le hack fonctionne parce que les majuscules et minuscules US-Latin sont exactement 0x20
l'un de l'autre et apparaissent dans le même ordre, ce qui n'est qu'une petite différence. Qui, en fait, ce bit hack, bascule.
Les personnes qui ont créé les pages de code pour l'Europe occidentale, et plus tard le consortium Unicode, ont été assez intelligentes pour conserver ce schéma pour les trémas allemands et les voyelles à accent français. Ce n'est pas le cas pour le ß qui (jusqu'à ce que quelqu'un convainque le consortium Unicode en 2017, et qu'un grand magazine de presse écrite Fake News écrive à ce sujet, convainquant en fait le Duden - pas de commentaire à ce sujet). n'existent même pas comme un versal (se transforme en SS). Maintenant, il fait existent en tant que versal, mais les deux sont 0x1DBF
positions séparées, pas 0x20
.
Les exécutants, eux, l'étaient, no assez prévenants pour continuer à le faire. Par exemple, si vous appliquez votre hack dans certaines langues d'Europe de l'Est ou autres (je ne connais pas le cyrillique), vous aurez une mauvaise surprise. Tous ces caractères "hatchet" en sont des exemples, les minuscules et les majuscules sont à part. Le hack fait donc no fonctionnent correctement à cet endroit.
Il y a bien d'autres choses à prendre en compte, par exemple, certains caractères ne passent pas simplement des minuscules aux majuscules (ils sont remplacés par des séquences différentes), ou ils peuvent changer de forme (nécessitant des points de code différents).
Ne pensez même pas à ce que ce piratage fera à des choses comme le thaï ou le chinois (cela vous donnera juste un non-sens total).
L'économie de quelques centaines de cycles CPU était peut-être très intéressante il y a 30 ans, mais de nos jours, il n'y a vraiment aucune excuse pour convertir correctement une chaîne de caractères. Il existe des fonctions de bibliothèque pour effectuer cette tâche non triviale.
Le temps nécessaire pour convertir plusieurs dizaines de kilo-octets de texte correctement est négligeable de nos jours.
5 votes
fr.wikipedia.org/wiki/File:USASCII_code_chart.png Conseil : vous pouvez convertir
@
en ` en utilisant^ 32
.112 votes
Pour information, cela ne "fonctionne" pas vraiment. Il fonctionne pour ce jeu de caractères particulier, mais il y a d'autres jeux pour lesquels il ne fonctionne pas.
toupper
ytolower
pour changer d'affaire.7 votes
Parfois, avec les concours en ligne, "l'idée" est d'écrire du code d'une manière tellement obscure qu'il ne passerait jamais un examen sérieux ;)
21 votes
^= transforme la valeur en utilisant XOR. Les lettres majuscules ASCII ont un zéro dans le bit correspondant, tandis que les lettres minuscules ont un un. Cela dit, ne le faites pas ! Utilisez les routines de caractères (unicode) appropriées pour convertir les minuscules en majuscules. L'ère du simple ASCII est révolue depuis longtemps.
0 votes
Ce que @NathanOliver a dit. C'est mignon mais ça va causer un bug.
14 votes
Ce n'est pas seulement qu'il ne fonctionne qu'avec certains jeux de caractères. Même si nous supposons que le monde entier est en UTF-8 (ce qui pourrait au moins être un objectif utopique), il ne fonctionne qu'avec les 26 lettres suivantes
A
aZ
. C'est très bien tant que vous ne vous intéressez qu'à l'anglais (et que vous n'utilisez pas les orthographes "naïf", des mots comme "café", ou des noms avec des diacritiques...), mais le monde ne se résume pas à l'anglais.0 votes
Related : vous pouvez vérifier pour un caractère alphabétique ASCII en forçant la minuscule avec
|= 0x20
et ensuite vérifier (non signé)if(c - 'a' < ('a'-'z'))
. Donc seulement 3 opérations : OU + SOUS + CMP. Voir aussi Convertir une chaîne en C++ en majuscule (toupie de chaîne SIMD masquant l'opérande pour XOR) et Comment accéder à un tableau de caractères et transformer les minuscules en majuscules, et vice versa ? (C avec SIMD intrinsèque, et x86 scalaire asm case-flip pour les caractères alphabétiques, laissant les autres non modifiés).3 votes
Même si [très hypothétiquement] cela était moins fragile et a fait fonctionne avec plus de jeux de caractères, etc., je déconseille toujours de l'utiliser. Il existe des moyens standard de faire cela, alors essayez de tirer parti des outils qui existent déjà. Inventer votre propre façon "intelligente" de le faire est un excellent moyen de se retrouver avec un code illisible/non maintenable qui est vraiment difficile à déboguer lorsque vous finissez par trouver le cas qui casse votre implémentation. (Ce n'est qu'un commentaire général et non une attaque contre le PO, qui n'a vraiment demandé que pourquoi cela fonctionne)
3 votes
Je ne peux pas dire à partir de la question si vous savez ce que le
^
y^=
Les opérateurs ne le font pas en premier lieu, mais c'est pertinent pour bien répondre à votre question. Le faites-vous ?0 votes
Soit dit en passant, le XOR/OR etc. est une méthode très courante pour changer de cas en EBCDIC. Je n'essaierais pas de le faire avec DBCS ou Unicode. La transformation en int pour l'arithmétique est largement tombée en désuétude pour de nombreuses bonnes raisons.
0 votes
Pour faire suite au commentaire de @NathanOliver - les choses qui semblent fonctionner pour un sous-ensemble de choses, mais qui n'affirment pas qu'elles ne fonctionnent que pour ce sous-ensemble, sont une invitation à créer un bug dans le futur ... et vous ne le saurez jamais. Si vous ne voulez pas utiliser std::toupper/tolower (parce que votre plateforme ne propose pas la bibliothèque std), vous devriez au moins affirmer que vous regardez [a-zA-Z].
0 votes
@NathanOliver : TBH
toupper
ytolower
sont désespérément cassés dans n'importe quel encodage multi-octet, tel que le très rare UTF-8. C'était peut-être une solution dans les années 80, mais aujourd'hui je dirais que c'est probablement encore pire que^32
.2 votes
Duplicata possible de Comment s[i]^=32 convertit-il les majuscules en minuscules ?
0 votes
J'ai toujours connu cette astuce comme
^= ' '
1 votes
Le "truc" que j'ai utilisé était
^= 'A' ^ 'a'
quandtoupper()
n'était pas disponible et nécessitait un code serré.0 votes
Cela fonctionne uniquement pour la table ASCII standard où il y a une distance de 32 entre les alphabets majuscules et les alphabets minuscules. Elle ne prend pas en compte la locale ou la table ASCII étendue. Dans la table de base, vous pouvez l'utiliser pour passer de e à E ou vice-versa. Mais dans la locale fr_FR, toutes les variations de e devraient correspondre à E lorsqu'elles sont capitalisées, mais en fr_CA, les accents restent. Cela signifie que UpperCase("eéèëê") ==> "EEEEE" en fr_FR ==> "EÉÈËÊ" en fr_CA.