"0x1800785" gibi bir değer içeren bir karakterim [] var ama değeri vermek istediğim işlev bir int gerektiriyor, bunu int'e nasıl dönüştürebilirim? Etrafı araştırdım ama bir cevap bulamıyorum. Teşekkürler.
Yanıtlar:
Denedin strtol()
mi
strtol - dizgeyi uzun bir tam sayıya dönüştürür
Misal:
const char *hexstring = "abcdef0";
int number = (int)strtol(hexstring, NULL, 16);
Durumunda sayının dize gösterimi bir ile başlar 0x
önek, tek gereken temel olarak 0 kullanmalıdır:
const char *hexstring = "0xabcdef0";
int number = (int)strtol(hexstring, NULL, 0);
(16 gibi açık bir taban belirtmek de mümkündür, ancak artıklık getirmeyi önermem.)
"0x"
sadece kullanmalısınız . 0
16
strtol
size long
çok büyük bir altıgenle uğraşırken harika olan yazımı verir . Daha büyük altıgenler için yazı strtoll
tipi long long
için kullanın .
Veya kendi uygulamanıza sahip olmak istiyorsanız, bu hızlı işlevi bir örnek olarak yazdım:
/**
* hex2int
* take a hex string and convert it to a 32bit number (max 8 hex digits)
*/
uint32_t hex2int(char *hex) {
uint32_t val = 0;
while (*hex) {
// get current character then increment
uint8_t byte = *hex++;
// transform hex character to the 4bit equivalent number, using the ascii table indexes
if (byte >= '0' && byte <= '9') byte = byte - '0';
else if (byte >= 'a' && byte <='f') byte = byte - 'a' + 10;
else if (byte >= 'A' && byte <='F') byte = byte - 'A' + 10;
// shift 4 to make space for new digit, and add the 4 bits of the new digit
val = (val << 4) | (byte & 0xF);
}
return val;
}
Bunun gibi bir şey yararlı olabilir:
char str[] = "0x1800785";
int num;
sscanf(str, "%x", &num);
printf("0x%x %i\n", num, num);
Man sscanf oku
%x
, bir unsigned int
. Ve bunu düzeltseniz bile, dizenin temsil ettiği sayı daha büyükse UINT_MAX
, yine tanımsız bir davranış olur
Bunun bir ip olduğunu varsayarsak, strtol'e ne dersiniz ?
int54_t
ve uint53_t
.
strtol
En iyi yanıtın önerdiği gibi libc'ye sahipseniz kullanın . Bununla birlikte, özel şeyleri seviyorsanız veya libc veya benzeri olmayan bir mikro denetleyicideyseniz, karmaşık dallanma içermeyen biraz optimize edilmiş bir sürüm isteyebilirsiniz.
#include <inttypes.h>
/**
* xtou64
* Take a hex string and convert it to a 64bit number (max 16 hex digits).
* The string must only contain digits and valid hex characters.
*/
uint64_t xtou64(const char *str)
{
uint64_t res = 0;
char c;
while ((c = *str++)) {
char v = (c & 0xF) + (c >> 6) | ((c >> 3) & 0x8);
res = (res << 4) | (uint64_t) v;
}
return res;
}
Bit kaydırma büyüsü şu şekildedir: Sadece son 4 biti kullanın, ancak rakam değilse, 9 ekleyin.
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; }
(c >> 6) | ((c >> 3) & 0x8)
→ harf olması durumunda 9, ondalık olması halinde 0 olarak değerlendirilir. Evet, oldukça hacky :)
Aşağıdaki kod bloğunu deneyin, benim için çalışıyor.
char *p = "0x820";
uint16_t intVal;
sscanf(p, "%x", &intVal);
printf("value x: %x - %d", intVal, intVal);
Çıktı:
value x: 820 - 2080
Bir süre araştırdıktan ve strtol'ün oldukça yavaş olduğunu öğrendikten sonra, kendi fonksiyonumu kodladım. Yalnızca büyük harfler için çalışır, ancak küçük harf işlevselliği eklemek sorun olmaz.
int hexToInt(PCHAR _hex, int offset = 0, int size = 6)
{
int _result = 0;
DWORD _resultPtr = reinterpret_cast<DWORD>(&_result);
for(int i=0;i<size;i+=2)
{
int _multiplierFirstValue = 0, _addonSecondValue = 0;
char _firstChar = _hex[offset + i];
if(_firstChar >= 0x30 && _firstChar <= 0x39)
_multiplierFirstValue = _firstChar - 0x30;
else if(_firstChar >= 0x41 && _firstChar <= 0x46)
_multiplierFirstValue = 10 + (_firstChar - 0x41);
char _secndChar = _hex[offset + i + 1];
if(_secndChar >= 0x30 && _secndChar <= 0x39)
_addonSecondValue = _secndChar - 0x30;
else if(_secndChar >= 0x41 && _secndChar <= 0x46)
_addonSecondValue = 10 + (_secndChar - 0x41);
*(BYTE *)(_resultPtr + (size / 2) - (i / 2) - 1) = (BYTE)(_multiplierFirstValue * 16 + _addonSecondValue);
}
return _result;
}
Kullanım:
char *someHex = "#CCFF00FF";
int hexDevalue = hexToInt(someHex, 1, 8);
1 çünkü dönüştürmek istediğimiz onaltılık uzaklık 1'den başlar ve 8, çünkü bu onaltılık uzunluktur.
Hız testi (1.000.000 çağrı):
strtol ~ 0.4400s
hexToInt ~ 0.1100s
Hızlı ve kirli bir çözüm:
// makes a number from two ascii hexa characters
int ahex2int(char a, char b){
a = (a <= '9') ? a - '0' : (a & 0x7) + 9;
b = (b <= '9') ? b - '0' : (b & 0x7) + 9;
return (a << 4) + b;
}
Girişinizin doğru olduğundan, doğrulama dahil edilmediğinden emin olmalısınız (C olduğu söylenebilir). İyi ki oldukça kompakt, hem "A" dan "F" ye hem de "a" dan "f" ye kadar çalışıyor.
Yaklaşım, ASCII tablosundaki alfabe karakterlerinin konumuna dayanır, örneğin Wikipedia'ya göz atalım ( https://en.wikipedia.org/wiki/ASCII#/media/File:USASCII_code_chart.png ). Uzun lafın kısası, sayılar karakterlerin altındadır, bu nedenle sayısal karakterler (0'dan 9'a), kodu sıfıra çıkararak kolayca dönüştürülür. Alfabetik karakterler (A'dan F'ye), son üç bit dışında sıfırlanarak (etkin bir şekilde büyük veya küçük harfle çalışmasını sağlayarak), bir çıkararak (çünkü bit maskelemeden sonra alfabe birinci konumda başlar) ve on eklenerek ( çünkü A - F, onaltılık kodda 10. - 15. değeri temsil eder). Son olarak, kodlanmış sayının alt ve üst yarım baytını oluşturan iki rakamı birleştirmemiz gerekiyor.
Burada aynı yaklaşımla gidiyoruz (küçük varyasyonlarla):
#include <stdio.h>
// takes a null-terminated string of hexa characters and tries to
// convert it to numbers
long ahex2num(unsigned char *in){
unsigned char *pin = in; // lets use pointer to loop through the string
long out = 0; // here we accumulate the result
while(*pin != 0){
out <<= 4; // we have one more input character, so
// we shift the accumulated interim-result one order up
out += (*pin < 'A') ? *pin & 0xF : (*pin & 0x7) + 9; // add the new nibble
pin++; // go ahead
}
return out;
}
// main function will test our conversion fn
int main(void) {
unsigned char str[] = "1800785"; // no 0x prefix, please
long num;
num = ahex2num(str); // call the function
printf("Input: %s\n",str); // print input string
printf("Output: %x\n",num); // print the converted number back as hexa
printf("Check: %ld = %ld \n",num,0x1800785); // check the numeric values matches
return 0;
}
Bu, onaltılı içeren char dizisini, fazladan kitaplık gerektirmeyen bir tamsayıya doğrudan dönüştürmek için bir işlevdir:
int hexadecimal2int(char *hdec) {
int finalval = 0;
while (*hdec) {
int onebyte = *hdec++;
if (onebyte >= '0' && onebyte <= '9'){onebyte = onebyte - '0';}
else if (onebyte >= 'a' && onebyte <='f') {onebyte = onebyte - 'a' + 10;}
else if (onebyte >= 'A' && onebyte <='F') {onebyte = onebyte - 'A' + 10;}
finalval = (finalval << 4) | (onebyte & 0xF);
}
finalval = finalval - 524288;
return finalval;
}
Kullanmadan Onaltılık / Ondalık dönüşüm yapmak için bir kitaplık yaptım stdio.h
. Kullanımı çok basit:
unsigned hexdec (const char *hex, const int s_hex);
İlk dönüşümden önce, dönüşüm için kullanılan diziyi şu şekilde tanıtın:
void init_hexdec ();
İşte github'daki bağlantı: https://github.com/kevmuret/libhex/
Ben de benzer bir şey yaptım, bunun aslında benim için çalışmasına yardımcı olabileceğini düşünüyorum
int main(){ int co[8],i;char ch[8];printf("please enter the string:");scanf("%s",ch);for(i=0;i<=7;i++){if((ch[i]>='A')&&(ch[i]<='F')){co[i]=(unsigned int)ch[i]-'A'+10;}else if((ch[i]>='0')&&(ch[i]<='9')){co[i]=(unsigned int)ch[i]-'0'+0;}}
burada sadece 8 karakterlik bir dizi aldım. Eğer 'a' dan 'f' ye eşdeğer onaltılık değerleri vermek için benzer bir mantık ekleyebilirsiniz, bunu yapmadım çünkü ihtiyacım olmadı.
Bunun gerçekten eski olduğunu biliyorum ama çözümlerin çok karmaşık göründüğünü düşünüyorum. Bunu VB'de deneyin:
Public Function HexToInt(sHEX as String) as long
Dim iLen as Integer
Dim i as Integer
Dim SumValue as Long
Dim iVal as long
Dim AscVal as long
iLen = Len(sHEX)
For i = 1 to Len(sHEX)
AscVal = Asc(UCase(Mid$(sHEX, i, 1)))
If AscVal >= 48 And AscVal <= 57 Then
iVal = AscVal - 48
ElseIf AscVal >= 65 And AscVal <= 70 Then
iVal = AscVal - 55
End If
SumValue = SumValue + iVal * 16 ^ (iLen- i)
Next i
HexToInt = SumValue
End Function