IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

amélioration de ma fonction


Sujet :

C++

  1. #1
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2014
    Messages
    36
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2014
    Messages : 36
    Points : 32
    Points
    32
    Par défaut amélioration de ma fonction
    Bonjour à tous,
    j'ai ecrit une fonction qui normalise un caractere diacrité en un caractere standard mais je trouve mon code pas optimisé
    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
     
    /* normalise_char -- fonction qui normalise les caracteres diacrités par leur equivalents non diacrités                       *                            
     * et les caracteres non diacrités par leur forme minuscule                                                                   *
     * parametres : c, caractere à normaliser                                                                                     *
     * retour : le caractere diacrité par son equivalent non diacrité en minuscule ou le caractere non diacrité en minuscule      *
     */
    char normalise_char(char c)
    {
    	// si c'est une caractere diacrité
    	if (estVoyelleDiac_fr(c) || estConsonneDiac_fr(c))
    	{
    		if (c == 'à' || c == 'À' || c == 'â' || c == 'Â') return 'a';
    		else if (c == 'é' || c == 'è' || c == 'ê' || c == 'É' || c == 'È' || c == 'Ê' || c == 'Ë') return 'e';
    		else if (c == 'î' || c == 'ï' || c == 'Î' || c == 'Ï') return 'i';
    		else if (c == 'ô' || c == 'ö' || c == 'Ô' || c == 'Ö') return 'o';
    		else if (c == 'ù' || c == 'û' || c == 'ü' || c == 'Ù' || c == 'Û' || c == 'Ü') return 'u';
    		else if (c == 'ÿ') return 'y';
    		else if (c == 'ç') return 'c';
    		else return c;
    	}
    	// sinon, on retourne le caractère en minuscule
    	else
    	{
    		return tolower(c);
    	}
    }
    Je compte sur vous pour des conseils d’amélioration plutot que plein de conditions et de tests.
    du genre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    if (fonction(c, "éèêë")) return 'e';
    Merci d'avance

  2. #2
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2014
    Messages
    36
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2014
    Messages : 36
    Points : 32
    Points
    32
    Par défaut
    j'ai trouvé

    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
     
    const std::unordered_map<string, char> diacritees({{"àÀâÂ", 'a'}, {"éèêëÉÈÊË", 'e'}, {"îïÎÏ", 'i'}, {"ôöÔÖ", 'o'}, {"ùûüÙÛÜ", 'u'}});
     
    /* normalise_char -- fonction qui normalise les caracteres diacrités par leur equivalents non diacrités                       *                            
     * et les caracteres non diacrités par leur forme minuscule                                                                   *
     * parametres : c, caractere à normaliser                                                                                     *
     * retour : le caractere diacrité par son equivalent non diacrité en minuscule ou le caractere non diacrité en minuscule      *
     */
    char normalise_char(char c)
    {	
    	if (estConsonneDiac_fr(c) || estVoyelleDiac_fr(c))
    	{
    		for (std::pair<string, char> elem : diacritees)
    		{
    			if (elem.first.find(c) != string::npos) return elem.second;
    		}
    		if (c == 'ÿ') return 'y';
    		else if (c == 'ç' || c == 'Ç') return 'c';
    		else return c;
    	}
    	else
    	{
    		if (isalpha(c)) return tolower(c);
    		else return c;
    	}
    }
    Qu'en pensez-vous ?

  3. #3
    Membre expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2011
    Messages
    739
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2011
    Messages : 739
    Points : 3 627
    Points
    3 627
    Par défaut
    Tu entends quoi par optimiser ? Parce qu'avec le second code on part sur de l'allocation dynamique, pas mal de déréférencement et plein de copie... C'est loin d'être optimisé.

    Je vais partir sur le fait que le fichier est enregistré en un encodage bizarre dans la catégorie des ascii étendus (parce que sinon 'é' ne fait pas 1 octet)

    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
    #include <string_view>
    #include <array>
     
    constexpr auto normalise_char_table = []{
      // un tableau de tous les caractères possible
      // l'index n correspond au caractère c de valeur n
      std::array<char, 256> table {};
      for (std::size_t i = 0; i < table.size(); ++i)) {
        tablec[static_cast<unsigned char>(c)] = char(i);
      }
     
      using namespace std::string_view_literals;
      struct P { char c; std::string_view str };
     
      // modification de certaines correspondances
      for (P pair : {
        P{'e', "éè....."sv},
        P{'a', "à....."sv},
        .....
      }) {
        for (char c : pair.str) {
          table[static_cast<unsigned char>(c)] = pair.c;
        }
      }
     
      return table;
    }();
     
    char normalise_char(char c)
    {
      return normalise_char_table[static_cast<unsigned char>(c)];
    }

  4. #4
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2014
    Messages
    36
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2014
    Messages : 36
    Points : 32
    Points
    32
    Par défaut
    Merci jo_link_noir pour ta reponse mais ton code est bcp trop complexe pour moi qui débute. J'ai commencé le c++ il y a un mois.
    Tu pourrais davantage le commenter ? surtout le debut avec constexpr
    Merci beaucoup

  5. #5
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2014
    Messages
    36
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2014
    Messages : 36
    Points : 32
    Points
    32
    Par défaut
    J'essaie de reporduire une indentation de debutant mais je n'y arrrive meme pas.
    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
     
    #include <string_view>
    #include <array>
     
    constexpr auto normalise_char_table = []
    {
    	std::array<char, 256> table {};
    	for (std::size_t i = 0; i < table.size(); ++i)) 
    	{
    		tablec[static_cast<unsigned char>(c)] = char(i);
    	}
    }
     
    using namespace std::string_view_literals;
    struct P { char c; std::string_view str };
     
    // modification de certaines correspondances
    for (P pair : {
        P{'e', "éè....."sv},
        P{'a', "à....."sv},
        .....
    }) 
    {
        for (char c : pair.str) 
        {
        table[static_cast<unsigned char>(c)] = pair.c;
        }
    }
     
    return table;
    }();
     
    char normalise_char(char c)
    {
      return normalise_char_table[static_cast<unsigned char>(c)];
    }

  6. #6
    Membre expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2011
    Messages
    739
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2011
    Messages : 739
    Points : 3 627
    Points
    3 627
    Par défaut
    constexpr est un mot clef pour dire que la variable est une expression déduite à la compilation. C’est-à-dire que tout le traitement effectué pour l’initialiser ne se trouvera pas dans le programme final, seulement le résultat (il y a quelques subtilités, mais c'est grossièrement le fonctionnement).

    Cette variable est initialisée avec le retour d'une lambda ([]{ ... }()) qui est appelé directement. Une lambda est une fonction créée "sur place". https://en.cppreference.com/w/cpp/language/lambda

    auto est un mot clef pour laisser le compilateur déduire le type de la variable plutôt que le marqué soi-même.

    ""sv est un raccourci pour faire une std::string_view (je te laisse regarder la doc) et la boucle est une manière simple de parcourir une séquence de valeur: https://en.cppreference.com/w/cpp/language/range-for

    Après, comme je n'ai pas testé le code, il y a une erreur: tablec[static_cast<unsigned char>(c)] = char(i); devrait être table[static_cast<unsigned char>(i)] = char(i);Si j'enlève la lambda, constexpr, auto et std::string_view, cela donne:

    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
    #include <string_view>
    #include <array>
     
    std::array<char, 256> make_normalise_char_table()
    {
      // un tableau de tous les caractères possible
      // l'index i correspond au caractère c de valeur i
      std::array<char, 256> table {};
      for (std::size_t i = 0; i < table.size(); ++i) {
        table[static_cast<unsigned char>(i)] = char(i);
      }
     
      struct P { char c; char const* str; };
     
      // modification de certaines correspondances
      for (P pair : {
        P{'e', "éè....."},
        P{'a', "à....."},
      }) {
        for (char const* s = pair.str; *s; ++s) {
          table[static_cast<unsigned char>(*s)] = pair.c;
        }
      }
     
      return table;
    }
     
    const std::array<char, 256> normalise_char_table = make_normalise_char_table();
     
    char normalise_char(char c)
    {
      return normalise_char_table[static_cast<unsigned char>(c)];
    }
    Si le code ne compile pas tel quel, c'est que tu utilises un compilateur de 3 ans ou qui n'est pas configuré pour C++17.

  7. #7
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2014
    Messages
    36
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2014
    Messages : 36
    Points : 32
    Points
    32
    Par défaut
    Merci beaucoup jo_link_noir pour toutes ces explications. Effectivement j'étais en c++ 11. J'ai changé et tout fonctionne parfaitement.
    En espérant avoir un jour ton niveau
    Dernière question, vaut-il mieux ici utiliser const char* ou string_view ?

  8. #8
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Si tu veux optimiser une série de if, et surtout la rendre plus lisible et facile à modifier, c'est plutôt vers un switch qu'il faudrait se tourner.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  9. #9
    Membre expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2011
    Messages
    739
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2011
    Messages : 739
    Points : 3 627
    Points
    3 627
    Par défaut
    Le compilateur sait très bien faire la transformation de if vers switch ou de switch vers if, la preuve sur https://godbolt.org/z/narzz9 où ici les 2 codes sont transformés en une comparaison suivit d'une table de saut (les fichiers étant en utf-8, j'ai indiqué les valeurs numériques de cette table). L'avantage du switch ici est surtout la visibilité et les erreurs en cas de variable en double. D'ailleurs, il en manque.

    Ce que je propose est tout autre: aucune comparaison. Simplement lire une valeur dans un tableau de 256 cases préalablement construit (https://godbolt.org/z/xxq43e).

  10. #10
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 630
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 630
    Points : 10 556
    Points
    10 556
    Par défaut
    Citation Envoyé par DoggySmile78 Voir le message
    Je compte sur vous pour des conseils d’amélioration plutot que plein de conditions et de tests.
    après si le nombre de tests te gène, tu peux faire 1 moulinette et ainsi avoir 1 fichier source généré avec ta fonction char normalise_char(char c) que tu n'as plus besoin de regarder dedans (1 fois la moulinette mise en place, elle est sûre à 100%)

    Par exemple, tu fais 1 ficher collation.json (attention à l'encodage des caractères)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    {
    	"collation_list": [{
    			"char": "a",
    			"list": ["à", "À", "â", "Â"],
                            "extra_test": "test1"
    		},
    		{
    			"char": "e",
    			"list": ["é", "è", "ê", "ë", "É", "È", "Ê", "Ë"]
    		}
    	],
            "test1": "estVoyelleDiac_fr(c) || estConsonneDiac_fr(c)"
    }
    Et la moulinette te génère :
    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
    char normalise_char(char c) {
        char ret;
     
        switch(c) {
        case 'à':
        case 'À':
        case 'â':
        case 'Â':
            c = ((estVoyelleDiac_fr(c) || estConsonneDiac_fr(c))? 'a': tolower(c));
            break;
     
        case 'é':
        case 'è':
        case 'ê':
        case 'ë':
        case 'É':
        case 'È':
        case 'Ê':
        case 'Ë':
            c = 'e';
            break;
     
        default: ret = tolower(c); break;
        }
     
        return c;
    }
    Il faut également affiner le truc pour ajouter les tests complémentaires.

    Ensuite, il faut se poser la question de l'encodage : en C/ C++, c'est de l'ASCII, et donc aucuns caractères accentués ou spéciaux.
    La moulinette pourrait replacer tous ces caractères Unicode UTF-8/ UTF-16 et les échapper dans le source généré.

    comme je le disais, le fichier généré peut être très difficile à lire (indentation, répétitions, caractères échappés, ...), mais le but n'est pas de le lire (1 fois la moulinette mise en place, elle est sûre à 100%)

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Amélioration de mon code PHP avec allegement de ma base de données
    Par guillaumeIOB dans le forum PHP & Base de données
    Réponses: 8
    Dernier message: 30/09/2018, 23h31
  2. Réponses: 3
    Dernier message: 29/01/2011, 20h17
  3. Votre avis pour améliorer mon code (opérations matricielles)
    Par Schopenhauer dans le forum Débuter
    Réponses: 42
    Dernier message: 17/09/2010, 19h25
  4. [WD15] Comment améliorer mon code LanceAppli
    Par papydev dans le forum WinDev
    Réponses: 13
    Dernier message: 20/08/2010, 12h17
  5. [Sécurité] Comment amélioré mon code ?
    Par Nadd dans le forum Langage
    Réponses: 14
    Dernier message: 03/03/2006, 20h13

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo