【发布时间】:2013-02-26 02:18:49
【问题描述】:
新手警告。
我正在尝试创建一个压缩程序。它以一个带有 ASCII 字符的 .txt 作为参数,并切断每个字符的二进制表示的前导 0。
它通过使用两个不同整数的最后 2 个字节来做到这一点。带前导零的字符被放入整数“write”的第 4 个字节,下一个字符被放入整数“temp”的第 3 个字节。然后将'temp' int 向右移动一次,然后与'write' 进行或运算,这样前导零槽就被我们需要的数据填充了。这重复,移位计数器在每个字符后增加。第一种情况有点奇怪。如果写在纸上,算法并不是很复杂。
我觉得我已经尝试了一切。我已经研究过算法很多次了。我很确定问题出在 shift_counter 达到 8 .. 但它应该可以正常工作。它只是没有。我可以在这里告诉你原因(代码在下面):
这是我输出的十六进制转储:
0000000 3f 00 00 00 41 10 68 9e 6e c3 d9 65 10 88 5e c6
0000020 d3 41 e6 74 9a 5d 06 d1 df a0 7a 7d 5e 06 a5 dd
0000040 20 3a bd 3c a7 a7 dd 67 10 e8 5d a7 83 e8 e8 72
0000060 19 a4 c7 c9 6e a0 f1 f8 dd 86 cb cb f3 f9 3c
0000077
以及正确的输出:
0000000 3f 00 00 00 41 d0 3c dd 86 b3 cb 20 7a 19 4f 07
0000020 99 d3 ec 32 88 fe 06 d5 e7 65 50 da 0d a2 97 e7
0000040 f4 b4 fb 0c 7a d7 e9 20 3a ba 0c d2 e3 64 37 d0
0000060 f8 dd 86 cb cb f3 79 fa ed 76 29 00 0a 0a
0000076
代码:
int compress(char *filename_ptr){
int in_fd;
in_fd = open(filename_ptr, O_RDONLY);
//set pointer to the end of the file, find file size, then reset position
//by closing/opening
unsigned int file_bytes = lseek(in_fd, 0, SEEK_END);
close(in_fd);
in_fd = open(filename_ptr, O_RDONLY);
//store file contents in buffer
unsigned char read_buffer[file_bytes];
read(in_fd, read_buffer, file_bytes);
//file where the output will be stored
int out_fd;
creat("output.txt", 0644);
out_fd = open("output.txt", O_WRONLY);
//sets file size in header (needed for decompression, this is the size of the
//file before compression. everything after this we write this 4-byte int
//is a 1 byte char
write(out_fd, &file_bytes, 4);
unsigned int writer;
unsigned int temp;
unsigned char out_char;
int i;
int shift_count = 8;
for(i = 0; i < file_bytes; i++){
if(shift_count == 8){
writer = read_buffer[i];
temp = temp & 0x00000000;
temp = read_buffer[i+1] << 8;
shift_count = 1;
}else{
//moves the next char's bits to the left, for the purpose of filling the
//8 bit buffer (writer) via OR operation
temp = read_buffer[i] << 8;
}
temp = temp >> shift_count;
writer = writer | temp;
//output right byte of writer
unsigned int right_byte = writer & 0x000000ff;
//output right_byte as a char
out_char = (char) right_byte;
//write_buffer[i] = out_char;
write(out_fd, &out_char, 1);
//clear right side of writer
writer = writer & 0x0000ff00;
//shift left side of writer to the right by 8
writer = writer >> 8;
shift_count++;
}
return 0;
}
【问题讨论】:
-
这将为您节省最多 1 / 8(即 12.5%)的费用,并且仅适用于文本。
-
temp = temp & 0x00000000;看起来像是对temp = 0;的过早优化。为什么不让编译器为您执行这些微优化?如果它可以执行更复杂的优化(例如消除死代码),您不认为它足够聪明吗?temp = read_buffer[i] << 8;看起来像未定义的行为。有关详细信息,请参阅 Alexandre 的链接。 -
假设
out_char = (char) right_byte;要引发一个实现定义的计算信号,表明char不能表示right_byte的值...假设实现定义的默认信号处理程序要忽略信号。根据第 7.14.1.1 节,C 标准的第 2 点,这种实现定义的行为序列将使您陷入未定义的行为领域。 -
stackoverflow.com/questions/5201571/… 讨论了相同的“z827 ASCII 压缩”系统。
标签: c algorithm compression bit-manipulation