在c中从8位压缩到7位
compressing from 8 bit to 7 in c
我是这个网站的新手,所以我希望这是正确的提问地点。
我的任务是将包含 8 位字符的文本文件压缩为 7 位字符以保存 space 并能够将其还原并解码回 8。因为最后一位始终为 0,这是一个无损压缩(假设我们在 127 之后不使用任何 ascii 字符)
我意识到有一个相对相似的 post (Compress 8 chars in 7 bytes) 但是我采取的方法完全不同,我想知道为什么它不起作用以及如何改进这个想法。
我的压缩思路如下:压缩位[i]应该是i+offset位右移i+1%8,每次i除以8时offset增加1
对于解码部分:新的位[i]应该等于压缩后的位[i]右移i次&~1
如果可以的话,我会上传我的逻辑草图,但代码就足够了。
两者的输出是我写入和读入 f 的文件在此代码之前完成并经过测试
压缩代码:
int offset = 1,size = strlen(f); //f is a char* buffer that I read the whole file to
for(int i = 0; i < size; i++)
{
if(offset%8 == 0)
offset++;
shift_right(f,size,(i+1)%8);
fputc(f[i+offset],output);
}
解码代码:
unsigned char temp;
for (int i = 0; i < actualLen; ++i) //actualLen being the length of the uncompressed file in chars(bytes)
{
temp = f[i]&(~1);
fputc(temp,output);
shift_right(f,actualLen,1); //f is a char* buffer that I read the whole file to
}
右移函数:
void shift_right(unsigned char *ar, int size, int shift)
{//credit to another post here for this function :)
int carry = 0; // Clear the initial carry bit.
while (shift--) { // For each bit to shift ...
for (int i = size - 1; i >= 0; --i) { // For each element of the array from high to low ...
int next = (ar[i] & 1) ? 0x80 : 0; // ... if the low bit is set, set the carry bit.
ar[i] = carry | (ar[i] >> 1); // Shift the element one bit left and addthe old carry.
carry = next; // Remember the old carry for next time.
}
}
}
提前感谢您的帮助:)
压缩意味着写入的输出字节数少于输入字节数。在最简单的层面上,您的程序无法运行,因为它不适合这样做。您遍历文件的所有字节:
for(int i = 0; i < size; i++)
{
尽管您执行了计算,但对于每个输入字节,您...
fputc(f[i+offset],output);
}
这可以实现某种密码,但它总是会为每个输入字节得到一个字节的输出(因此,没有压缩)。
我认为这里存在一个基本的概念错误,因为这个想法...
the compressed bit[i] should be the i+offset bit shifted right by i+1
% 8 when the offset increases by one each time i divides by 8
... 似乎将在 整个输入 上运行的算法描述为位数组,但您已尝试在每个字节上单独实现它。
还有一个可能的次要错误,你说的是右移,但从 bit-array 的角度来看,你似乎实际上想要 左 移,因为我们通常认为二进制数被写成 most-significant 位到最少,并且术语“左移”和“右移”是根据这种表示定义的。左移将位移向 more-significant 位置(== 在 bit-array 视图中移向数组的前面),而 right-shifting 将它们移向相反的方向。如果您根本不提及移动,您的描述实际上会更符合我认为您的想法:
”压缩位[i]应该是输入位[i+offset],其中offset 从 1 开始,每除以 8 就加 1 i > 0."
请注意,除了可能的最后一个字节外,每个输出字节都包含来自两个输入字节的位,并且每个 7 个输出字节块都包含 8 个输入字节的所有位。这是我的实施建议的基础:
- 维护一个 8 字节的输入缓冲区和一个 7 字节的输出缓冲区。
- 一次读取输入 8 个字节,并根据您的方案将它们打包到输出缓冲区的 7 个字节中。
- 将每个完整的 7 字节压缩组作为一个单元输出
- 不要忘记对文件的最后一个块实施适当的处理,它通常不会包含完整的 8 个字节。
我是这个网站的新手,所以我希望这是正确的提问地点。 我的任务是将包含 8 位字符的文本文件压缩为 7 位字符以保存 space 并能够将其还原并解码回 8。因为最后一位始终为 0,这是一个无损压缩(假设我们在 127 之后不使用任何 ascii 字符) 我意识到有一个相对相似的 post (Compress 8 chars in 7 bytes) 但是我采取的方法完全不同,我想知道为什么它不起作用以及如何改进这个想法。
我的压缩思路如下:压缩位[i]应该是i+offset位右移i+1%8,每次i除以8时offset增加1
对于解码部分:新的位[i]应该等于压缩后的位[i]右移i次&~1
如果可以的话,我会上传我的逻辑草图,但代码就足够了。
两者的输出是我写入和读入 f 的文件在此代码之前完成并经过测试
压缩代码:
int offset = 1,size = strlen(f); //f is a char* buffer that I read the whole file to
for(int i = 0; i < size; i++)
{
if(offset%8 == 0)
offset++;
shift_right(f,size,(i+1)%8);
fputc(f[i+offset],output);
}
解码代码:
unsigned char temp;
for (int i = 0; i < actualLen; ++i) //actualLen being the length of the uncompressed file in chars(bytes)
{
temp = f[i]&(~1);
fputc(temp,output);
shift_right(f,actualLen,1); //f is a char* buffer that I read the whole file to
}
右移函数:
void shift_right(unsigned char *ar, int size, int shift)
{//credit to another post here for this function :)
int carry = 0; // Clear the initial carry bit.
while (shift--) { // For each bit to shift ...
for (int i = size - 1; i >= 0; --i) { // For each element of the array from high to low ...
int next = (ar[i] & 1) ? 0x80 : 0; // ... if the low bit is set, set the carry bit.
ar[i] = carry | (ar[i] >> 1); // Shift the element one bit left and addthe old carry.
carry = next; // Remember the old carry for next time.
}
}
}
提前感谢您的帮助:)
压缩意味着写入的输出字节数少于输入字节数。在最简单的层面上,您的程序无法运行,因为它不适合这样做。您遍历文件的所有字节:
for(int i = 0; i < size; i++) {
尽管您执行了计算,但对于每个输入字节,您...
fputc(f[i+offset],output); }
这可以实现某种密码,但它总是会为每个输入字节得到一个字节的输出(因此,没有压缩)。
我认为这里存在一个基本的概念错误,因为这个想法...
the compressed bit[i] should be the i+offset bit shifted right by i+1 % 8 when the offset increases by one each time i divides by 8
... 似乎将在 整个输入 上运行的算法描述为位数组,但您已尝试在每个字节上单独实现它。
还有一个可能的次要错误,你说的是右移,但从 bit-array 的角度来看,你似乎实际上想要 左 移,因为我们通常认为二进制数被写成 most-significant 位到最少,并且术语“左移”和“右移”是根据这种表示定义的。左移将位移向 more-significant 位置(== 在 bit-array 视图中移向数组的前面),而 right-shifting 将它们移向相反的方向。如果您根本不提及移动,您的描述实际上会更符合我认为您的想法:
”压缩位[i]应该是输入位[i+offset],其中offset 从 1 开始,每除以 8 就加 1 i > 0."
请注意,除了可能的最后一个字节外,每个输出字节都包含来自两个输入字节的位,并且每个 7 个输出字节块都包含 8 个输入字节的所有位。这是我的实施建议的基础:
- 维护一个 8 字节的输入缓冲区和一个 7 字节的输出缓冲区。
- 一次读取输入 8 个字节,并根据您的方案将它们打包到输出缓冲区的 7 个字节中。
- 将每个完整的 7 字节压缩组作为一个单元输出
- 不要忘记对文件的最后一个块实施适当的处理,它通常不会包含完整的 8 个字节。