Advertisement
Guest User

pt_huffman

a guest
Mar 19th, 2021
112
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 6.33 KB | None | 0 0
  1. #include <stdio.h>
  2.  
  3. #define NCHARS 128
  4. #define EOT 4
  5.  
  6. #include <assert.h>
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10.  
  11. typedef struct {
  12.   FILE* fptr;
  13.   int currentBit;
  14.   unsigned char currentByte;
  15. } BitStream;
  16.  
  17. void openWrite(BitStream* bs, char* filename) {
  18.   bs->fptr = fopen(filename, "w");
  19.   bs->currentBit = 0;
  20.   bs->currentByte = 0;
  21. }
  22.  
  23. void openRead(BitStream* bs, char* filename) {
  24.   bs->fptr = fopen(filename, "r");
  25.   bs->currentBit = 0;
  26.   bs->currentByte = 0;
  27. }
  28.  
  29. void closeWrite(BitStream bs) {
  30.   bs.currentByte << 8 - bs.currentBit;
  31.   fputc(bs.currentByte, bs.fptr);
  32.   fclose(bs.fptr);
  33. }
  34.  
  35. void closeRead(BitStream bs) { fclose(bs.fptr); }
  36.  
  37. int readBit(BitStream* bs) {
  38.   if (bs->currentBit == 0) {
  39.     bs->currentByte = fgetc(bs->fptr);
  40.   }
  41.   int result = bs->currentByte & (1 << (7 - bs->currentBit));
  42.   bs->currentBit = (bs->currentBit + 1) % 8;
  43.   return result;
  44. }
  45.  
  46. void writeBit(BitStream* bs, int b) {
  47.   if (b) {
  48.     bs->currentByte = bs->currentByte | (1 << (7 - bs->currentBit));
  49.   }
  50.   bs->currentBit = (bs->currentBit + 1) % 8;
  51.   if (bs->currentBit == 0) {
  52.     fputc(bs->currentByte, bs->fptr);
  53.     bs->currentByte = 0;
  54.   }
  55. }
  56.  
  57. typedef struct node {
  58.   int f;
  59.   char c;
  60.   struct node* links;
  61.   struct node* rechts;
  62. } Node;
  63.  
  64. Node* create(int f, char c) {
  65.   Node* node = (Node* )malloc(sizeof(Node));
  66.   node->f = f;
  67.   node->c = c;
  68.   node->links = NULL;
  69.   node->rechts = NULL;
  70. }
  71.  
  72. Node* destroy(Node* node) {
  73.   if (node != NULL) {
  74.     destroy(node->links);
  75.     destroy(node->rechts);
  76.     free(node);
  77.   }
  78.   return NULL;
  79. }
  80.  
  81. void printBoom(Node* t, int level) {
  82.   if (t == NULL) {
  83.     return;
  84.   }
  85.   printBoom(t->rechts, level + 1);
  86.   for (int i = 0; i < 4 * level; ++i) {
  87.     printf(" ");
  88.   }
  89.   printf("->");
  90.   printf("%c %-3d\n", t->c, t->f);
  91.   printBoom(t->links, level + 1);
  92. }
  93.  
  94. Node* voegSamen(Node* x, Node* y) {
  95.   assert(x != NULL);
  96.   assert(y != NULL);
  97.   assert(x->f <= y->f);
  98.   Node* result = create(x->f + y->f, '\0');
  99.   result->links = x;
  100.   result->rechts = y;
  101. }
  102.  
  103. void merge(Node* a[], int n1, int n2, Node* b[]) {
  104.   for (int i = 0; i < n2; ++i) {
  105.     b[i] = a[i];
  106.   }
  107.   int j = 0;
  108.   int k = n1;
  109.   for (int i = 0; i < n2; ++i) {
  110.     if (j < n1 && (k == n2 || b[j]->f <= b[k]->f)) {
  111.       a[i] = b[j];
  112.       ++j;
  113.     } else {
  114.       a[i] = b[k];
  115.       ++k;
  116.     }
  117.   }
  118. }
  119.  
  120. void mergeSort(Node* a[], int n, Node* b[]) {
  121.   if (n <= 1) {
  122.     return;
  123.   }
  124.   int mid = n / 2;
  125.   mergeSort(&a[0], mid, b);
  126.   mergeSort(&a[mid], n - mid, b);
  127.   merge(a, mid, n, b);
  128. }
  129.  
  130. Node* hoffmanBoom(char a[], int f[], int n) {
  131.   Node* nodes[NCHARS];
  132.   for (int i = 0; i < n; ++i) {
  133.     nodes[i] = create(f[i], a[i]);
  134.   }
  135.  
  136.   Node* tmp[NCHARS];
  137.   mergeSort(nodes, n, tmp);
  138.  
  139.   for (int i = 1; i < n; ++i) {
  140.     nodes[i] = voegSamen(nodes[i - 1], nodes[i]);
  141.     for (int j = i + 1; j < n; ++j) {
  142.       if (nodes[j - 1]->f > nodes[j]->f) {
  143.         Node* tmp = nodes[j];
  144.         nodes[j] = nodes[j - 1];
  145.         nodes[j - 1] = tmp;
  146.       } else {
  147.         break;
  148.       }
  149.     }
  150.   }
  151.  
  152.   return nodes[n - 1];
  153. }
  154.  
  155. int vind(char c, Node* boom, char* code) {
  156.   if (boom == NULL) {
  157.     return 0;
  158.   }
  159.   if (boom->c == c) {
  160.     return 1;
  161.   }
  162.   int n = strlen(code);
  163.   code[n + 1] = '\0';
  164.   code[n] = '1';
  165.   if (vind(c, boom->links, code)) {
  166.     return 1;
  167.   }
  168.   code[n] = '0';
  169.   if (vind(c, boom->rechts, code)) {
  170.     return 1;
  171.   }
  172.   code[n] = '\0';
  173.   return 0;
  174. }
  175.  
  176. int codeer(char* infile, Node* boom, char* outfile) {
  177.   FILE* fptr = fopen(infile, "r");
  178.   BitStream bs;
  179.   openWrite(&bs, outfile);
  180.   char code[NCHARS] = "";
  181.  
  182.   char c = EOF;
  183.   while (c != EOT) {
  184.     c = fgetc(fptr);
  185.     if (c == EOF) {
  186.       c = EOT;
  187.     }
  188.     code[0] = '\0';
  189.     vind(c, boom, code);
  190.     for (int i = 0; i < strlen(code); ++i) {
  191.       writeBit(&bs, code[i] == '1');
  192.     }
  193.   }
  194.   fclose(fptr);
  195.   closeWrite(bs);
  196. }
  197.  
  198. int decodeer(char* infile, Node* root, char* outfile) {
  199.   FILE* fptr = fopen(outfile, "w");
  200.   BitStream bs;
  201.   openRead(&bs, infile);
  202.  
  203.   Node* current = root;
  204.   while (current->c != EOT) {
  205.     current = root;
  206.     while (current->c == '\0') {
  207.       if (readBit(&bs)) {
  208.         current = current->links;
  209.       } else {
  210.         current = current->rechts;
  211.       }
  212.     }
  213.     fprintf(fptr, "%c", current->c);
  214.   }
  215.  
  216.   fclose(fptr);
  217.   closeRead(bs);
  218. }
  219.  
  220. void bewaarFrequenties(char* filename, char* a, int* f, int n) {
  221.   FILE* fptr = fopen(filename, "w");
  222.   for (int i = 0; i < n; ++i) {
  223.     fprintf(fptr, "%c %d\n", a[i], f[i]);
  224.   }
  225.   fclose(fptr);
  226. }
  227.  
  228. void berekenFrequenties(char* filename, char* a, int* f, int* n) {
  229.   int charToFreq[NCHARS];
  230.   for (int c = 0; c < NCHARS; ++c) {
  231.     charToFreq[c] = 0;
  232.   }
  233.  
  234.   charToFreq[EOT] = 1; // last character
  235.  
  236.   FILE* fptr = fopen(filename, "r");
  237.   while (1) {
  238.     char c = fgetc(fptr);
  239.     if (c == EOF) {
  240.       break;
  241.     }
  242.     ++charToFreq[c];
  243.   }
  244.   fclose(fptr);
  245.   assert(charToFreq[EOT] == 1);
  246.  
  247.   int k = 0;
  248.   for (int c = 0; c < NCHARS; ++c) {
  249.     if (charToFreq[c] > 0) {
  250.       a[k] = c;
  251.       f[k] = charToFreq[c];
  252.       ++k;
  253.     }
  254.   }
  255.   *n = k;
  256. }
  257.  
  258. void leesFrequenties(char* filename, char* a, int* f, int* n) {
  259.   FILE* fptr = fopen(filename, "r");
  260.   int k = 0;
  261.   while (1) {
  262.     char c = fgetc(fptr);
  263.     if (c == EOF) {
  264.       break;
  265.     }
  266.     fgetc(fptr); // spatie
  267.     fscanf(fptr, "%d", &f[k]);
  268.     a[k] = c;
  269.     ++k;
  270.     fgetc(fptr); // newline
  271.   }
  272.   fclose(fptr);
  273.   *n = k;
  274. }
  275.  
  276. int main(int argc, char* argv[]) {
  277.   if (argc != 5) {
  278.     fprintf(stderr, "Verkeerde argumenten: ./a.out [codeer/decodeer] "
  279.                     "inputbestand frequentiebestand outputbestand\n");
  280.     return 1;
  281.   }
  282.  
  283.   int doeCodeer = strcmp(argv[1], "decodeer");
  284.   char* input = argv[2];
  285.   char* frequentie = argv[3];
  286.   char* output = argv[4];
  287.  
  288.   char a[NCHARS];
  289.   int f[NCHARS];
  290.   int n = 0;
  291.  
  292.   Node* root = NULL;
  293.  
  294.   if (doeCodeer) {
  295.     printf("coderen...\n");
  296.  
  297.     berekenFrequenties(input, a, f, &n);
  298.     root = hoffmanBoom(a, f, n);
  299.     printBoom(root, 0);
  300.     bewaarFrequenties(frequentie, a, f, n);
  301.  
  302.     codeer(input, root, output);
  303.   } else {
  304.     printf("decoderen...\n");
  305.  
  306.     leesFrequenties(frequentie, a, f, &n);
  307.     root = hoffmanBoom(a, f, n);
  308.     printBoom(root, 0);
  309.     decodeer(input, root, output);
  310.   }
  311.  
  312.   root = destroy(root);
  313.  
  314.   return 0;
  315. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement