2011-07-01 4 views
1

Я пытаюсь извлечь значение символа из формата UTF-8. Предположим, у меня есть два символа, и извлечь 5 битов из первого символа => 10111 и 6 бит из другого символа => 010000C++ бит-манипуляция

так

ch1 = 10111; 
ch2 = 010000; 

как бы я объединить их, чтобы сформировать 10111010000 и вывести его hex как 0x5d0? Нужно ли мне менять или есть более простой способ сделать это, потому что проверка документации write, по-видимому, способна читать символы последовательно, есть ли подобная функция? Кроме того, похоже, мне понадобится буфер символов, так как 10111010000 имеет длину 11 бит. Кто-нибудь знает, как это сделать?

+0

Как насчет использования 'union'? Возможно, вам придется проявлять особую осторожность, поскольку их выравнивание может быть зависимым от платформы. – iammilind

+0

@iammilind, как бы я использовал союз? Не могли бы вы ответить на этот вопрос? – Mark

ответ

3

Вам необходимо использовать сдвиг, плюс оператор | или |=.

unsigned int ch3 = (ch1 << 6) | ch2; 
// ch3 = 0000010111010000 

Я предполагаю, что unsigned int - это 16 бит. Ваш пробег может отличаться.

+0

Мне нужно до 21 бит, чтобы прочитать самый большой utf8. Как мне это сделать? – Mark

+1

И затем, чтобы напечатать в шестнадцатеричном виде, 'std :: cout << std :: showbase << std :: hex;' – juanchopanza

+2

@Mark Я бы посмотрел на ['std :: bitset'] (http: // www .cplusplus.com/ссылка/STL/BitSet /). Кроме того, вы можете использовать 'unsigned long int', который, как гарантируется, должен составлять не менее 32 бит. – Maxpm

2

Вам обязательно понадобится использовать shift и OR.

Сначала объявите целочисленный тип без знака нужного размера. Мне нравятся типы C99, определенные в stdint.h, но ваш компилятор C++ может не иметь их. Если у вас нет uint16_t, вы можете использовать unsigned short. Это ширина 16 бит и может содержать 11 бит.

Затем вы выясните, какие биты попадают в высокие бит. Похоже, что это должно быть:

unsigned short ch1 = 0x17; 
unsigned short ch2 = 0x10; 
unsigned short result = (ch1 << 6) | ch2; 
+0

Наибольшее извлечение занимает до 21 бит. Нужен ли мне буфер символов []? – Mark

+0

@Mark, нет, посмотрите эту тему: http://stackoverflow.com/questions/589575/c-size-of-int-long-etc. В соответствии с этим стандарт требует, чтобы 'unsigned long' составлял 32 бита. – juanchopanza

0

1: для объединения их вместе:

char bytes[2] = { 0x17, 0x10 }; // for example 

unsigned short result = 0;  // 00000000 00000000 
result = bytes[0] << 6;   // 101 11000000 
result |= bytes[1];    // 101 11010000 

2: для его печати, как гекса

std::cout << std::showbase << std::hex << <what you want to print>; 

в этом случае:

std::cout << std::showbase << std::hex << result 
// output: 0x5d0 if it is little-endian, it depends on your operating system 
0

Во-первых, от K & R: «Почти все битполы зависят от реализации».

Следующие работы на MS Visual Studio 2008:

#include <stdio.h> 
#include <string.h> 

struct bitbag { 
    unsigned int ch2 : 6; 
    unsigned int ch1 : 6; 
}; 

int main() 
{ 
    struct bitbag bits; 

    memset(&bits, 0, sizeof(bits)); 

    bits.ch1 = 0x17; // 010111 
    bits.ch2 = 0x10; // 010000 

    printf ("0x%06x 0x%06x\n", bits.ch1, bits.ch2); 
    printf ("0x%0x\n", bits); 

    return 0; 
} 

Производит вывод:

0x000017 0x000010 
0x5d0 

Однако я не мог гарантирую, что он будет работать так же, как во всех компиляторах. Обратите внимание на memset, который инициализирует любое дополнение до нуля.

+0

И делать printf на struct ... нет гарантий, которые будут работать. –

+0

Кроме того, для UTF-8 вам понадобятся «переменные битрейты», расположение бит зависит от первого байта. И этого не существует вообще. – MSalters

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