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 :

Préférences de codages (syntaxe)


Sujet :

C++

  1. #1
    Membre chevronné Avatar de mess-mate
    Inscrit en
    Septembre 2008
    Messages
    352
    Détails du profil
    Informations forums :
    Inscription : Septembre 2008
    Messages : 352
    Par défaut Préférences de codages (syntaxe)
    Bonjour, est-ce qu'il y a un style de code, syntaxe, à préférencer ?

    J'ai une paire de fonctions dont je viens ( avec les suggestions des membres) de faire 4 versions différentes avec ou sans la STL ou un mélange, avec plus ou moins la même longueur de codage.

  2. #2
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Par défaut
    Si tu ne nous donnes pas les 4 versions, on va être bien en mal de te dire celle qu'on préfère.

  3. #3
    Membre chevronné Avatar de mess-mate
    Inscrit en
    Septembre 2008
    Messages
    352
    Détails du profil
    Informations forums :
    Inscription : Septembre 2008
    Messages : 352
    Par défaut
    Du temps du C j'introduisais des fonctions en assembleur pour rendre l'application plus rapide.
    1. Maintenant avec le C++ et toutes ces bibliothèques en plus, je me demandais tout simplement si une manière de programmer et le code pouvait avoir une influence positive lors de l'exécution du programme.
    2. Si c'est le cas, comment ou vers quoi s'orienter le mieux ?

  4. #4
    Membre chevronné Avatar de mess-mate
    Inscrit en
    Septembre 2008
    Messages
    352
    Détails du profil
    Informations forums :
    Inscription : Septembre 2008
    Messages : 352
    Par défaut
    Citation Envoyé par loufoque Voir le message
    Si tu ne nous donne pas les 4 versions, on va être bien en mal de te dire celle qu'on préfère.
    Ok, je vais mettre cela au propre ( se sont des tests ).

  5. #5
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut,

    Si j'ai bien compris ta question, je crois que la réponse devrait être:
    Vu la qualité des compilateur (aussi bien C que C++) actuels, la première qualité du code devrait être la facilité de lecture (pour l'humain qui le lit/le modifie)
    Le tout en gardant à l'esprit d'essayer de fournir l'algorithme le plus efficace possible, cela va de soi

    En effet, il est important de garder en mémoire le fait que
    Dans, mettons, 90% des cas, une optimisation prématurée est la route de toutes les enfers
    lorsque l'on en vient à utiliser un "sucre syntaxique" dans le but (qu'il soit imaginaire ou réel) de gagner quelque cycles d'horloge.

    Pour que tu comprenne bien l'idée, le fait d'améliorer ton algorithme pour qu'il travaille selon une logique en O(log(n)) plutôt que selon une logique en O(n) est une bonne chose, et fait partie des optimisations qu'il ne faut pas éviter à apporter.

    Par contre, le fait "d'utiliser un sucre syntaxique" (de partir de l'idée qu'une syntaxe donnée est plus efficace que d'autre en terme de cycles d'horloge nécessaires pour effectuer la commande), ou de rendre une méthode inline (par exemple) fait partie de ces "optimisations prématurées" qu'il faut éviter, jusqu'à ce que le profiling de l'application te démontre qu'il est effectivement opportun d'y recourir.

    Ne serait-ce parce que le premier principe que tout codeur ne devrait jamais perdre de vue, c'est que
    un code est plus souvent lu / étudié qu'il n'est écrit / compilé
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  6. #6
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Par défaut
    L'assembleur ne te permettra pas vraiment d'aller plus vite non.
    C'est à utiliser uniquement si le profiling montre que le compilateur ne génère pas du code optimal par rapport à ton besoin (ce qui semble très peu probable...).
    L'assembleur reste utile pour programmer des routines non disponibles en C ou en C++ (changement de contexte, instructions atomiques, etc.) sauf que y'a des chances que ton compilateur ou environnement fournisse déjà ce genre de choses...

    Les manières de coder en C++ permettent généralement de combiner robuste, efficacité, généricité et élégance, contrairement à d'autres langages où on s'intéresse juste à la concision, qui est une forme d'élégance.

    Les éléments centraux de programmation en C++ sont (liste non exhaustive) :
    - Les notions de propriété, propriété partagée, propriété partagée faible, vue et leur utilisation via le paradigme RAII
    - Les invariants que fournit un objet et l'ensemble de ses états possibles
    - La modélisation d'objets sous forme de valeurs copiables, assignables et déplaçables ou non, en fonction de ce qui a du sens.
    - Les notions de mutabilité et de const-correctness.

    Si tu maîtrises ça, déjà, tu as le potentiel d'écrire du code acceptable.
    Si ces éléments ne sont pas gérés de manière satisfaisante, pour moi, le code est à jeter. En particulier, le RAII est la seule manière vraiment utilisable pour écrire du code exception-safe, et les exceptions est généralement le seul moyen acceptable pour initialiser un objet satisfaisant certains invariants.
    Le code const-correct permet de différencier les accès en lecture et les accès en écriture, ce qui permet d'augmenter la robustesse du code en évitant les écritures là où ça n'a pas de sens. Ça peut aussi servir pour la programmation multi-threadée, si tu choisis de satisfaire que toute opération constante puisse être executée de manière concurrente.

    À noter que la première notion est la plus importante et que celle qui a le plus de mal à rentrer.
    En gros, si tu utilises des pointeurs résultats de new, il y a de fortes chances que ce ne soit pas bon. Si tu utilises des delete ailleurs que dans un destructeur, c'est quasi-sûr.

    Une fois que tu gères ça, tu peux commencer à songer à écrire du code générique de manière pertinente (en utilisant l'une ou l'autre des formes du polymorphisme) pour éviter la redondance de code.
    Le mécanisme de templates peut en particulier permettre la généralisation sans aucun coût en performance. Mettre en place des abstractions à haute performance est cependant tout un art de conception.

  7. #7
    Membre chevronné Avatar de mess-mate
    Inscrit en
    Septembre 2008
    Messages
    352
    Détails du profil
    Informations forums :
    Inscription : Septembre 2008
    Messages : 352
    Par défaut
    Merci pour les conseils, j'y tiendrais compte.

    Voici donc les diverses versions. Laquelle est la meilleure ?
    Il s'agit d'un test pour converser un nombre décimal en binaire de test pour faire évoluer vers du double et float.

    Convert décimal vers binaire, dec2bin:
    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
     
    #include <stdio.h>
    extern char s[];
    int x = 0;
    void conv_dec2bin(int n)
    {
    if (n >= 1) {
        if ( n % 2 == 0 )
            s[x]='0';
        else
            s[x]='1';
            x++;
            conv_dec2bin(n/2);
        }
    printf("%d",n%2);   // get it from the stack
    }
    Idem version 2:
    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
     
    #include <iostream>
    #include <c++/4.3/vector>
    #include <c++/4.3/numeric>
    #include <c++/4.3/algorithm>
    using std::cout;
    using std::endl;
    std::vector<char> table1; // empty char table
    int x = 0;
    void conv_dec2bin_vec(int n)
    {
    if (n >= 1) {
        if ( n % 2 == 0 )
            table1.push_back('0');
        else
            table1.push_back('1');
            x++;
            conv_dec2bin_vec(n/2);
        }
    printf("%d",n%2);  // output from the stack
    }
    Les inverseurs de char (pour les bits) :
    version 1 :
    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
     
    #include <iostream>
    #include <string>
    #include <cstring>
    using std::cout;
    using std::endl;
    using std::string;
    string charev_array2str (char *s)
    {
    int z=0;
    int y = strlen(s);
    string str2;
    while ( y >= 0 ) {
        str2+=s[y];
        y--; z++;
        }
    return str2;
    }
    version 2:
    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
     
    #include <iostream>
    #include <string>
    #include <cstring>
    using std::cout;
    using std::endl;
    extern char s[];
    void charev_array2str2(std::string str)
    {
    int z=0;
    unsigned q;
    char *bufstr;
    // create buf --> reverse
        size_t size = str.size();
        z=size-1;
        bufstr = new char[ size ];
        for ( q=0; q < size; q++) {
            bufstr[q]=str[z];
            z--;
        }
    cout << " bufstr = " << bufstr << endl;
    //delete [] bufstr;   ???
    }
    version 3 :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    #include <string>
    #include <algorithm> //  std::reverse()
    void charev_str(std::string str)
    {
    std::reverse(str.begin(), str.end());   // reverse ss
    }
    Version 4:
    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
     
    #include <iostream>
    #include <c++/4.3/vector>
    #include <c++/4.3/numeric>
    #include <c++/4.3/algorithm>
    using std::cout;
    using std::endl;
    std::vector<char> table1; // empty char table
    void charev_vec1(  )
    {
    char *arry = new char [table1.size() +1];
    int ii = table1.size();
    cout << " ii = " << ii << endl;
    for( unsigned int i = 0; i < table1.size(); i++ )
        arry[i]= table1[i];
    cout << arry << " = the new array " << endl;
    }
    Et un main pour le test :
    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
     
    #include <stdio.h>
    #include <iostream>
    #include <string>
    #include <cstring>
    using std::cout;
    using std::endl;
    using std::cin;
    using std::string;
    char s[20];
    void conv_dec2bin(int);
    string charev_array2str (char *);
    int main(void)
    {
    int n;
    cout << "Dec nbr to convert to bin :  ";
    cin >> n ;
    conv_dec2bin(n);
    cout << " = printf output from the stack = good order !" << endl;
    cout << s << " = bin output to s" << endl;
    string ss=charev_array2str(s);
    cout << ss << " = reversed output of ss (good order). " << endl;
    }
    L'ordre dont il est question est celui comme il est stocké en mémoire ou en fichier.

  8. #8
    Membre chevronné Avatar de mess-mate
    Inscrit en
    Septembre 2008
    Messages
    352
    Détails du profil
    Informations forums :
    Inscription : Septembre 2008
    Messages : 352
    Par défaut
    En tenant compte des suggestions de loufoque et de koala01, cela m'aiderais pour le futur.

    C'est un avis personnel que je demande quel qu'il soit qui me mettra sur la bonne voie pour le futur.

  9. #9
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    A vrai dire, la "meilleure" solution serait de l'ordre de
    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
    #include <string>
    #include <bitset>
    #include <sstream>
    #include <iostream>
    std::string dec2bin(int i)
    {
        std::bitset<32> tab(i);
        std::stringstream ss;
        ss<<tab;
        std::string ret;
        ss>>ret;
        return ret;
    }
    int main()
    {
        std::cout<<dec2bin(10);
        return 0;
    }
    [edit] l'une des adaptations possibles pourrait être
    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
    #include <string>
    #include <bitset>
    #include <sstream>
    #include <iostream>
    template<typename T>
    std::string dec2bin(T t)
    {
        std::bitset<sizeof(T)*8> tab(t);
        std::stringstream ss;
        ss<<tab;
        std::string ret;
        ss>>ret;
        return ret;
    }
    int main()
    {
        std::cout<<"pour un 'char' :"<<dec2bin((char)10)<<std::endl
                 <<"pour un 'short' :"<<dec2bin((short)10)<<std::endl
                 <<"pour un 'int' :"<<dec2bin((int)10)<<std::endl
                 <<"pour un 'long' :"<<dec2bin((long)10)<<std::endl
                 <<"pour un 'long long' :"<<dec2bin((long long)10)<<std::endl;
        return 0;
    }
    C'est si facile
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  10. #10
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Par défaut
    Le truc, pour dec2bin, c'est que tu connais à l'avance la taille maximale dont tu vas avoir besoin.
    Toutes les solutions autres que la première que tu as donnée vont allouer dynamiquement de la mémoire, ce qui peut être considéré comme dommage, mais c'est vrai que ça permet d'avoir une interface bien plus simple à manipuler.
    Tu peux éventuellement retourner un std::array<char, std::numeric_limits<T>::digits10 + 3>, mais c'est pas très pratique pour l'appelant.
    Retourner une std::string semble être un compromis intéressant. Sinon, la manière propre de permettre à l'appelant de fournir le buffer, c'est d'utiliser les output iterators. L'appelant peut alors soit s'embêter à calculer la bonne taille, soit utiliser un conteneur dynamique et std::back_inserter.

    Tes trucs pour inverser des chaînes, c'est tous des horreurs. T'alloues même de la mémoire que tu libères pas.
    La solution 3 n'a même aucun effet, puisque tu modifies un argument passé par valeur, donc tu modifies une copie temporaire...
    Pour inverser, le mieux, c'est
    - soit appliquer un algorithme en-place de manière immédiate si c'est vraiment ce qu'on veut (rarement le cas), comme std::reverse ou mieux (n'alloue pas de mémoire, temps linéaire, modifie la séquence originale)
    - soit un adapteur d'itérateurs ou de séquence pour appliquer l'inversion de manière paresseuse au fur et à mesure qu'on itère, ce qui se fait en temps constant, ne nécessite aucune allocation, et ne modifie pas la séquence originale. (std::reverse_iterator ou mieux)

    Tenir également compte de ma remarque, à savoir : pas de variables globales, te sera aussi très utile pour le futur.
    Il y a des cas où les variables globales sont utiles, typiquement quand on veut réellement partager quelque chose dans l'ensemble du programme, mais là en effet, ça n'a aucun sens, il faut s'en débarrasser;

  11. #11
    Membre chevronné Avatar de mess-mate
    Inscrit en
    Septembre 2008
    Messages
    352
    Détails du profil
    Informations forums :
    Inscription : Septembre 2008
    Messages : 352
    Par défaut
    Merci beaucoup pour les excellentes pistes et conseils ainsi que les exemples qui parlent pour elles-mêmes.
    Du très haut niveau !
    J'ai encore pas mal de chemin à parcourir.

    Je vais maintenant essayer de faire de même pour des nombres négatif et des doubles.

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

Discussions similaires

  1. [Syntaxe] Action simultanée sur plusieurs élements
    Par FranT dans le forum Composants VCL
    Réponses: 2
    Dernier message: 20/03/2003, 20h20
  2. Syntaxe TASM <-> MASM
    Par LFC dans le forum Assembleur
    Réponses: 3
    Dernier message: 28/02/2003, 15h56
  3. [Accents - XML] Problème de codage non supporté !!
    Par Smortex dans le forum Composants VCL
    Réponses: 6
    Dernier message: 24/11/2002, 11h00
  4. [VB6] [Syntaxe] Fonction renvoyant un tableau d'objets
    Par Troopers dans le forum VB 6 et antérieur
    Réponses: 2
    Dernier message: 18/10/2002, 15h33
  5. codage objet
    Par charly dans le forum Algorithmes et structures de données
    Réponses: 18
    Dernier message: 22/08/2002, 16h49

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