转自http://shijuanfeng.blogbus.com/logs/162678019.html
以下程序是一个信息编码的程序,阅读其encode部分,并补全其decode部分
最后运行程序,会打印出的一句话。这句话就是我们要求的答案。
注意!这句话是用GBK编码的!
- //#include "stdafx.h"
- #include<iostream>
- typedef unsigned char uint8_t;
- typedef unsigned int uint32_t;
- /*解题思路:须知:1. & 即保留位为1的位。2. ^可逆。即 a^b^a = b。3. << 左移几位,就在后面补几个零,高位在结果中被丢弃; 右移同样*/
- int encode(const void* raw_in, void* raw_out, uint32_t password, size_t len)
- {
- const uint8_t* in = (const uint8_t*)raw_in;
- uint8_t* out = (uint8_t*)raw_out;
- uint32_t seed = password ^ 0x99a43ceeu;
- for (size_t i = 0 ; i < len; ++i)
- {
- // 将in的1-8位与seed第1-8位异或,然后右移5位,得到一个8位,1-7位为a。
- uint8_t a = ( in[i] ^ seed ) >> 5;
- // 将in左移13位(低位的13位均为0)的1-8位与seed第1-8位异或,然后右移10位,得到一个8位,1-7位为b。
- uint8_t b = ( ( ((uint32_t)in[i]) << 13 ) ^ seed ) >> (13-3);
- // 与7 ,此时a变成了 0000 0xxx
- a &= 7;
- // 与248 ,此时b变成了 xxxx x000
- b &= 248;
- // b << 3 得到 xx00 0000; 与a异或,得到xx00 0xxx;与7按位与,0000 0xxx ;
- // 换言之,这句话没用,忽悠人的
- a = 7 & ( a ^ (b << 3));
- // out 为 xxxx x xxx ;前5位由b决定,后3位由a决定
- out[i] = a | b;
- // 更新seed
- seed = (seed * 144123481 ^ seed ^ out[i]);
- }
- return 0;
- }
- int decode(const void* raw_in, void* raw_out, uint32_t password, size_t len)
- {
- const uint8_t* in = (const uint8_t*)raw_in;
- uint8_t* out = (uint8_t*)raw_out;
- uint32_t seed = password ^ 0x99a43ceeu;
- for (size_t i = 0 ; i < len; ++i)
- {
- // 请在此处补全代码//////////////////////////////////////////
- // 取出后三位,即前5位
- uint8_t a = in[i] & 7;
- uint8_t b = in[i] & 248;
- // a = ( in[i] ^ seed ) >> 5; 的逆过程
- // a 左移5位,变成xxx0 0000; 异或 seed的前3位,得到的结果为xxxx xxxx; 再位与224,得到xxx0 0000
- a=((a<<5)^seed) & 224;
- // uint8_t b = ( ( ((uint32_t)in[i]) << 13 ) ^ seed ) >> (13-3); 的逆过程
- // b : 0000 0000 0000 0000 0000 0000 XXXX X000 左移10位,变成0000 0000 0000 00XX XXX0 0000 0000 0000;
- // 然后 异或seed,xxxx xxxx xxxx xxXX XXXx xxxx xxxx xxxx
- // 再 右移13位 0000 0000 0000 0xxx xxxx xxxx xxxX XXXX
- // 位与31 得到 0000 0000 0000 0000 0000 0000 000X XXXX
- // 因此b = 000X XXXX
- b=(((((uint32_t)b) << 10)^seed)>>13) & 31;
- out[i] = a | b; // in 和out 反一下就好了
- seed = (seed * 144123481 ^ seed ^ in[i]);
- }
- return 0;}
- int main()
- {
- const uint8_t buf1[] = {0x46, 0x5c, 0x22, 0x2b, 0xa2, 0x88, 0x09, 0x15, 0x4f, 0x0c, 0x62,
- 0x29, 0x12, 0x03, 0xcd, 0x84, 0xe4, 0xa7, 0xc3, 0x67, 0x00, 0x20, 0xba, 0x60, 0x6e,
- 0x21, 0xf6, 0xb0, 0x71, 0x4d, 0x75, 0xea, 0x1e, 0xdd, 0x4a, 0x28, 0x32, 0x6d, 0x20,
- 0x5c, 0x5a, 0x91, 0xd2, 0xd9, 0xc8, 0xcb, 0x8b, 0x53, 0x30, 0xab, 0x01, 0x8d, 0xf4,
- 0x35, 0x4e, 0xc5, 0x26, 0xaa, 0x95, 0x99, };
- uint8_t buf2[100] = {};
- const uint32_t password = 0x7c8448e8u;
- const size_t len = sizeof(buf1);
- decode(buf1, buf2, password, len);
- printf("%s\n", buf2);
- }
输出结果:
ASCII码用一个字节(最左边位为0)表示一个英文字符,范围0---127
汉字用GBK编码。两个字节(共16位二进制)表示,两个字节的首位都是“1”。这种汉字编码最多可以表示128*128个汉字