Je peux imprimer avec printf comme un nombre hexadécimal ou octal. Existe-t-il une balise de format à imprimer en tant que base binaire ou arbitraire?
J'utilise gcc.
printf("%d %x %o\n", 10, 10, 10); //prints "10 A 12\n"
print("%b\n", 10); // prints "%b\n"
Réponses:
Hacky mais fonctionne pour moi:
Pour les types multi-octets
Vous avez malheureusement besoin de toutes les citations supplémentaires. Cette approche présente les risques d'efficacité des macros (ne passez pas de fonction comme argument
BYTE_TO_BINARY
), mais évite les problèmes de mémoire et les invocations multiples de strcat dans certaines des autres propositions ici.la source
printf
lequel ceux avec desstatic
tampons ne peuvent pas.%d
en%c
, car il devrait être encore plus rapide (%d
doit effectuer une conversion digit-> char, tout en%c
int
le système est 32 bits, l'impression d'une seule valeur 32 bits nécessitera de l'espace pour les valeurs 32 * 4 octets; 128 octets au total. Ce qui, selon la taille de la pile, peut ou non être un problème.Imprimer le binaire pour tout type de données
tester
la source
size_t i; for (i=size; i-- > 0; )
d'évitersize_t
ou deint
mésappariement.ptr
(boucle externe); puis pour chaque bit l'octet courant (boucle interne), masquez l'octet par le bit courant (1 << j
). Décalez ce droit pour obtenir un octet contenant 0 (0000 0000b
) ou 1 (0000 0001b
). Imprimez l'octet résultant printf avec le format%u
. HTH.>
avecsize_t
et non le>=
de votre commentaire pour déterminer quand terminer la boucle.>
et>=
avec les types non signés.0
est un cas de bord non signé et se produit généralement, contrairement aux mathématiques signées avec moins courantesINT_MAX/INT_MIN
.Voici un hack rapide pour démontrer les techniques pour faire ce que vous voulez.
la source
strcat
est une méthode inefficace pour ajouter un seul caractère à la chaîne à chaque passage de la boucle. Ajoutez plutôt achar *p = b;
et remplacez la boucle intérieure par*p++ = (x & z) ? '1' : '0'
.z
devrait commencer à 128 (2 ^ 7) au lieu de 256 (2 ^ 8). Pensez à mettre à jour pour prendre un pointeur sur le tampon à utiliser (pour la sécurité des threads), similaire àinet_ntoa()
.strcat()
! Je suis d'accord questrcat
c'est probablement plus facile à comprendre que la post-incrémentation d'un pointeur déréférencé pour l'affectation, mais même les débutants doivent savoir comment utiliser correctement la bibliothèque standard. Peut-être que l'utilisation d'un tableau indexé pour l'affectation aurait été une bonne démonstration (et fonctionnera en fait, car elleb
n'est pas réinitialisée à tous les zéros chaque fois que vous appelez la fonction).printf("%s + %s = %s", byte_to_binary(3), byte_to_binary(4), byte_to_binary(3+4))
.Il n'y a pas de spécificateur de conversion binaire dans la glibc normalement.
Il est possible d'ajouter des types de conversion personnalisés à la famille de fonctions printf () dans la glibc. Voir register_printf_function pour plus de détails. Vous pouvez ajouter une conversion% b personnalisée pour votre propre usage, si cela simplifie le code d'application pour le rendre disponible.
Voici un exemple de mise en œuvre d'un format d'impression personnalisé dans la glibc.
la source
warning: 'register_printf_function' is deprecated [-Wdeprecated-declarations]
Il y a une nouvelle fonction pour faire la même chose, cependant:register_printf_specifier()
. Un exemple de la nouvelle utilisation peut être trouvé ici: codereview.stackexchange.com/q/219994/200418Vous pouvez utiliser une petite table pour améliorer la vitesse 1 . Des techniques similaires sont utiles dans le monde embarqué, par exemple, pour inverser un octet:
1 Je me réfère principalement aux applications intégrées où les optimiseurs ne sont pas si agressifs et où la différence de vitesse est visible.
la source
Imprimez le bit le moins significatif et déplacez-le vers la droite. Faire cela jusqu'à ce que l'entier devienne zéro imprime la représentation binaire sans zéros de tête mais dans l'ordre inverse. En utilisant la récursivité, l'ordre peut être corrigé assez facilement.
Pour moi, c'est l'une des solutions les plus propres au problème. Si vous aimez le
0b
préfixe et un nouveau caractère de ligne de fin, je vous suggère d'habiller la fonction.Démo en ligne
la source
putc('0'+(number&1), stdout);
Sur la base de la réponse de @William Whyte, ceci est une macro qui fournit
int8
,16
,32
et64
versions, réutilisant lesINT8
macro pour éviter la répétition.Cela produit:
Pour plus de lisibilité, vous pouvez ajouter un séparateur, par exemple:
la source
PRINTF_BYTE_TO_BINARY_INT#
define à utiliser éventuellement.Voici une version de la fonction qui ne souffre pas de problèmes de réentrance ou de limites de taille / type d'argument:
Notez que ce code fonctionnerait aussi bien pour n'importe quelle base entre 2 et 10 si vous remplacez simplement les 2 par la base souhaitée. L'utilisation est:
Où
x
est toute expression intégrale.la source
char *a = binary_fmt(x), *b = binary_fmt(y);
cela ne fonctionneront pas comme prévu. Forcer l'appelant à passer un tampon rend explicites les exigences de stockage; l'appelant est bien sûr libre d'utiliser un tampon statique si cela est vraiment souhaité, puis la réutilisation du même tampon devient explicite. Notez également que, sur les PIC ABI modernes, les tampons statiques coûtent généralement plus de code d'accès que les tampons de la pile.la source
'1'
et'0'
au lieu de49
et48
dans votre ternaire. Ilb
doit également contenir 9 caractères afin que le dernier caractère puisse rester un terminateur nul.static char b[9] = {0}
2. Déclaration de déplacement de la boucle:int z,y;
3. Ajouter le zéro final:b[y] = 0
. De cette façon, aucune revitalisation n'est nécessaire.8
s devraient être remplacés parCHAR_BIT
.Solution simple et rapide:
Fonctionne pour tout type de taille et pour les encres signées et non signées. Le '& 1' est nécessaire pour gérer les entrées signées car le décalage peut faire l'extension du signe.
Il y a tellement de façons de procéder. Voici un super simple pour imprimer 32 bits ou n bits à partir d'un type 32 bits signé ou non signé (ne pas mettre de négatif s'il est signé, juste imprimer les bits réels) et pas de retour chariot. Notez que i est décrémenté avant le décalage de bit:
Qu'en est-il du retour d'une chaîne avec les bits à stocker ou à imprimer plus tard? Vous pouvez soit allouer la mémoire et la renvoyer et l'utilisateur doit la libérer, soit renvoyer une chaîne statique mais elle sera encombrée si elle est appelée à nouveau, ou par un autre thread. Les deux méthodes présentées:
Appeler avec:
la source
Aucune des réponses précédemment publiées ne correspond exactement à ce que je cherchais, alors j'en ai écrit une. Il est super simple d'utiliser% B avec le
printf
!la source
char* buffer = (char*) malloc(sizeof(char) * 50);
char *buffer = malloc(sizeof(*buffer) * 50);
Certains runtimes prennent en charge "% b" bien que ce ne soit pas une norme.
Voir également ici pour une discussion intéressante:
http://bytes.com/forum/thread591027.html
HTH
la source
Ce code devrait gérer vos besoins jusqu'à 64 bits. J'ai créé 2 fonctions pBin & pBinFill. Les deux font la même chose, mais pBinFill remplit les espaces de tête avec fillChar. La fonction de test génère des données de test, puis les imprime à l'aide de la fonction.
la source
width
place!La
printf()
famille ne peut imprimer qu'en base 8, 10 et 16 en utilisant directement les spécificateurs standard. Je suggère de créer une fonction qui convertit le nombre en une chaîne selon les besoins particuliers du code.Pour imprimer dans n'importe quelle base [2-36]
Jusqu'à présent, toutes les autres réponses ont au moins une de ces limitations.
Utilisez de la mémoire statique pour le tampon de retour. Cela limite le nombre de fois où la fonction peut être utilisée comme argument
printf()
.Allouez de la mémoire nécessitant le code appelant aux pointeurs libres.
Exiger que le code appelant fournisse explicitement un tampon approprié.
Appelez
printf()
directement. Cela oblige une nouvelle fonction àfprintf()
,sprintf()
,vsprintf()
, etc.Utilisez une plage entière réduite.
Ce qui suit n'a aucune des limitations ci-dessus . Il nécessite C99 ou version ultérieure et l'utilisation de
"%s"
. Il utilise un littéral composé pour fournir l'espace tampon. Il n'a aucun problème avec plusieurs appels dans unprintf()
.Production
la source
Peut-être un peu OT, mais si vous en avez besoin uniquement pour le débogage pour comprendre ou retracer certaines opérations binaires que vous faites, vous pouvez jeter un œil à wcalc (une simple calculatrice de console). Avec les options -b, vous obtenez une sortie binaire.
par exemple
la source
ruby -e 'printf("%b\n", 0xabc)'
,dc
suivies de2o
suivies par0x123p
et ainsi de suite.Il n'y a pas de fonction de formatage dans la bibliothèque standard C pour sortir un binaire comme ça. Toutes les opérations de formatage prises en charge par la famille printf visent un texte lisible par l'homme.
la source
La fonction récursive suivante peut être utile:
la source
J'ai optimisé la meilleure solution pour la taille et le C ++ - ness, et suis arrivé à cette solution:
la source
std::string
), vous pouvez tout aussi bien vous débarrasser dustatic
tableau. Le moyen le plus simple serait de simplement supprimer lestatic
qualificatif et de le rendreb
local à la fonction.((x>>z) & 0x01) + '0'
est suffisant.Imprimer des bits de tout type en utilisant moins de code et de ressources
Cette approche a pour attributs:
Production
J'ai utilisé une autre approche ( bitprint.h ) pour remplir une table avec tous les octets (sous forme de chaînes de bits) et les imprimer en fonction de l'octet d'entrée / d'index. Ça vaut le coup d'oeil.
la source
la source
J'ai aimé le code de paniq, le tampon statique est une bonne idée. Cependant, il échoue si vous voulez plusieurs formats binaires dans un seul printf () car il retourne toujours le même pointeur et écrase le tableau.
Voici un drop-in de style C qui fait pivoter le pointeur sur un tampon divisé.
la source
count
atteintMAXCNT - 1
, l'incrément suivant decount
le feraMAXCNT
au lieu de zéro, ce qui entraînera un accès hors des limites du tableau. Vous auriez dû fairecount = (count + 1) % MAXCNT
.MAXCNT + 1
appels à cette fonction en un seulprintf
. En général, si vous voulez donner l'option pour plus d'une chose, rendez-la infinie. Des nombres tels que 4 ne pouvaient que poser problème.Pas de manière standard et portable.
Certaines implémentations fournissent itoa () , mais ce ne sera pas le cas dans la plupart des cas, et il a une interface quelque peu minable. Mais le code est derrière le lien et devrait vous permettre d'implémenter votre propre formateur assez facilement.
la source
Conversion générique d'une instruction de tout type intégral en représentation de chaîne binaire à l'aide de la bibliothèque standard :
Ou juste:
std::cout << std::bitset<sizeof(num) * 8>(num);
la source
Ma solution:
la source
Sur la base de @ suggestion de ideasman42 dans sa réponse, il est une macro qui fournit
int8
,16
,32
et64
versions, réutilisant lesINT8
macro pour éviter la répétition.Cela produit:
Pour plus de lisibilité, vous pouvez changer:
#define PRINTF_BINARY_SEPARATOR
en#define PRINTF_BINARY_SEPARATOR ","
ou#define PRINTF_BINARY_SEPARATOR " "
Cela produira:
ou
la source
Utilisation:
Pour plus de réf., Voir Comment imprimer un nombre binaire via printf .
la source
devrait fonctionner - non testé.
la source
la source
Ensuite, vous verrez la disposition de la mémoire:
la source
Voici une petite variante de la solution de paniq qui utilise des modèles pour permettre l'impression d'entiers 32 et 64 bits:
Et peut être utilisé comme:
Voici le résultat:
la source