70

Tôi có một char [] chứa giá trị như "0x1800785" nhưng hàm tôi muốn cung cấp giá trị để yêu cầu int, làm cách nào tôi có thể chuyển đổi giá trị này thành 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.

|
180

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 0xtiề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 như 16, nhưng tôi không khuyên bạn nên giới thiệu dự phòng.)

|
19

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 người đàn ông sscanf

|
  • 1

    Điều này gây ra hành vi không xác định, %xphải nhận địa chỉ của một unsigned int. Và ngay cả khi bạn sửa lỗi đó, nếu số được biểu thị bằng chuỗi lớn hơn UINT_MAXthì đó là hành vi không xác định lại

    – Hồ Hoàng Xuân 02:09:19 11/02/2019
10

Hoặc nếu bạn muốn có cách triển khai của riêng mình, 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;
}
|
9

Giả sử bạn có nghĩa đó là một chuỗi, còn strtol thì sao?

|
  • 1

    Tại sao downvote này, nghiêm túc?

    – Lê Lan Nghi 19:03:43 14/04/2012
  • 1

    Ban đầu tôi đã liên kết với strtod (-> double) thay vì strtol. Tôi đoán ai đó đã nhìn thấy nó trong khi tôi đang chỉnh sửa.

    – Đặng Tuấn Hùng 19:04:25 14/04/2012
  • 1

    Chà, đó không phải là một lỗi quá lớn ... trình biên dịch sẽ tự động đưa ra giá trị trả về nếu được cung cấp cho một int. +1, btw.

    – Tạ Bội Linh 19:05:05 14/04/2012
  • 1

    Tôi không nghĩ rằng một nhân đôi có thể lưu trữ tất cả các giá trị có thể có một số nguyên 32 bit (thực ra, có ai biết điều này có đúng không? Tôi không 100% khi biểu diễn số dấu phẩy động.)

    – Hoàng Bảo An 19:06:08 14/04/2012
  • 1

    @JamesMcLaughlin Nó có thể. Bộ đôi IEEE 64 bit có độ chính xác tích phân đến khoảng 2 ^ 53.

    – Tạ Minh Toàn 19:10:06 14/04/2012
4

Hãy thử bên dưới khối mã, nó hoạt động với tôi.

char *p = "0x820";
uint16_t intVal;
sscanf(p, "%x", &intVal);

printf("value x: %x - %d", intVal, intVal);

Đầu ra là:

value x: 820 - 2080
|
3

Vì vậy, sau một thời gian tìm kiếm và phát hiện ra rằng strtol khá chậm, tôi đã mã hóa chức năng của chính mình. Nó chỉ hoạt động cho chữ hoa trên chữ cái, nhưng thêm chức năng chữ thường không phải là một 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 chúng tôi muốn chuyển đổi bắt đầu ở offset 1 và 8 vì đó là hex.

Speedtest (1.000.000 cuộc gọi):

strtol ~ 0.4400s
hexToInt ~ 0.1100s
|
1

Tôi biết điều này thực sự cũ nhưng tôi nghĩ các giải pháp có vẻ 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 
|
1

Sử dụng xtoi (stdlib.h). Chuỗi có "0x" là hai chỉ mục đầu tiên, vì vậy hãy cắt val [0] và val [1] bằng cách gửi xtoi & val [2].

xtoi( &val[2] );

|
0

tôi đã làm một điều tương tự, nghĩ rằng nó có thể giúp bạ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' để đưa ra 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ó.

|
0

Tôi đã thực hiện một librairy để thực hiện chuyển đổi 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, intialize mảng được sử dụng để chuyển đổi với:

void init_hexdec ();

Đây là đường dẫn trên github: https://github.com/kevmuret/libhex/

|

Câu trả lời của bạn (> 20 ký tự)

Bằng cách click "Đăng trả lời", bạn đồng ý với Điều khoản dịch vụ, Chính sách bảo mật and Chính sách cookie của chúng tôi.

Không tìm thấy câu trả lời bạn tìm kiếm? Duyệt qua các câu hỏi được gắn thẻ hoặc hỏi câu hỏi của bạn.