Comment puis-je en toute sécurité et extraire rapidement des chiffres à partir d'un int?
Question
Nous avons actuellement un code pour extraire les chiffres d'un int, mais je dois convertir en une plate-forme sans snprintf, et je suis peur d'un dépassement de mémoire tampon. J'ai commencé à écrire mon propre portable (et optimisé) snprintf mais on m'a dit de demander ici au cas où quelqu'un avait une meilleure idée.
int extract_op(int instruction)
{
char buffer[OP_LEN+1];
snprintf(buffer, sizeof(buffer), "%0*u", OP_LEN, instruction);
return (buffer[1] - 48) * 10 + buffer[0] - 48;
}
Nous utilisons des chaînes C parce que la vitesse est très important.
La solution
Utilisation sprintf
doit être fine. sizeof type * 3 * CHAR_BIT / 8 + 2
est un tampon suffisamment grand pour l'impression d'un nombre entier de Type type
. Vous pouvez simplifier cette expression si vous assumez CHAR_BIT
est 8 ou si vous ne vous préoccupez formats non signés. L'idée de base est que chaque octet contribue au plus 3 chiffres en décimal (ou octal), et vous avez besoin d'espace pour un signe et la terminaison nulle.
Autres conseils
Vous n'avez pas besoin de former instruction
dans un tableau de caractères à cet effet; vous avez juste besoin de garder « les deux chiffres supérieurs », comme suit:
int extract_op(unsigned int instruction)
{
int first = 0;
int second = 0;
while(instruction) {
second = first;
first = instruction % 10;
instruction /= 10;
}
return first + 10 * second;
}
Je pense que l'expression dans le return
est faux, mais il ne reproduit ce que vous faites. Dix fois le secondes chiffres, ainsi que le premier
Je soupçonne que la vitesse pourrait être encore mieux que ce que vous obtenez maintenant, mais c'est à vous mesurer sur votre plate-forme spécifique et compilateur, bien sûr.
Jusqu'à présent, il y a une réponse qui permute les deux derniers chiffres et qui permute les deux premiers ... il me semble que "%0*u", OP_LEN
est de forcer la sortie à une largeur particulière, et l'importance des chiffres extraits est prédéterminée par OP_LEN
.
En supposant OP_LEN
est une macro, nous pouvons obtenir 10 ^ (OP_LEN-2) avec
#define DIVISOR ( (int) ( 1.e ## OP_LEN * 0.01 ) )
Alors, semblable à la réponse de @ zneak,
int extract_op( int instruction )
{
instruction /= DIVISOR;
int tens = (instruction / 10) % 10;
int units = instruction % 10;
return units * 10 + tens;
}
#undef DIVISOR
U peut stocker le chiffre u obtiennent en réseau. Celui-ci était CODE EXPLIQUE PAR ALEX. Ici, je suis d'ajouter certaines variables.
int a[5];
int extract_op(unsigned int instruction)
{
int i=0;
int first = 0;
int second = 0;
while(instruction) {
second = first;
first = instruction % 10;
instruction /= 10;
}
a[i]=first;
}
Ceci est quelque chose fonctionnera pour tous les entiers auront max 5 chiffres. Mais encore, si tu veux prendre un tableau dynamique alors u peut utiliser la liste de liens
devrait fonctionner aussi pour 0 et <0.
int extract_op( int instruction )
{
int numd = 1;
while( instruction /= 10 )
++numd;
return numd;
}