Advertisement
noler89

Untitled

Apr 14th, 2015
192
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.08 KB | None | 0 0
  1. #include <stdio.h>
  2. #define BITS 12 /* Установка длины кода равной 12, 13 */
  3. #define HASHING_SHIFT BITS-8 /* или 14 битам. */
  4. #define MAX_VALUE (1 << BITS) - 1/* Отметим, что на MS-DOS-машине при */
  5. #define MAX_CODE MAX_VALUE - 1 /* длине кода 14 бит необходимо компи- */
  6. /* лировать, используя large-модель. */
  7. #if BITS == 14
  8. #define TABLE_SIZE 18041 /* Размер таблицы строк должен быть */
  9. #endif /* простым числом, несколько большим, */
  10. #if BITS == 13 /* чем 2**BITS. */
  11. #define TABLE_SIZE 9029
  12. #endif
  13. #if BITS <= 12
  14. #define TABLE_SIZE 5021
  15. #endif
  16.  
  17. void *malloc();
  18. /* Это массив для значений кодов */
  19. int *code_value;
  20. /* Этот массив содержит префиксы кодов */
  21. unsigned int *prefix_code;
  22. /* Этот массив содержит добавочные символы */
  23. unsigned char *append_character;
  24. /* Этот массив содержит декодируемые строки */
  25. unsigned char decode_stack[4000];
  26.  
  27. /*******************************************************************
  28. ** Эта программа получает имя файла из командной строки.
  29. ** Она упаковывает
  30. ** файл, посылая выходной поток в файл test.lzw. Затем распаковывает
  31. ** test.lzw в test.out. Test.out должен быть точной копией исходного
  32. ** файла.
  33. ********************************************************************/
  34.  
  35. main(int argc, char *argv[])
  36. {
  37. FILE *input_file;
  38. FILE *output_file;
  39. FILE *lzw_file;
  40. char input_file_name[81];
  41. /*
  42. ** Эти три буфера необходимы на стадии упаковки.
  43. */
  44. code_value=malloc(TABLE_SIZE*sizeof(unsigned int));
  45. prefix_code=malloc(TABLE_SIZE*sizeof(unsigned int));
  46. append_character=malloc(TABLE_SIZE*sizeof(unsigned char));
  47. if (code_value==NULL || prefix_code==NULL || append_character==NULL)
  48. {
  49. printf("Fatal error allocating table space!\n");
  50. exit();
  51. }
  52.  
  53. /*
  54. ** Получить имя файла, открыть его и открыть выходной lzw-файл.
  55. */
  56. if (argc>1)
  57. strcpy(input_file_name,argv[1]);
  58. else
  59. {
  60. printf("Input file name? ");
  61. scanf("%s",input_file_name);
  62. }
  63. input_file=fopen(input_file_name,"rb");
  64. lzw_file=fopen("test.lzw","wb");
  65. if (input_file==NULL || lzw_file==NULL)
  66. {
  67. printf("Fatal error opening files.\n");
  68. exit();
  69. };
  70. /*
  71. ** Сжатие файла.
  72. */
  73. compress(input_file,lzw_file);
  74. fclose(input_file);
  75. fclose(lzw_file);
  76. free(code_value);
  77. /*
  78. ** Сейчас открыть файлы для распаковки.
  79. */
  80. lzw_file=fopen("test.lzw","rb");
  81. output_file=fopen("test.out","wb");
  82. if (lzw_file==NULL || output_file==NULL)
  83. {
  84. printf("Fatal error opening files.\n");
  85. exit();
  86. };
  87. /*
  88. ** Распаковка файла.
  89. */
  90. expand(lzw_file,output_file);
  91. fclose(lzw_file);
  92. fclose(output_file);
  93. free(prefix_code);
  94. free(append_character);
  95. }
  96.  
  97. /*
  98. ** Процедура сжатия.
  99. */
  100. compress(FILE *input,FILE *output)
  101. {
  102. unsigned int next_code;
  103. unsigned int character;
  104. unsigned int string_code;
  105. unsigned int index;
  106. int i;
  107. next_code=256; /* Next_code - следующий доступный код строки */
  108. for (i=0;i<TABLE_SIZE;i++)/*Очистка таблицы строк перед стартом */
  109. code_value[i]=-1;
  110. i=0;
  111. printf("Compressing...\n");
  112. string_code=getc(input); /* Get the first code*/
  113.  
  114. /*
  115. ** Основной цикл. Он выполняется до тех пор, пока возможно чтение
  116. ** входного потока. Отметим, что он прекращает заполнение таблицы
  117. ** строк после того, как все возможные коды были использованы.
  118. */
  119. while ((character=getc(input)) != (unsigned)EOF)
  120. {
  121. if (++i==1000) /* Печатает * через каждые 1000 */
  122. { /* чтений входных символов (для */
  123. i=0; /* умиротворения зрителя). */
  124. printf("*");
  125. }
  126. /* Смотрит, есть ли строка */
  127. index=find_match(string_code,character);
  128. if (code_value[index] != -1) /* в таблице. Если есть,*/
  129. string_code=code_value[index];/* получает значение кода*/
  130. else /* Если нет, добавляет ее*/
  131. { /* в таблицу. */
  132. if (next_code <= MAX_CODE)
  133. {
  134. code_value[index]=next_code++;
  135. prefix_code[index]=string_code;
  136. append_character[index]=character;
  137. }
  138. output_code(output,string_code);/*Когда обнаруживается, что*/
  139. string_code=character; /*строки нет в таблице, */
  140. } /*выводится последняя строка*/
  141. } /*перед добавлением новой */
  142. /*
  143. ** End of the main loop.
  144. */
  145. output_code(output,string_code); /* Вывод последнего кода */
  146. output_code(output,MAX_VALUE); /* Вывод признака конца потока */
  147. output_code(output,0); /* Очистка буфера вывода */
  148. printf("\n");
  149. }
  150. /*
  151. ** Процедура хэширования. Она пытается найти сопоставление для строки
  152. ** префикс+символ в таблице строк. Если найдено, возвращается индекс.
  153. ** Если нет, то возвращается первый доступный индекс.
  154. */
  155. find_match(int hash_prefix,unsigned int hash_character)
  156. {
  157. int index;
  158. int offset;
  159.  
  160. index = (hash_character << HASHING_SHIFT) ^ hash_prefix;
  161. if (index == 0)
  162. offset = 1;
  163. else
  164. offset = TABLE_SIZE - index;
  165. while (1)
  166. {
  167. if (code_value[index] == -1)
  168. return(index);
  169. if (prefix_code[index]==hash_prefix
  170. &&append_character[index]==hash_character)
  171. return(index);
  172. index -= offset;
  173. if (index < 0)
  174. index += TABLE_SIZE;
  175. }
  176. }
  177.  
  178. /*
  179. ** Процедура распаковки. Она читает файл LZW-формата и распаковывает
  180. ** его в выходной файл.
  181. */
  182. expand(FILE *input,FILE *output)
  183. {
  184. unsigned int next_code;
  185. unsigned int new_code;
  186. unsigned int old_code;
  187. int character;
  188. int counter;
  189. unsigned char *string;
  190. char *decode_string(unsigned char *buffer,unsigned int code);
  191. next_code=256; /* Следующий доступный код. */
  192. counter=0; /* Используется при выводе на экран.*/
  193. printf("Expanding...\n");
  194.  
  195. old_code=input_code(input);/*Читается первый код, инициализируется*/
  196. character=old_code; /* переменная character и посылается первый */
  197. putc(old_code,output); /* код в выходной файл. */
  198. /*
  199. ** Основной цикл распаковки. Читаются коды из LZW-файла до тех пор,
  200. ** пока не встретится специальный код, указывающий на конец данных.
  201. */
  202. while ((new_code=input_code(input)) != (MAX_VALUE))
  203. {
  204. if (++counter==1000) { counter=0; printf("*"); }
  205. /*
  206. ** Проверка кода для специального случая
  207. ** STRING+CHARACTER+STRING+CHARACTER+
  208. ** STRING, когда генерируется неопределенный код.
  209. ** Это заставляет его декодировать последний код,
  210. ** добавив CHARACTER в конец декод. строки.
  211. */
  212. if (new_code>=next_code)
  213. {
  214. *decode_stack=character;
  215. string=decode_string(decode_stack+1,old_code);
  216. }
  217. /*
  218. ** Иначе декодируется новый код.
  219. */
  220. else
  221. string=decode_string(decode_stack,new_code);
  222. /*
  223. ** Выводится декодируемая строка в обратном порядке.
  224. */
  225. character=*string;
  226. while (string >= decode_stack)
  227. putc(*string--,output);
  228. /*
  229. ** Наконец, если возможно, добавляется новый код в таблицу строк.
  230. */
  231. if (next_code <= MAX_CODE)
  232. {
  233. prefix_code[next_code]=old_code;
  234. append_character[next_code]=character;
  235. next_code++;
  236. }
  237. old_code=new_code;
  238. }
  239. printf("\n");
  240. }
  241.  
  242. /*
  243. ** Процедура простого декодирования строки из таблицы строк,
  244. * сохраняющая
  245. ** результат в буфер. Этот буфер потом может быть выведен
  246. ** в обратном порядке программой распаковки.
  247. */
  248. char *decode_string(unsigned char *buffer,unsigned int code)
  249. {
  250. int i;
  251.  
  252. i=0;
  253. while (code > 255)
  254. {
  255. *buffer++ = append_character[code];
  256. code=prefix_code[code];
  257. if (i++>=4094)
  258. {
  259. printf("Fatal error during code expansion.\n");
  260. exit();
  261. }
  262. }
  263. *buffer=code;
  264. return(buffer);
  265. }
  266. /*
  267. ** Следующие две процедуры управляют вводом/выводом кодов
  268. ** переменной длины. Они для ясности написаны чрезвычайно
  269. ** простыми и не очень эффективны.
  270. */
  271. input_code(FILE *input)
  272. {
  273. unsigned int return_value;
  274. static int input_bit_count=0;
  275. static unsigned long input_bit_buffer=0L;
  276. while (input_bit_count <= 24)
  277. {
  278. input_bit_buffer|=(unsigned long)getc(input)<<(24-input_bit_count);
  279. input_bit_count += 8;
  280. }
  281. return_value=input_bit_buffer >> (32-BITS);
  282. input_bit_buffer <<= BITS;
  283. input_bit_count -= BITS;
  284. return(return_value);
  285. }
  286. output_code(FILE *output,unsigned int code)
  287. {
  288. static int output_bit_count=0;
  289. static unsigned long output_bit_buffer=0L;
  290. output_bit_buffer|=(unsigned long)code<<(32-BITS-output_bit_count);
  291. output_bit_count += BITS;
  292. while (output_bit_count >= 8)
  293. {
  294. putc(output_bit_buffer >> 24,output);
  295. output_bit_buffer <<= 8;
  296. output_bit_count -= 8;
  297. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement