我有一个练习,我必须按照命令行给出的位级别对字符串进行编码和解码。
需要注意的是,我必须使用置换映射来对位进行重新排序。
这是一个例子:
用户输入要编码的字符
H
H的二进制是
01001000
但是,这是8位到0-7的常规映射。
我的程序必须将这些位置换为我使用的任何映射模式。
例如,如果我使用映射64752031
字符'H'的位
01001000
转到
01000001
编码char时,第0位变为第6位,第2位变为第4位,第3位变为第7位,依此类推。不论该映射基于什么。
有没有一种方法可以根据给定的排列图来操纵和更改位的顺序?
谢谢。
答案 0 :(得分:3)
如果您需要处理较大的字符串,最好使用可以预先计算翻译的查找表。
#include <stdio.h>
unsigned char perm[256]; // permutation table
unsigned mapping[8]={6,4,7,5,2,0,3,1};
// assumes 7 6 5 4 3 2 1 0
// => 6 4 7 5 2 0 3 1
void mkperm(unsigned char perm[256]) {
for (int i=0; i<256; i++)
perm[i]=0;
for (int i=0;i<256;i++) {
for (int j=7; j>=0; j--) {
int pos=mapping[7-j]; // at mapping[0] is the new position of bit 7
if (i & (1<<j)) // only considers set bits, the table is previously cleared
perm[i] |= (1<<pos) ;
}
}
}
int main() {
mkperm(perm);
printf("%.2x => %.2x\n",'H',perm['H']);
}
mkperm()
通过扫描每个字符的连续位来计算置换表。如果在char i中设置了一位,我们将在映射表中的位置i上以映射给出的逻辑权重将其设置为1。通过对单元格i的内容正确移位1进行设置。
答案 1 :(得分:1)
使用按位运算符。
这是一个如何将第二位移到第七位的示例:
x |= (x & 1<<1) << 6;
x &= ~(1<<1);
如果我的位编号困扰所有人,对不起。这就是我读取二进制数字的方式。
您还可以将其放入内联函数中:
inline int bit_mode(int *x, int bit1, int bit2)
{
*x |= *x & (1<<(bit1-1)) << (bit2-1);
*x &= ~(1<<(bit1-1));
return *x;
}
int a;
bit_mode(&a, 2, 7);
答案 2 :(得分:1)
只需将位移到正确的位置。经过一番乐趣之后,我想我已经明白了:
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <limits.h>
#include <stdint.h>
/**
* A little helper function
* get the bit number 'as' from the byte 'in'
* and put that bit as the number 'num' in the output
*/
static inline
uint8_t map_get_bit_as(uint8_t in,
uint8_t num, uint8_t as)
{
return (!!(in & (1 << as))) << num;
}
uint8_t map(unsigned long mapping, uint8_t in)
{
// static_assert(CHAR_BIT == 8, "are you insane?");
const int bit0 = mapping / 10000000 % 10;
const int bit1 = mapping / 1000000 % 10;
const int bit2 = mapping / 100000 % 10;
const int bit3 = mapping / 10000 % 10;
const int bit4 = mapping / 1000 % 10;
const int bit5 = mapping / 100 % 10;
const int bit6 = mapping / 10 % 10;
const int bit7 = mapping / 1 % 10;
return
map_get_bit_as(in, 0, bit0) |
map_get_bit_as(in, 1, bit1) |
map_get_bit_as(in, 2, bit2) |
map_get_bit_as(in, 3, bit3) |
map_get_bit_as(in, 4, bit4) |
map_get_bit_as(in, 5, bit5) |
map_get_bit_as(in, 6, bit6) |
map_get_bit_as(in, 7, bit7);
}
int main() {
printf("%#02x %#02x\n\n", 'H', map(64752031, 'H'));
}
将输出:
0x48 0x41
在repl上进行了测试。
答案 3 :(得分:1)
如果我在对它们进行计数时正确理解了位的顺序,那么相应功能可以按照演示程序中所示的方式进行查找。
#include <stdio.h>
#include <limits.h>
#include <stdint.h>
char encode( char c, uint32_t mask )
{
unsigned char result = '\0';
for ( size_t i = 0; i < 2 * sizeof( mask ) ; i++ )
{
uint32_t bit = ( ( ( uint32_t )1 << ( CHAR_BIT - 1 - ( mask & 0xf ) ) ) & c ) != 0;
result |= bit << i;
mask >>= 4;
}
return ( char )result;
}
int main( void )
{
uint32_t mask = 0x64752031;
char c = 'H';
printf( "c = %hhx\n", c );
c = encode( c, mask );
printf( "c = %hhx\n", c );
}
程序输出为
c = 48
c = 41