Mogę drukować za pomocą printf jako liczby szesnastkowej lub ósemkowej. Czy istnieje znacznik formatu do wydrukowania jako baza binarna lub dowolna?
Korzystam z gcc.
printf("%d %x %o\n", 10, 10, 10); //prints "10 A 12\n"
print("%b\n", 10); // prints "%b\n"
Odpowiedzi:
Hacky, ale działa dla mnie:
Dla typów wielobajtowych
Niestety potrzebujesz wszystkich dodatkowych cytatów. Takie podejście wiąże się z ryzykiem wydajności makr (nie przekazuj funkcji jako argumentu
BYTE_TO_BINARY
), ale pozwala uniknąć problemów z pamięcią i wielokrotnych wywołań strcat w niektórych innych propozycjach tutaj.źródło
printf
dostatic
buforów z buforami.%d
się%c
, ponieważ powinien być jeszcze szybszy (%d
musi wykonać digit-> CHAr, podczas gdy%c
po prostu wyprowadza argumentint
w systemie jest 32 bity, wydrukowanie pojedynczej wartości 32-bitowej będzie wymagało miejsca na wartości 32 * 4 bajty; łącznie 128 bajtów. Co, w zależności od wielkości stosu, może, ale nie musi stanowić problemu.Drukuj plik binarny dla dowolnego typu danych
test
źródło
size_t i; for (i=size; i-- > 0; )
aby unikaćsize_t
kontraint
niewłaściwe dopasowanie.ptr
(zewnętrzna pętla); następnie dla każdego bitu bieżący bajt (pętla wewnętrzna) zamaskuj bajt bieżącym bitem (1 << j
). Przesunięcie w prawo powoduje powstanie bajtu zawierającego 0 (0000 0000b
) lub 1 (0000 0001b
). Wydrukuj wynikowy bajt printf z formatem%u
. HTH.>
z komentarzem,size_t
a nie>=
z twojego komentarza, aby określić, kiedy zakończyć pętlę.>
i>=
typów bez znaku.0
jest nieoznaczonym przypadkiem na krawędzi i często występuje, w przeciwieństwie do podpisanej matematyki z mniej powszechnymINT_MAX/INT_MIN
.Oto szybki hack, aby zademonstrować techniki robienia tego, co chcesz.
źródło
strcat
jest nieefektywną metodą dodawania pojedynczego znaku do ciągu przy każdym przejściu pętli. Zamiast tego dodaj achar *p = b;
i zamień wewnętrzną pętlę na*p++ = (x & z) ? '1' : '0'
.z
powinien zaczynać się od 128 (2 ^ 7) zamiast 256 (2 ^ 8). Rozważ aktualizację, aby wziąć wskaźnik do bufora do użycia (dla bezpieczeństwa wątków), podobnie jakinet_ntoa()
.strcat()
! Zgadzam się, żestrcat
jest to prawdopodobnie łatwiejsze do zrozumienia niż zwiększanie wskaźnika do zadania z pominięciem odniesienia, ale nawet początkujący muszą wiedzieć, jak prawidłowo korzystać ze standardowej biblioteki. Być może użycie tablicy indeksowanej do przypisania byłoby dobrą demonstracją (i faktycznie będzie działać, ponieważb
nie resetuje się do zer zerowych przy każdym wywołaniu funkcji).printf("%s + %s = %s", byte_to_binary(3), byte_to_binary(4), byte_to_binary(3+4))
.Normalnie w glibc nie ma specyfikatora konwersji binarnej.
Możliwe jest dodanie niestandardowych typów konwersji do rodziny funkcji printf () w glibc. Aby uzyskać szczegółowe informacje, patrz register_printf_function . Możesz dodać niestandardową konwersję% b do własnego użytku, jeśli upraszcza to kod aplikacji, aby był dostępny.
Oto przykład implementacji niestandardowych formatów printf w glibc.
źródło
warning: 'register_printf_function' is deprecated [-Wdeprecated-declarations]
Jest to nowa funkcja, aby zrobić to samo, ale:register_printf_specifier()
. Przykład nowego zastosowania można znaleźć tutaj: codereview.stackexchange.com/q/219994/200418Możesz użyć małego stolika, aby poprawić prędkość 1 . Podobne techniki są przydatne w świecie osadzonym, na przykład do odwrócenia bajtu:
1 Mam na myśli głównie aplikacje wbudowane, w których optymalizatory nie są tak agresywne, a różnica prędkości jest widoczna.
źródło
Wydrukuj najmniej znaczący bit i przesuń go w prawo. Robiąc to, dopóki liczba całkowita nie zmieni się w zero, drukuje reprezentację binarną bez zer wiodących, ale w odwrotnej kolejności. Za pomocą rekurencji kolejność można dość łatwo poprawić.
Dla mnie jest to jedno z najczystszych rozwiązań problemu. Jeśli podoba Ci się
0b
przedrostek i znak nowej linii, sugeruję zawinięcie funkcji.Demo online
źródło
putc('0'+(number&1), stdout);
Na podstawie odpowiedzi @William Whyte, ten jest makro, które zapewnia
int8
,16
,32
i64
wersje, ponowne użycieINT8
makra w celu uniknięcia powtórzeń.To daje:
Aby zapewnić czytelność, możesz dodać separator dla np .:
źródło
PRINTF_BYTE_TO_BINARY_INT#
definicji do opcjonalnego użycia.Oto wersja funkcji, która nie cierpi z powodu problemów z ponownym uruchomieniem lub ograniczeń rozmiaru / typu argumentu:
Zauważ, że ten kod będzie działał równie dobrze dla dowolnej bazy między 2 a 10, jeśli po prostu zastąpisz 2 przez pożądaną bazę. Zastosowanie to:
Gdzie
x
jest jakieś wyrażenie integralne.źródło
char *a = binary_fmt(x), *b = binary_fmt(y);
nie będą działać zgodnie z oczekiwaniami. Zmuszenie osoby dzwoniącej do przekazania bufora powoduje, że wymagania dotyczące miejsca stają się oczywiste; osoba dzwoniąca może oczywiście użyć bufora statycznego, jeśli jest to naprawdę pożądane, a następnie ponowne użycie tego samego bufora staje się jawne. Zauważ również, że w nowoczesnych PIC ABI bufory statyczne zwykle kosztują więcej kodu niż dostęp do buforów na stosie.źródło
'1'
i'0'
zamiast49
i48
w trójskładnikowego. Ponadto,b
powinien być długi 9 znaków więc ostatnia postać może pozostać null terminator.static char b[9] = {0}
2. Oświadczenie wyjść z pętli:int z,y;
3. Dodać ostateczną Zerob[y] = 0
. W ten sposób nie jest wymagana ponowna inicjalizacja.8
powinny zostać zastąpione przezCHAR_BIT
.Szybkie i łatwe rozwiązanie:
Działa dla dowolnego typu rozmiaru i dla podpisanych i niepodpisanych int. „& 1” jest potrzebne do obsługi podpisanych znaków wewnętrznych, ponieważ przesunięcie może powodować rozszerzenie znaku.
Jest na to wiele sposobów. Oto bardzo prosty do drukowania 32 bitów lub n bitów z 32-bitowego typu ze znakiem lub bez znaku (nie wstawianie ujemnego znaku, tylko drukowanie rzeczywistych bitów) i bez powrotu karetki. Zauważ, że i jest zmniejszane przed przesunięciem bitów:
Co powiesz na zwrócenie ciągu z bitami do późniejszego zapisania lub wydrukowania? Możesz albo przydzielić pamięć i zwrócić ją, a użytkownik musi ją zwolnić, albo zwróci ciąg statyczny, ale zostanie zablokowany, jeśli zostanie ponownie wywołany lub przez inny wątek. Pokazano obie metody:
Zadzwoń z:
źródło
Żadna z wcześniej opublikowanych odpowiedzi nie była dokładnie tym, czego szukałem, więc napisałem jedną. Jest bardzo prosty w użyciu% B z
printf
!źródło
char* buffer = (char*) malloc(sizeof(char) * 50);
char *buffer = malloc(sizeof(*buffer) * 50);
Niektóre środowiska wykonawcze obsługują „% b”, chociaż nie jest to standard.
Zobacz także tutaj ciekawą dyskusję:
http://bytes.com/forum/thread591027.html
HTH
źródło
Ten kod powinien obsłużyć Twoje potrzeby do 64 bitów. Stworzyłem 2 funkcje pBin i pBinFill. Oba robią to samo, ale pBinFill wypełnia wiodące spacje znakiem fillChar. Funkcja testowa generuje niektóre dane testowe, a następnie drukuje je za pomocą funkcji.
źródło
width
zamiast tego!printf()
Rodzina jest tylko w stanie drukować w bazie 8, 10 i 16, stosując bezpośrednio standardowe specyfikatorów. Sugeruję utworzenie funkcji, która konwertuje liczbę na ciąg według określonych potrzeb kodu.Aby wydrukować w dowolnej bazie [2-36]
Wszystkie pozostałe odpowiedzi mają co najmniej jedno z tych ograniczeń.
Użyj pamięci statycznej dla bufora powrotu. Ogranicza to liczbę przypadków użycia funkcji jako argumentu
printf()
.Przydziel pamięć wymagającą kodu wywołującego, aby zwolnić wskaźniki.
Wymagaj od kodu wywołującego jawnego udostępnienia odpowiedniego bufora.
Zadzwoń
printf()
bezpośrednio. To zobowiązuje nową funkcję dofprintf()
,sprintf()
,vsprintf()
, itd.Użyj zmniejszonego zakresu liczb całkowitych.
Poniższe nie ma żadnego z powyższych ograniczeń . Wymaga C99 lub nowszego i użycia
"%s"
. Używa literału złożonego, aby zapewnić przestrzeń buforową. Nie ma problemu z wieloma połączeniami wprintf()
.Wynik
źródło
Może trochę OT, ale jeśli potrzebujesz tego tylko do debugowania, aby zrozumieć lub odtworzyć niektóre wykonywane operacje binarne, możesz rzucić okiem na wcalc (prosty kalkulator konsoli). Z opcjami -b otrzymujesz wyjście binarne.
na przykład
źródło
ruby -e 'printf("%b\n", 0xabc)'
,dc
po czym2o
następuje0x123p
, i tak dalej.W standardowej bibliotece C nie ma funkcji formatowania, która wyprowadzałaby takie pliki binarne. Wszystkie operacje formatowania obsługiwane przez rodzinę printf są skierowane na tekst czytelny dla człowieka.
źródło
Przydatna może być następująca funkcja rekurencyjna:
źródło
Zoptymalizowałem najlepsze rozwiązanie dla rozmiaru i C ++ - i doszedłem do tego rozwiązania:
źródło
std::string
), równie dobrze możesz pozbyć sięstatic
tablicy. Najprostszym sposobem byłoby po prostu upuszczeniestatic
kwalifikatora i uczynienie gob
lokalnym dla funkcji.((x>>z) & 0x01) + '0'
jest wystarczający.Drukuj bity dowolnego typu, używając mniej kodu i zasobów
Podejście to ma następujące atrybuty:
Wynik
Użyłem innego podejścia ( bitprint.h ), aby wypełnić tabelę wszystkimi bajtami (jako ciągi bitów) i wydrukować je w oparciu o bajt wejściowy / indeksowy. Warto się przyjrzeć.
źródło
źródło
Podobał mi się kod paniq, bufor statyczny to dobry pomysł. Jednak nie powiedzie się, jeśli chcesz wielu formatów binarnych w jednym printf (), ponieważ zawsze zwraca ten sam wskaźnik i zastępuje tablicę.
Oto lista rozwijana w stylu C, która obraca wskaźnik na podzielonym buforze.
źródło
count
osiągnieMAXCNT - 1
, następny przyrostcount
spowoduje, żeMAXCNT
zamiast zera, spowoduje to dostęp poza granice tablicy. Powinieneś był to zrobićcount = (count + 1) % MAXCNT
.MAXCNT + 1
wywołań tej funkcji w jednymprintf
. Ogólnie, jeśli chcesz dać opcję więcej niż 1 rzeczy, ustaw ją na nieskończoność. Liczby takie jak 4 mogą tylko powodować problemy.Brak standardowego i przenośnego sposobu.
Niektóre implementacje zapewniają itoa () , ale w większości nie będzie i ma nieco kiepski interfejs. Ale kod znajduje się za linkiem i powinien umożliwić łatwe wdrożenie własnego formatera.
źródło
Jedna instrukcja ogólna konwersja dowolnego typu integralnego na reprezentację ciągu binarnego przy użyciu standardowej biblioteki:
Lub tylko:
std::cout << std::bitset<sizeof(num) * 8>(num);
źródło
Moje rozwiązanie:
źródło
Na podstawie sugestii użytkownika @ ideasman42 w jego odpowiedzi, jest to makro, który zapewnia
int8
,16
,32
i64
wersje, ponowne użycieINT8
makra w celu uniknięcia powtórzeń.To daje:
Dla czytelności możesz zmienić:
#define PRINTF_BINARY_SEPARATOR
na#define PRINTF_BINARY_SEPARATOR ","
lub#define PRINTF_BINARY_SEPARATOR " "
Spowoduje to:
lub
źródło
Posługiwać się:
Aby uzyskać więcej informacji, zobacz Jak wydrukować liczbę binarną za pomocą printf .
źródło
powinien działać - niesprawdzony.
źródło
źródło
Następnie pokaże ci układ pamięci:
źródło
Oto niewielka odmiana rozwiązania paniq , która wykorzystuje szablony do drukowania liczb całkowitych 32- i 64-bitowych:
I może być używany jak:
Oto wynik:
źródło