#include "common.h" #include "display.h" #include "huftree.h" #include #include #include #include /** * Détermine la profondeur maximale de l'arbre de Huffman donné */ static int _treeDepth(HufTree); /** * Sous-fonction pour l'affichage récursif d'un arbre de Huffman */ static void _subPrintTree(HufTree, wchar_t*, int); /** * Transforme le caractère donné en espace s'il est non-imprimable * ou le laisse tel quel sinon */ static char _safeChar(char input); // Drapeau pour l'affichage verbeux ou non-verbeux static int is_verbose = FALSE; void printVerbose(const char* format, ...) { if (is_verbose) { va_list args_list; va_start(args_list, format); vfprintf(stderr, format, args_list); va_end(args_list); } } void setVerbose(int flag) { is_verbose = flag; } int isVerbose() { return is_verbose; } void printTree(HufTree tree) { if (tree == NULL) { // Cas particulier : arbre vide printVerbose("(Arbre vide.)\n"); } else { // Allocation d'un tampon suffisamment grand pour contenir // les indentations des sommets les plus profonds de l'arbre wchar_t* buffer = malloc(_treeDepth(tree) * 4 * sizeof(*buffer)); _subPrintTree(tree, buffer, 0); free(buffer); } } void _subPrintTree(HufTree tree, wchar_t* buffer, int length) { if (tree->child_l != NULL && tree->child_r != NULL) { // Affichage d'un sommet avec enfants, on montre // la probabilité somme des enfants printVerbose("■\n"); // Affichage du fils gauche. Augmentation du préfixe // pour l'affichage des enfants du fils gauche buffer[length] = '\0'; printVerbose("%ls├── ", buffer); buffer[length] = L'│'; buffer[length + 1] = ' '; buffer[length + 2] = ' '; buffer[length + 3] = ' '; buffer[length + 4] = '\0'; _subPrintTree(tree->child_l, buffer, length + 4); // Affichage du fils droite. Augmentation du préfixe // pour l'affichage des enfants du fils droit buffer[length] = '\0'; printVerbose("%ls└── ", buffer); buffer[length] = ' '; _subPrintTree(tree->child_r, buffer, length + 4); } else { // Affichage d'une feuille de l'arbre, correspondant // à un caractère du corpus printVerbose("%c\n", _safeChar(tree->value)); } } int _treeDepth(HufTree tree) { if (tree->child_l != NULL && tree->child_r != NULL) { int left = _treeDepth(tree->child_l); int right = _treeDepth(tree->child_r); return (left > right ? left : right) + 1; } else { return 1; } } void printCountsTable(bytecount* table, bytecount total, size_t size) { printVerbose("┌─┬────┬────────┐\n"); printVerbose("│C│code│effectif│\n"); printVerbose("├─┼────┼────────┤\n"); for (size_t i = 0; i < size; i++) { if (table[i] != 0) { printVerbose("│%c│%4d│%8llu│\n", _safeChar(i), (int) i, table[i]); } } printVerbose("├─┴────┼────────┤\n"); printVerbose("│ Total│%8llu│\n", total); printVerbose("└──────┴────────┘\n"); } void printLabelsTable(char** table, size_t size) { printVerbose("┌─┬────┬────────────────┐\n"); printVerbose("│C│code│ étiquette│\n"); printVerbose("├─┼────┼────────────────┤\n"); double total_length = 0; size_t label_count = 0; for (size_t i = 0; i < size; i++) { if (table[i] != 0) { printVerbose("│%c│%4d│%16s│\n", _safeChar(i), (int) i, table[i]); total_length += strlen(table[i]); label_count++; } } printVerbose("├─┴────┴───┬────────────┤\n"); printVerbose("│Long. moy.│%12.4lf│\n", total_length / label_count); printVerbose("└──────────┴────────────┘\n"); } char _safeChar(char input) { if (input < 32 || input == 127) { return ' '; } return input; }