148 lines
4.3 KiB
C
148 lines
4.3 KiB
C
#include "common.h"
|
|
#include "display.h"
|
|
#include "huftree.h"
|
|
|
|
#include <stdarg.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <locale.h>
|
|
|
|
/**
|
|
* 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;
|
|
}
|