Konwertuj ciąg szesnastkowy (char []) na int?


Odpowiedzi:


209

Czy próbowałeś strtol()?

strtol - konwertuje ciąg znaków na długą liczbę całkowitą

Przykład:

W przypadku znaków reprezentujący numer zaczyna się od 0xprefiksu, jeden musi powinni stosować 0 jako podstawy:

(Równie dobrze można określić jawną podstawę, taką jak 16, ale nie polecałbym wprowadzania nadmiarowości).


4
Jeśli ciąg szesnastkowy jest zawsze wprowadzany przez a, "0x"jak podano w pytaniu, powinieneś po prostu użyć 0zamiast 16.
Jens Gustedt,

16
@KelvinHu Nie ufaj cplusplus.com, to bzdura. Jeśli tak, przejdź do cppreference.com .

1
@KelvinHu Wiele technicznie niepoprawnych lub luźno sformułowanych informacji znajduje się w tej witrynie, a jeśli zobaczysz programistów C ++ wokół SO, wszyscy zniechęcą do polegania na niej z tego powodu.

1
@ H2CO3 Okay, widzę, jestem nowy w C ++, więc wyszukuję to w google i umieszczam cplusplus.com na samym początku. Naprawdę dziękuję za twoją informację.
Kelvin Hu

3
Na marginesie strtolpodaje typ, longktóry świetnie sprawdza się w przypadku bardzo dużego heksa. Użyj strtolldo pisania long longdla jeszcze większych heksów.
Steven Lu

20

Lub jeśli chcesz mieć własną implementację, napisałem tę szybką funkcję jako przykład:


1
Bardzo przydatne na platformach z ograniczonymi zasobami, takimi jak mikrokontrolery.
Mubin Icyer

19

Coś takiego może się przydać:

Przeczytaj man sscanf


1
Powoduje to niezdefiniowane zachowanie, %xmusi otrzymać adres pliku unsigned int. A nawet jeśli to naprawisz, jeśli liczba reprezentowana przez ciąg jest większa niż UINT_MAX, oznacza to ponownie niezdefiniowane zachowanie
MM

10

Zakładając, że masz na myśli ciąg, a co powiesz na strtol ?


Początkowo łączyłem się ze strtod (-> double) zamiast strtol. Chyba ktoś to widział, kiedy redagowałem.
James McLaughlin,

Cóż, to nie jest duży błąd ... kompilator automatycznie rzuca wartość zwracaną, jeśli zostanie przekazana do pliku int. +1, przy okazji.

Nie sądzę podwójne może przechowywać wszystkie możliwe wartości 32-bitowej liczby całkowitej puszkę (faktycznie, czy ktoś wie, czy jest to prawda, nie jestem 100% na liczbę zmiennoprzecinkową reprezentacji?).
James McLaughlin

4
@JamesMcLaughlin To może. 64-bitowy podwójny IEEE ma całkowitą dokładność do około 2 ^ 53.

Szczegóły: „64-bitowy podwójny IEEE ma całkowitą dokładność do około 2 ^ 53”. i trochę znak. Więc może obsłużyć int54_ti uint53_t.
chux - Przywróć Monikę

5

Użyj, strtoljeśli masz dostępną bibliotekę libc, jak sugeruje najlepsza odpowiedź. Jeśli jednak lubisz niestandardowe rzeczy lub korzystasz z mikrokontrolera bez biblioteki libc lub czegoś podobnego, możesz potrzebować nieco zoptymalizowanej wersji bez skomplikowanych rozgałęzień.

Magia przesuwania bitów sprowadza się do: Po prostu użyj ostatnich 4 bitów, ale jeśli nie jest to cyfra, dodaj także 9.


Jeśli będziesz miał okazję, mógłbyś wyjaśnić trochę więcej na temat działania linii „v =”? Udało mi się zaimplementować twoją funkcję do własnych celów w następujący sposób:unsigned long long int hextou64(char *str) { unsigned long long int n = 0; char c, v; for (unsigned char i = 0; i < 16; i++) { c = *(str + i); v = (c & 0xF) + (c >> 6) | ((c >> 3) & 0x8); n = (n << 4) | (unsigned long long int)v; } return n; }
iamoumuamua

