2013-08-29 5 views
2

У меня есть номер версии для приложения, которое представляет собой форму 0x00870016, где первые 4 шестнадцатеричных цифры представляют первую часть номера версии, а вторую 4 - вторую, поэтому в этом примере версия число - 135,22.Извлечение чисел из странной строки версии

Я пытаюсь выяснить, как (в C++) я бы извлек эти числа отдельно, чтобы отобразить их как строку.

ответ

9

При использовании комбинации масок и сдвигов:

int main() 
{ 
    const uint32_t v = 0x00870016; 
    const uint16_t major = (v & 0xFFFF0000) >> 16; 
    const uint16_t minor = v & 0x0000FFFF; 
    cout << major << "." << minor << "\n"; 
} 

Выход:

135.22 

Пояснение:

0x00870016 представляет собой 32-битное число. Ваш основной номер версии состоит из 16 наиболее значимых цифр, а младший номер версии - это 16 наименее значащих цифр.

Для извлечения основного номера версии, давайте выясним, что 16 MSBits является маскировка значения входного сигнала с 0xFFFF0000 - номером, по которому все 16 из наиболее signifigant цифр устанавливаются в 1 и все наималейшее сиг биты 0:

0x00870016 && 0xFFFF0000 = 0x00870000 

Полученное значение является вашим основным номером версии, сдвинут влево 16 бит. Поэтому давайте переместим его на:

0x00870000 >> 16 = 0x00000087 

И вот у нас есть ваш настоящий номер главной версии.

Извлечение младшего номера версии аналогично, за исключением того, что нам не нужно сдвигать.

Примечание:

Первый шаг может быть упрощена путем пропуска маски:

const uint16_t major = v >> 16; 

Это работает, потому что Стандарт C++ говорит, что, когда вы сдвиг вправо, освободившиеся биты заполняются 0 s. Таким образом, окончательная программа будет:

int main() 
{ 
    const uint32_t v = 0x00870016; 
    const uint16_t major = v >> 16; 
    const uint16_t minor = v & 0x0000FFFF; 
    cout << major << "." << minor << "\n"; 
} 

Edit:

Как было отмечено в комментариях, вы можете получать 0x00870016 в виде строки, а не числа. Нам просто нужно преобразовать эту строку в числовой эквивалент.Работа с ведущими 0x может показаться, как камень преткновения, но это не так, если вы используете C++ Standard Library iostream манипуляторов:

int main() 
{ 
    const std::string inVer = "0x00870016"; 
    uint32_t v = 0; 
    std::stringstream ss; 
    ss << inVer; 
    ss >> std::hex >> v; 
    const uint16_t major = v >> 16; 
    const uint16_t minor = v & 0x0000FFFF; 
    cout << major << "." << minor << "\n"; 
} 
+0

OP получили версию в виде строки, Я думаю, было бы интересно добавить бит кода, который сначала преобразует его в интегральное значение ради полноты – SirDarius

+0

@SirDarius: Согласовано и отредактировано. –

+0

Не используйте здесь 'uint32_t' и' uint16_t': они переполнены, потому что ** не существуют ** в системах, которые не имеют таких точных размеров. Если код использует 'uint_least32_t' или' uint_fast32_t' или 'unsigned long', он будет работать так же хорошо, и не будет иметь этой переносимости. –

0
unsigned version = 0x00870016; 
unsigned major = version >> 16; 
unsigned minor = version & 0xffff; 

printf("Version %u.%u\n", major, minor); 

или

std::cout << "Version " << major << "." << minor << std::endl; 
+0

Обратите внимание, что 'unsigned' может быть недостаточно большим, чтобы удерживать' 0x00870016', так как он должен содержать значения до '0xffff'. Используйте 'unsigned long' или, если вы должны (' '),' uint_least32_t'. –

Смежные вопросы