Tôi có một char [] có chứa một giá trị chẳng hạn như "0x1800785" nhưng hàm tôi muốn cung cấp giá trị yêu cầu một int, làm cách nào để chuyển đổi giá trị này thành một int? Tôi đã tìm kiếm xung quanh nhưng không thể tìm thấy câu trả lời. Cảm ơn.
Tôi có một char [] có chứa một giá trị chẳng hạn như "0x1800785" nhưng hàm tôi muốn cung cấp giá trị yêu cầu một int, làm cách nào để chuyển đổi giá trị này thành một int? Tôi đã tìm kiếm xung quanh nhưng không thể tìm thấy câu trả lời. Cảm ơn.
Câu trả lời:
Bạn đã thử strtol()
chưa?
strtol - chuyển đổi chuỗi thành một số nguyên dài
Thí dụ:
const char *hexstring = "abcdef0";
int number = (int)strtol(hexstring, NULL, 16);
Trong trường hợp biểu diễn chuỗi của số bắt đầu bằng 0x
tiền tố, người ta phải sử dụng 0 làm cơ sở:
const char *hexstring = "0xabcdef0";
int number = (int)strtol(hexstring, NULL, 0);
(Cũng có thể chỉ định một cơ sở rõ ràng chẳng hạn như 16, nhưng tôi không khuyên bạn nên giới thiệu dư thừa.)
"0x"
như đã cho trong câu hỏi, bạn chỉ nên sử dụng 0
thay vì 16
.
strtol
cung cấp cho bạn loại long
rất tốt khi xử lý một hex rất lớn. Sử dụng strtoll
cho loại long long
cho hexes thậm chí lớn hơn.
Hoặc nếu bạn muốn triển khai riêng, tôi đã viết hàm nhanh này làm ví dụ:
/**
* 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;
}
Một cái gì đó như thế này có thể hữu ích:
char str[] = "0x1800785";
int num;
sscanf(str, "%x", &num);
printf("0x%x %i\n", num, num);
Đọc man sscanf
%x
phải nhận địa chỉ của một unsigned int
. Và ngay cả khi bạn khắc phục điều đó, nếu số được đại diện bởi chuỗi lớn hơn UINT_MAX
thì đó là hành vi không xác định một lần nữa
Giả sử ý bạn là một chuỗi, vậy còn strtol thì sao?
int
. +1, btw.
int54_t
và uint53_t
.
Sử dụng strtol
nếu bạn có sẵn libc như câu trả lời trên đề xuất. Tuy nhiên, nếu bạn thích nội dung tùy chỉnh hoặc sử dụng vi điều khiển không có libc, bạn có thể muốn một phiên bản được tối ưu hóa một chút mà không cần phân nhánh phức tạp.
#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;
}
Phép thuật dịch chuyển bit tổng hợp thành: Chỉ cần sử dụng 4 bit cuối cùng, nhưng nếu nó là một chữ số không phải là chữ số, thì cũng thêm 9.
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)
→ đánh giá là 9 trong trường hợp là một chữ cái, hoặc 0 trong trường hợp là số thập phân. Đúng vậy, khá khó hiểu :)
Vì vậy, sau một thời gian tìm kiếm và phát hiện ra rằng strtol chạy khá chậm, tôi đã code hàm của riêng mình. Nó chỉ hoạt động đối với chữ hoa trên các chữ cái, nhưng thêm chức năng viết thường không phải là vấn đề.
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;
}
Sử dụng:
char *someHex = "#CCFF00FF";
int hexDevalue = hexToInt(someHex, 1, 8);
1 vì hex mà chúng ta muốn chuyển đổi bắt đầu ở độ lệch 1 và 8 vì đó là độ dài hex.
Speedtest (1.000.000 cuộc gọi):
strtol ~ 0.4400s
hexToInt ~ 0.1100s
Một giải pháp nhanh chóng và bẩn thỉu:
// 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;
}
Bạn phải chắc chắn rằng đầu vào của bạn là chính xác, không bao gồm xác thực (có thể nói đó là C). Điều tốt là nó khá nhỏ gọn, nó hoạt động với cả 'A' thành 'F' và 'a' thành 'f'.
Cách tiếp cận dựa trên vị trí của các ký tự bảng chữ cái trong bảng ASCII, hãy xem ví dụ như Wikipedia ( https://en.wikipedia.org/wiki/ASCII#/media/File:USASCII_code_chart.png ). Truyện ngắn, các con số nằm dưới các ký tự, vì vậy các ký tự số (0 đến 9) dễ dàng được chuyển đổi bằng cách trừ mã cho số không. Các ký tự chữ cái (A đến F) được đọc bằng số 0 khác với ba bit cuối cùng (làm cho nó hoạt động hiệu quả với cả chữ hoa hoặc chữ thường), trừ đi một (vì sau khi che bit, bảng chữ cái bắt đầu ở vị trí một) và thêm mười ( vì A đến F đại diện cho giá trị thứ 10 đến thứ 15 trong mã thập lục phân). Cuối cùng, chúng ta cần kết hợp hai chữ số tạo thành nibble dưới và trên của số được mã hóa.
Ở đây chúng tôi đi với cùng một cách tiếp cận (với các biến thể nhỏ):
#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;
}
Đây là một hàm để chuyển đổi trực tiếp mảng char chứa thập lục phân thành một số nguyên mà không cần thêm thư viện:
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;
}
Tôi đã sử dụng thư viện để thực hiện chuyển đổi Hệ thập lục phân / Thập phân mà không cần sử dụng stdio.h
. Rất đơn giản để sử dụng:
unsigned hexdec (const char *hex, const int s_hex);
Trước khi chuyển đổi đầu tiên, hãy nhập số hóa mảng được sử dụng để chuyển đổi với:
void init_hexdec ();
Đây là liên kết trên github: https://github.com/kevmuret/libhex/
tôi đã làm một điều tương tự, nghĩ rằng nó có thể giúp ích cho bạn, nó thực sự làm việc cho tôi
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;}}
ở đây tôi chỉ lấy một chuỗi 8 ký tự. nếu bạn muốn bạn có thể thêm logic tương tự cho 'a' thành 'f' để cung cấp các giá trị hex tương đương của chúng, tôi đã không làm điều đó vì tôi không cần nó.
Sử dụng xtoi (stdlib.h). Chuỗi có "0x" là hai chỉ mục đầu tiên nên hãy cắt bớt val [0] và val [1] bằng cách gửi xtoi & val [2].
xtoi( &val[2] );
xtoi
không phải là một chức năng tiêu chuẩn
Tôi biết điều này thực sự cũ nhưng tôi nghĩ các giải pháp trông quá phức tạp. Hãy thử điều này trong VB:
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