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 :

Extraire caractères fichier .txt


Sujet :

C++

  1. #1
    Futur Membre du Club
    Homme Profil pro
    INSA Centre Val de Loire
    Inscrit en
    Mars 2017
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 27
    Localisation : France, Dordogne (Aquitaine)

    Informations professionnelles :
    Activité : INSA Centre Val de Loire

    Informations forums :
    Inscription : Mars 2017
    Messages : 8
    Points : 6
    Points
    6
    Par défaut Extraire caractères fichier .txt
    Bonjour,
    J'ai un fichier texte :
    6 4
    ######
    # ##
    # # #
    ######
    Et je dois récupérer le premier et le deuxième chiffre dans deux variables.

    J'ai fais ceci, c'est un peu laborieux mais, je n'arrive pas à utiliser l’opérateur "<<".
    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
     
        const string Nom_fichier="./terrain.txt";
        string ligneCourante;//Chaine de caractère qui contien le ligne actuelle
        ifstream fichier;// Création du fichier
     
        fichier.open(Nom_fichier.c_str());//Ouverture du fichier
        if(!fichier.is_open())//Vérification de 'louverture du fichier
        {
            cout<<"Impossible d'ouvrir le fichier"<<endl;
            return false;
        }
     
        getline(fichier, ligneCourante);
     
        size_t posSuivante = 0, pos=0;//Variable ressortant la position de l'espace
        bool Fin_de_la_ligne = false;//Si on a atteint la fin de la ligne
     
        vector <string> champs;//Création du tableau qui contiendra les paramètres récupéré
     
        while(!Fin_de_la_ligne)
        {
            posSuivante=ligneCourante.find(' ', pos);
            if(posSuivante!=string::npos)
            {
                champs.push_back(ligneCourante.substr(pos, posSuivante-pos));
                pos=posSuivante+1;
            }
            else
            {
                champs.push_back(ligneCourante.substr(pos, string::npos));
                Fin_de_la_ligne=true;
            }
        }
        largeur = atoi(champs[0].c_str());
        hauteur = atoi(champs[1].c_str());
    Ça fonctionne mais je sais qu'il existe un moyen de le faire en deux trois lignes.

    Ensuite, j'aimerais récupérer caractère par caractère et ligne par ligne pour créer une grille de jeu :
    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
    ///Création du terrain
        char **terrain_defaut;
        terrain_defaut= new char*[hauteur];
        for(unsigned int i = 0; i < largeur; i++)
        {
            terrain_defaut[i] = new char[largeur];
        }
     
        terrain = new Case[largeur*hauteur];
     
        for(y=0;y<hauteur;++y)
    	for(x=0;x<largeur;++x)
                if (terrain_defaut[y][x]=='#')//#, c'est le caractère a récupérer
                    terrain[y*largeur+x] = MUR;
                else
                    terrain[y*largeur+x] = VIDE;
    Merci d'avance.

  2. #2
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 611
    Points
    30 611
    Par défaut
    Salut,

    Déjà, avant même de t'intéresser à la manière de récupérer les données de ton terrain depuis un fichier, il faut corriger de toute urgence ta notion de terrain (d'autant plus que ton deuxième code est non seulement buggé, mais aussi totalement faux ) :

    En C++, on a pour principe de n'avoir recours aux pointeurs et à l'allocation dynamique de la mémoire que si l'on n'a absolument pas d'autre solution. Alors, tu penses, les pointeurs de pointeurs, c'est pas demain la veille du jour qui verra qu'on les accepte

    Il faut en effet savoir que, si tu veux créer une grille de LINES lignes de haut et de ROWS colonnes en vertical, ce que tu veux en réalité, c'est d'être en mesure de représenter ... LINES * ROWS elements; et qu'il est donc tout à possible de créer un tabeau à une seule dimension qui contienne ces LINES * ROWS elements.

    Pour accéder aux différents éléments contenu, on utilise alors une formule toute bête, qui correspond à element_recherche = ligne_souhaitee * ROWS + colonne_souhaitee.

    Ensuite, il faut savoir que la bibliothèque standard du C++ fournit depuis "la nuit des temps" une classe qui a été spécialement crée pour permettre la représentation de données sous forme tabulaire: la classe std::vector.

    L'idéal serait donc d'utiliser cette classe pour définir notre propre notion de "grille" (ou de "matrice"), sous une forme qui serait sans doute proche 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
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    /* nous créons une classe template, car nous nous en foutons royalement
     * du type des données qui seront représentée dans notre grille; ce qui nous intéresse,
     * c'est la manière dont nous pourrons les manipuler
     */
    template <typename T>
    class Grid{
    public:
        Grid(size_t lines, size_t rows, T val=T{}):
            lines_{lines}, rows_{rows}, items_{lines*rows, val}{
                assert(lines_ > 0 && "null height detected");
                assert(rows_ > 0 && "null width detected");
            }
         /* permet d'accéder (en lecture / écriture )à l'élément qui se trouve 
          * à la ligne l et à la colonne r
          */
        T & operator() (size_t l, size_t r){
            assert(l<lines_ && "line out of bound");
            assert(r<rows_ && "row out of bound");
            return items_[l*rows_ + r];
        }
        /* meme chose, mais sous forme constante */
        T const  & operator()(size_t l, size_t r) const{
            return const_cast<Grid &>(*this).operator()(l, r);
        }
        /* parce que l'on aura parfois besoin de connaitre le nombre
         * de lignes et de colonnes
         */
        size_t lines() const{
            return lines_;
        }
        size_t rows() const{
            return rows_;
        }
    private:
        size_t lines_;
        size_t rows_;
        std::vector<T> items_;
    };
    Grace à cette notion, tu pourrais en arriver à un code proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    Grid<char> terrain{LIGNES, COLONNES,' '};
    for(size_t l=0; l<terrain.lines(); ++ l){
        for(size_t c=0; c<terrain.rows(); ++c){
            if(une condition)
                terrain(l,c)=MUR;
            else
                terrain(l.c)=EMPTY;
        }
    }
    Et le tour serait joué

    Une fois que tu auras quelque chose dans le genre, nous pourrons nous intéresser au moyen d'extraire les données de ton fichier... Mais, comme j'ai déjà donné beaucoup d'informations, je vais te laisser dormir là dessus
    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

  3. #3
    Futur Membre du Club
    Homme Profil pro
    INSA Centre Val de Loire
    Inscrit en
    Mars 2017
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 27
    Localisation : France, Dordogne (Aquitaine)

    Informations professionnelles :
    Activité : INSA Centre Val de Loire

    Informations forums :
    Inscription : Mars 2017
    Messages : 8
    Points : 6
    Points
    6
    Par défaut
    Bonjour,
    Merci beaucoup de vous intéresser a mon cas.

    Tout d'abord, je trouve que crée une nouvelle classe soit beaucoup de travail pour pas grand chose et je vois pas bien où vous voulez en venir.
    Je ne comprend pas cette ligne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    :lines_{lines}, rows_{rows}, items_{lines*rows, val}
    Je compilateur me signal qu'il ne conait pas "lines_" et ainsi de suite ce qui est normal.
    Il ne manquerait pas dans "private: const int lines_, rows_; char items_" ?
    Cependant, je ne vois pas bien comment faire avec toute cette classe.


    Ensuite, pour ce qui est de cette partie:
    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
     
    char* ligne_decompose{};
     
    /*Dans la boucle de parcourt du fichier, pour stocker la ligne courante sous forme de tableau*/
    get (ligne_decompose, LIGNES*COLONNES);
     
    Grid<char> terrain{LIGNES, COLONNES,' '};
    for(size_t l=0; l<terrain.lines(); ++ l){
        for(size_t c=0; c<terrain.rows(); ++c){
            if(ligne_decompose[l*c]=='#')
                terrain(l,c)=MUR;
            else
                terrain(l.c)=EMPTY;
        }
    }
    Je suppose que LIGNES et COLONNES sont en majuscule car on fait un "#define LIGNES (fonction qui récupère la ligne)" ?
    Mais ça me parais bizarre parce que normalement les #define sont au début du code.
    Pour ce qui est de la condition, je ne suis pas sûr qu'elle soit bonne.
    J'aurais plutôt défini ligne par ligne en même temps que la lecture du fichier l'initialisation du terrain.

    Merci

  4. #4
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 611
    Points
    30 611
    Par défaut
    Citation Envoyé par Ovnib Voir le message
    Tout d'abord, je trouve que crée une nouvelle classe soit beaucoup de travail pour pas grand chose et je vois pas bien où vous voulez en venir.
    Non, ce n'est pas beaucoup de travail pour pas grand chose, c'est une des règles fondamentales de la programmation: toute notion qui apparaît dans l'étude des besoins doit apparaître dans le code sous une forme ou une autre.

    autrement dit, la règle est simple, et peut se résumer comme suit:
    un nom (ou un groupe nominal) qui apparaît dans l'analyse des besoins == un type de donnée dans le code
    un verbe (ou un groupe verbal) qui apparaît dans l'analyse des besoins == un fonction dans le code
    C'est simple et efficace, car cela te permet de faire la relation entre "j'avais pensé qu'il fallait <ceci> pour que ce soit sympa, j'ai bien <ceci> qui se fait dans le code"
    Je ne comprend pas cette ligne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    :lines_{lines}, rows_{rows}, items_{lines*rows, val}
    Je compilateur me signal qu'il ne conait pas "lines_" et ainsi de suite ce qui est normal.
    Il ne manquerait pas dans "private: const int lines_, rows_; char items_" ?
    Effectivement, au temps pour moi... j'ai oublié de rajouter les deux données membres lines_ et rows_... j'ai corrigé mon code

    NOTE que ce ne sont pas des int, qui sont par défaut des valeurs signées (et donc qui peuvent représenter des valeurs négatives), mais des size_t, qui sont des valeurs numériques non signées (et qui ne peuvent donc jamais être négatives )
    Cependant, je ne vois pas bien comment faire avec toute cette classe.

    Ensuite, pour ce qui est de cette partie:
    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
     
    char* ligne_decompose{};
     
    /*Dans la boucle de parcourt du fichier, pour stocker la ligne courante sous forme de tableau*/
    get (ligne_decompose, LIGNES*COLONNES);
     
    Grid<char> terrain{LIGNES, COLONNES,' '};
    for(size_t l=0; l<terrain.lines(); ++ l){
        for(size_t c=0; c<terrain.rows(); ++c){
            if(ligne_decompose[l*c]=='#')
                terrain(l,c)=MUR;
            else
                terrain(l.c)=EMPTY;
        }
    }
    Je suppose que LIGNES et COLONNES sont en majuscule car on fait un "#define LIGNES (fonction qui récupère la ligne)" ?
    Mais ça me parais bizarre parce que normalement les #define sont au début du code.
    Il faut savoir que tout code proposé sur un forum est destiné à être adapté à différentes situations.

    Dans le cas présent, quand tu crées ta grille, tu devras forcément indiquer le nombre de lignes et le nombre de colonnes qui la composent.

    L'origine de ces nombres n'a que peu d'importance: ils peuvent être définis "en durs" "quelque part" dans ton code, tout comme il se peut que tu les récupère dans un fichier qui représentera le contenu de ta grille, en fonction des situations dans lesquelles tu te trouve

    j'aurais, sans doute, du mettre un commentaire à ce sujet dans le code

    Une chose est sure: même si les valeurs de LIGNES et de COLONNES sont définies en dur dans le code, ce ne sera pas au travers d'un #define, à cause des problèmes liés à l'utilisation de symboles préprocesseurs.

    On préféreras, si l'on veut définir ces valeurs en dur, utiliser des définitions comme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    static size_t const LIGNES{25};   // valeurs à adapter à la grille que tu veux obtenir, bien sur
    static size_t const COLONNES{42};
    ou mieux encore
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    enum SIZES{
        LIGNES = 25,
        COLONNES = 42
    };
    Voire, le fin du fin, depuis l'arrivée de C++11
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    static constexpr size_t LIGNES{25};
    static constexpr size_t COLONNES{42};
    Dans les trois cas, nous créerons des constantes de compilation, que le compilateur sera -- le cas échéant -- en mesure d'utiliser pour ses propres calculs.

    Mais nous auront un avantage certain sur les "simples" #define : le compilateur pourra faire toutes les vérifications de types qui s'imposent
    Pour ce qui est de la condition, je ne suis pas sûr qu'elle soit bonne.
    J'aurais plutôt défini ligne par ligne en même temps que la lecture du fichier l'initialisation du terrain.
    Encore une fois, le code que je t'ai présenté doit être adapté à la situation dans laquelle tu te trouves. Car il ne faut pas espérer que je fasse tout le travail à ta place, non plus

    La manière dont tu obtiens la valeur qui te permettra de choisir entre le fait de mettre un mur ou de mettre un espace vide, la condition que tu mettra en place pour que le choix se fasse, ce n'est pas mon problème...

    La seule chose que je voulais te montrer au travers de ce code, c'est que, avec une valeur l représentant une ligne de ta grille et une valeur c représentant une colonne de ta grille, tu pouvais, grâce à la classe que je t'ai présentée et à l'opérateur () que j'ai défini dedans (sous une forme constante et sous une forme non constante), arriver à définir les valeur de chaque cases à l'aide d'un code aussi simple que terrain(l,c)=<valeur>;La seule différence, finalement, avec un tableau à deux dimensions, c'est que l'on n'utilise pas l'opérateur [], qui aurait du être utilisé sous une forme proche de plateau[l][ c ]=<valeur>;, mais l'opérateur (), en séparant les deux coordonnées par une virgule
    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

  5. #5
    Expert éminent
    Avatar de Pyramidev
    Homme Profil pro
    Développeur
    Inscrit en
    Avril 2016
    Messages
    1 460
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur

    Informations forums :
    Inscription : Avril 2016
    Messages : 1 460
    Points : 6 064
    Points
    6 064
    Par défaut
    Bonjour,

    HS const_cast :
    Citation Envoyé par koala01 Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
         /* permet d'accéder (en lecture / écriture )à l'élément qui se trouve 
          * à la ligne l et à la colonne r
          */
        T & operator() (size_t l, size_t r){
            assert(l<lines_ && "line out of bound");
            assert(r<rows_ && "row out of bound");
            return items_[l*rows_ + r];
        }
        /* meme chose, mais sous forme constante */
        T const  & operator()(size_t l, size_t r) const{
            return const_cast<Grid &>(*this).operator()(l, r);
        }
    De mon point de vue, quand on utilise const_cast, par défaut, il vaut mieux que ce soit la fonction non const qui appelle la fonction const en faisant un const_cast sur la référence retournée plutôt que la fonction const appelle la fonction non const.
    Les deux ont leurs défauts, mais appeler une fonction non const depuis une fonction const me semble plus dangereux, notamment à cause du vicieux std::map::operator[].
    Dans ton exemple, le cas où un tel danger pourrait survenir serait celui où un développeur ferait un réusinage de code un peu rapide en remplaçant std::vector<T> par std::map<Position, T>, par exemple pour implémenter une matrice creuse.

    HS dans le HS : Dommage qu'on n'ait pas les const predicates et selfconst du langage Loci. En effet, ils permettraient de factoriser le code sans passer par des const_cast ou des templates. Remarque : Je n'ai jamais programmé en Loci. J'ai seulement lu la description du langage.

  6. #6
    Futur Membre du Club
    Homme Profil pro
    INSA Centre Val de Loire
    Inscrit en
    Mars 2017
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 27
    Localisation : France, Dordogne (Aquitaine)

    Informations professionnelles :
    Activité : INSA Centre Val de Loire

    Informations forums :
    Inscription : Mars 2017
    Messages : 8
    Points : 6
    Points
    6
    Par défaut
    Finalement, j'ai trouvé la solution autrement:

    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
    int x, y;
    	string nombre_ligne,nombre_colones;
    	list<Fantome>::iterator itFantome;
    	fantomes.resize(10);
     
        ifstream fichier("./terrain.txt");
        if(fichier)//L'ouverture s'est bien passée, on peut donc lire
        {
            string ligne; //Une variable pour stocker les lignes lues
     
            ///Récupération de la largeur et de la hauteur
            fichier>>nombre_colones;
            fichier>>nombre_ligne;
            largeur = atoi(nombre_colones.c_str());
            hauteur = atoi(nombre_ligne.c_str());
            terrain = new Case[largeur*hauteur];
     
            getline(fichier, ligne);//On passe la première ligne qui a déjà été lue
            for(x=0;x<hauteur;x++) //Tant qu'on n'est pas à la fin, on lit
            {
                getline(fichier, ligne);
                for(y=0;y<largeur;y++)
                {
                    if(ligne[y]=='#')
                    {
                        terrain[x*largeur+y] = MUR;
                    }
                    else
                    {
                        terrain[x*largeur+y] = VIDE;
                    }
                }
             }
        }
        else
        {
           cout << "ERREUR: Impossible d'ouvrir le fichier en lecture." << endl;
        }
    Merci de votre aide

  7. #7
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 611
    Points
    30 611
    Par défaut
    Citation Envoyé par Pyramidev Voir le message
    Bonjour,

    HS const_cast :<snip>
    Tu le sais bien, je ne suis pas du tout partisan -- de manière générale -- des cast quels qu'ils soient, et pour quelle que soit la raison...

    Il n'empêche que, quand on sait ce que l'on fait (ce qui est -- me semble-t-il -- mon cas) et qu'un cast (quel qu'il soit) te permet d'éviter une duplication de code qui ne pourra que nuire par la suite, on se trouve justement dans une situation dans laquelle on peut justifier de faire une exception.

    Cela présente des risques, nous sommes bien d'accord, mais nous pouvons -- a priori -- partir du principe que ces risques sont "suffisamment maîtrisés" que pour éviter les problèmes
    Dans ton exemple, le cas où un tel danger pourrait survenir serait celui où un développeur ferait un réusinage de code un peu rapide en remplaçant std::vector<T> par std::map<Position, T>, par exemple pour implémenter une matrice creuse.
    Nous sommes bien d'accord là dessus...

    Mais il ne faut pas oublier non plus que n'importe quelle refactorisation / modification du code existant pose systématiquement de nombreux problèmes.

    Ce n'est pas pour rien que l'OCP compte parmi les cinq principes les plus importants en programmation

    Et cela implique -- bien entendu -- que toute modification du code existant doit être étudiée avec le plus grand soin.

    Dans l'exemple que tu donnes, le fait d'accéder à une position inexistante depuis la version constante de l'opérateur serait -- purement et simplement -- une erreur de logique qui doit être repérée et corrigée avant la mise en production du programme.

    Et il se fait que l'on a le mécanisme parfait pour palier ce genre de situation au travers des assertions qui nous viennent du C (c'est d'ailleurs sans doute le seul mécanisme issu du C dont je conseille l'usage et même l'abus ).

    Si tu veux mettre un système de matrice creuse en place en utilisant std::map, tu dois donc penser à placer une assertion -- dans la version constante de ton opérateur -- sur l'existence de la clé

    Si tu ne le fais pas, tu fais une modification du code existant sans en avoir évalué tous les problèmes potentiels, et ca, il n'existe aucune mesure qui pourra t'en prémunir
    HS dans le HS : Dommage qu'on n'ait pas les const predicates et selfconst du langage Loci. En effet, ils permettraient de factoriser le code sans passer par des const_cast ou des templates. Remarque : Je n'ai jamais programmé en Loci. J'ai seulement lu la description du langage.
    De manière générale, il est dommage que le langage ne dispose pas encore d'un moyen efficace de valider correctement tous les contrats possibles.

    assert et static_assert (couplé aux type_traits) sont deux solutions qui couvrent déjà une belle surface du problème, mais nous attendons avec impatience l'arrivée des concepts
    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

  8. #8
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Citation Envoyé par koala01 Voir le message
    De manière générale, il est dommage que le langage ne dispose pas encore d'un moyen efficace de valider correctement tous les contrats possibles.

    assert et static_assert (couplé aux type_traits) sont deux solutions qui couvrent déjà une belle surface du problème, mais nous attendons avec impatience l'arrivée des concepts
    Il y a deux choses en cours sur ce sujet :
    - Les concepts, qui permettent de valider des types
    - Les contrats, qui eux s'intéressent aux valeurs, et doivent remplacer assert : http://open-std.org/JTC1/SC22/WG21/d...8/p0542r3.html.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 611
    Points
    30 611
    Par défaut
    wouah, cool!!!

    A-t-on une chance de les avoir en C++20

    Y a-t-il déjà un compilateur qui les mette (à titre expérimental) en oeuvre

    As-tu l'impression que la "communauté" les voit des bon oeil
    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
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    La cible actuelle pour cette proposition est effectivement C++20.

    J'ai trouvé ce document qui est plus une introduction à la feature écrit par son principal contributeur : https://www.arcos.inf.uc3m.es/jdgarc.../contracts.pdf. Il précise entre autres qu'en avril 2017, il n'y avait pas encore d'implémentation pour les contrats. Je n'ai pas eu de connaissance de quelque-chose depuis.

    Je n'ai pas de retours négatifs sur cette fonctionnalité. Il y a eu plusieurs tentatives concurrentes à une époque, mais toutes ont convergé vers cette proposition. Il y a eu en revanche des controverses sur comment la spécifier. De tête :
    • Solution pur runtime, ou permettant aussi à des analyseurs statiques d'en tirer partie ? => C'est le second cas qui a gagné, ce qui est une bonne chose !
    • Combien de niveaux définir, comment les appeler => Ce débat a lui aussi été résolu, voir la proposition actuelle
    • Que faire si dans une translation unit, le niveau de vérification est off, et dans une autre, le niveau est default. Dans ce cas, le même code peut avoir un comportement différent selon l'endroit où il est appelé, ce qui est une violation de la ODR (il y a d'ailleurs exactement le même problème avec assert). J'ai l'impression que ce problème est désormais réglé (il n'apparait plus trop dans les discussions récentes), mais je n'ai pas suivi comment (peut-être lié au point suivant)
    • L'idée est que le code appelé dans les vérifications doit être plus ou moins sans effets secondaires (le principe est qu'il faut que le code ait le même comportement, au temps d'exécution prêt, selon que l'on active ou pas les vérifications), sauf quand la condition est violée. Mais ce plus ou moins n'est pas encore clairement défini : Doit-on le détecter à la compilation ? Doit on juste confier au développeur cette tâche ? Une sortie sur la console est-elle acceptable ? Une modification d'une variable locale d'une fonction appelée dans le test (par exemple pour boucler sur des éléments d'un tableau) ?
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  11. #11
    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
    HS:

    Citation Envoyé par Pyramidev Voir le message
    HS dans le HS : Dommage qu'on n'ait pas les const predicates et selfconst du langage Loci. En effet, ils permettraient de factoriser le code sans passer par des const_cast ou des templates. Remarque : Je n'ai jamais programmé en Loci. J'ai seulement lu la description du langage.
    Il y a une proposition que je trouve très intéressante qui permet de "corriger" la duplication de code: mettre explicitement un paramètre this dans une fonction membre pour garder le qualificateur et n'avoir à écrire qu'une fois le code. http://www.open-std.org/jtc1/sc22/wg...8/p0847r0.html

  12. #12
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 611
    Points
    30 611
    Par défaut
    Citation Envoyé par jo_link_noir Voir le message
    Il y a une proposition que je trouve très intéressante qui permet de "corriger" la duplication de code: mettre explicitement un paramètre this dans une fonction membre pour garder le qualificateur et n'avoir à écrire qu'une fois le code. http://www.open-std.org/jtc1/sc22/wg...8/p0847r0.html
    C'est, d'un point de vue conceptuel, à mon sens totalement indispensable, car la duplication de code et les chausses trappes qui peuvent traîner à gauche et à droite (comme l'inexistence de l'opérateur [] en version constante dans std::map dont parlait Pyramidev) posent de sérieux problèmes en termes de maintenabilité du code.

    Pour moi, tout ce qui peut rendre le code à la fois plus robuste, plus explicite, plus facile à écrire et plus facilement maintenable devrait être mis en oeuvre

    Espérons que cette proposition passera, sous une forme ou une autre
    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

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

Discussions similaires

  1. Supprimer les 2 derniers caractères fichiers TXT
    Par boumbo73 dans le forum VB.NET
    Réponses: 2
    Dernier message: 21/01/2013, 20h26
  2. Extraire ligne fichier txt
    Par Leben75 dans le forum Général JavaScript
    Réponses: 4
    Dernier message: 25/06/2012, 17h12
  3. Extraire données fichier txt
    Par thib1984 dans le forum MATLAB
    Réponses: 6
    Dernier message: 18/02/2008, 14h39
  4. extraire donné fichier txt afficher dans xml
    Par jasminrose dans le forum Format d'échange (XML, JSON...)
    Réponses: 1
    Dernier message: 01/04/2007, 13h14
  5. Extraire données fichier txt
    Par philippef dans le forum Langage
    Réponses: 1
    Dernier message: 10/10/2005, 18h12

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