Bonjour a tous,
Je suis en train de lire Clean Code, et me suis essayé a l'écriture d'un code clair, simple et propre.
J'aurai voulu votre aide pour savoir ce que je pourrai encore améliorer au niveau de la clarté ou de l'implémentation. J'ai du mal avec la notion : un niveau d'abstraction par fonction.

Le but du fichier : crypter une string en 0 et en 1 avec l'algorithme de ShannonFano. Vous verez il est très court et pas compliqué, ce qui m'intéresse c'est surtout l'aspect "code"

Voila, je vous remercie d'avance pour votre aide !

Edit, ça sera plus simple de copier le code ici :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
 
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <unordered_map>
#include <unordered_set>
using namespace std;
 
class shannonFano{
 
public:
 
    void afficherTexteOriginal(){
        cout << texteACoder;
    }
    void afficherTexteCode(){
        cout << messageCode;
    }
    void afficherCodesDesCaracteres(){
        for(auto car : caracteresPresents){
            cout << car << " " << codeDuCaractere[car] << endl;
        }
    }
 
    shannonFano(string texteACoder):texteACoder(texteACoder){
        extraireCaracteresDifferents();
        calculerOccurenceDeChaqueCaractere();
        trierCaracteresParOccurencesCroissantes();
        calculerTableauCumulatif();
        calculerLeCodeDeChaqueCaractere();
        calculerLeMessageCode();
    }
 
private:
 
    void extraireCaracteresDifferents(){
        unordered_set<char> dejaVu;
        for(auto caractere : texteACoder)
            dejaVu.insert(caractere);
        caracteresPresents.insert(caracteresPresents.begin(), dejaVu.begin(), dejaVu.end());
    }
 
    void calculerOccurenceDeChaqueCaractere(){
        //initialisation a 0 (necessaire?)
        for(auto caractere : caracteresPresents)
            occurencesDuCaractere[caractere] = 0;
 
        //remplissage
        for(auto caractere : texteACoder)
            occurencesDuCaractere[caractere] += 1;
    }
 
    void trierCaracteresParOccurencesCroissantes(){
        sort(caracteresPresents.begin(), caracteresPresents.end(), comparerCaractereParOccurence(this));
    }
    struct comparerCaractereParOccurence{ //et ordre alphabetique
        shannonFano* s;
        comparerCaractereParOccurence(shannonFano* s) : s(s){}
        bool operator()(const char& a, const char& b){
            if(s->occurencesDuCaractere[a] == s->occurencesDuCaractere[b])
                return a < b;
            else
                return s->occurencesDuCaractere[a] < s->occurencesDuCaractere[b];
        }
    };
 
    void calculerTableauCumulatif(){
        int somme(0);
        for(auto caractere : caracteresPresents){
            somme += occurencesDuCaractere[caractere];
            cumulOccurences.push_back(somme);
        }
    }
 
    void calculerLeCodeDeChaqueCaractere(){
        if(caracteresPresents.size() == 1)
            codeDuCaractere[caracteresPresents.front()].push_back(CODE_GAUCHE);
        else
            calculerLeCodeDeChaqueCaractereEntre(0, (int)caracteresPresents.size()-1);
    }
    void calculerLeCodeDeChaqueCaractereEntre(int debut, int fin){ //fonction recursive
        if(fin <= debut) return;
 
        int indexCoupure = separe2PaquetsOccurencesEgales(debut, fin);
 
        //moitie gauche
        for(int i = debut; i <= indexCoupure-1; ++i)
            codeDuCaractere[caracteresPresents[i]].push_back(CODE_DROITE);
        calculerLeCodeDeChaqueCaractereEntre(debut, indexCoupure-1);
 
        //moitie droite
        for(int i = indexCoupure; i <= fin; ++i)
            codeDuCaractere[caracteresPresents[i]].push_back(CODE_GAUCHE);
        calculerLeCodeDeChaqueCaractereEntre(indexCoupure, fin);
    }
    int  separe2PaquetsOccurencesEgales(int debut, int fin){
        int offset = (cumulOccurences[debut]-1); //il faudrait trouver un meilleur nom...
        int valeurDeSeparation = (cumulOccurences[fin]-offset)/2 + offset;
        int indexCoupure = 0;
        for(indexCoupure = debut; indexCoupure <= fin; ++indexCoupure){
            if(cumulOccurences[indexCoupure] > valeurDeSeparation)
                break;
        }
        return indexCoupure;
    }
 
    void calculerLeMessageCode(){
        for(auto car : texteACoder){
            messageCode.append(codeDuCaractere[car]);
        }
    }
 
 
    //var
 
    static char constexpr CODE_GAUCHE ='0';
    static char constexpr CODE_DROITE ='1';
 
    string texteACoder;
    string messageCode;
    vector<char> caracteresPresents;
    unordered_map<char, int> occurencesDuCaractere;
    unordered_map<char, string> codeDuCaractere;
    vector<int> cumulOccurences;
};
 
int main(int argc, const char * argv[])
{
    cout << "Entrez un texte a coder : ";
    string texte;
    cin >> texte;
 
    shannonFano texteCrypte(texte);
 
    cout << "Le texte : ";
    texteCrypte.afficherTexteOriginal();
    cout << endl;
 
    cout << "Se code en : ";
    texteCrypte.afficherTexteCode();
    cout << endl;
 
    cout << "Avec les clefs suivantes : \n";
    texteCrypte.afficherCodesDesCaracteres();
    cout << endl;
 
    return 0;
}