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

82

Mam znak char [], który zawiera wartość, taką jak „0x1800785”, ale funkcja, której chcę nadać wartość, wymaga int, jak mogę przekonwertować to na int? Szukałem w okolicy, ale nie mogę znaleźć odpowiedzi. Dzięki.

kizyle502
źródło
1
możliwe duplikat konwersji łańcucha do podpisanego int
maska bitowa

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).

Mahendra Gunawardena
źródło
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:

radhoo
źródło
1
Bardzo przydatne na platformach z ograniczonymi zasobami, takimi jak mikrokontrolery.
Mubin Icyer
19

Coś takiego może się przydać:

Przeczytaj man sscanf

Saxi
źródło
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 ?

James McLaughlin
źródło
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.

LimeRed
źródło
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:

Wykop kod
źródło
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ń):

mexikanoZ
źródło
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):

Szymon
źródło
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:

Vaibhav VK
źródło
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/

kevmuret
źródło
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.

sairam singh
źródło
-5

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

CHEWBAKKEE
źródło