Zobaczmy, czy uda mi się to jeszcze połączyć ^^ Wydaje mi się, że jest to dość trudne .. Przesłanka: „0” - „9” wszystkie zaczynają się od „0011 ????” binarnie. „A” - „F” zaczynają się od „0100 ????” binarnie. Możemy wykorzystać te informacje, aby uniknąć rozgałęzień. (c & 0xF) → tylko ostatnie cztery bity zawierają wartość. To jest już poprawna wartość dla „0” - „9”. W przypadku „A” - „F” musimy dodać 9 dziesiętne, aby uzyskać prawidłową wartość. (Na przykład Hex C kończy się na 0011. Co jest 3. Ale chcemy 12. Dlatego musimy dodać 9. (c >> 6) | ((c >> 3) & 0x8)→ daje w wyniku 9 w przypadku litery lub 0 w przypadku ułamka dziesiętnego. Tak, całkiem
zepsuty

3

Wypróbuj poniższy blok kodu, działa dla mnie.

Wynik to:


3

Tak więc po chwili wyszukiwania i stwierdzeniu, że strtol jest dość powolny, zakodowałem własną funkcję. Działa tylko w przypadku wielkich liter, ale dodanie funkcji małych liter nie stanowi problemu.

Stosowanie:

1, ponieważ hex, który chcemy przekonwertować, zaczyna się od przesunięcia 1, a 8, ponieważ jest to długość szesnastkowa.

Speedtest (1.000.000 połączeń):


2

Jedno szybkie i brudne rozwiązanie:

Musisz mieć pewność, że wprowadzone dane są poprawne, bez weryfikacji (można powiedzieć, że to C). Dobrze, że jest dość kompaktowy, działa zarówno z „A” do „F”, jak i „a” do „f”.

Podejście opiera się na pozycji znaków alfabetu w tabeli ASCII, zajrzyjmy np. Do Wikipedii ( https://en.wikipedia.org/wiki/ASCII#/media/File:USASCII_code_chart.png ). Krótko mówiąc, liczby znajdują się pod znakami, więc znaki numeryczne (od 0 do 9) można łatwo przekonwertować, odejmując kod na zero. Znaki alfabetu (od A do F) są odczytywane przez zerowanie inne niż ostatnie trzy bity (efektywnie dzięki czemu działa z dużą lub małą literą), odejmowanie jednego (ponieważ po maskowaniu bitów, alfabet zaczyna się na pozycji pierwszej) i dodawanie dziesięciu ( ponieważ od A do F reprezentują od 10 do 15 wartości w kodzie szesnastkowym). Na koniec musimy połączyć dwie cyfry, które tworzą dolną i górną część zakodowanej liczby.

Tutaj idziemy z tym samym podejściem (z niewielkimi zmianami):


1
Po opublikowaniu odpowiedzi dowiedziałem się, że przegapiłem post @LimeRed, który jest bardzo uroczy
Simon

1

Jest to funkcja umożliwiająca bezpośrednią konwersję szesnastkowej tablicy znaków zawierającej znaki na liczbę całkowitą, która nie wymaga dodatkowej biblioteki:


0

Zrobiłem librairy, aby dokonać konwersji szesnastkowej / dziesiętnej bez użycia stdio.h. Bardzo prosty w użyciu:

Przed pierwszą konwersją zainicjuj tablicę używaną do konwersji za pomocą:

Tutaj link na github: https://github.com/kevmuret/libhex/


0

Zrobiłem podobną rzecz, myślę, że może ci to pomóc, że faktycznie działa dla mnie

tutaj wziąłem tylko ciąg 8 znaków. jeśli chcesz, możesz dodać podobną logikę dla „a” do „f”, aby podać ich równoważne wartości szesnastkowe, nie zrobiłem tego, ponieważ nie potrzebowałem tego.


-5

Wiem, że to jest naprawdę stare, ale myślę, że rozwiązania wyglądały na zbyt skomplikowane. Spróbuj tego w VB:

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.