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 :

Comptabiliser des mots et detection d'espace dans un texte


Sujet :

C++

  1. #1
    Membre éclairé
    Profil pro
    Inscrit en
    Février 2010
    Messages
    2 051
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 2 051
    Points : 877
    Points
    877
    Par défaut Comptabiliser des mots et detection d'espace dans un texte
    Bonjour tous,

    j'ai un fichier texte avec deux type de lignes (pour simplifier) A et B:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    # type A
    A ferrite 2.85 1e-30
     # type B
    B VC 4.1
    je voudrais sélectionner chaque ligne et mettre dans une variable, pour cela je fais:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    getline(inputfile,variable)
    ensuite je voudrais savoir combien il y a de mot dans la phrase
    pour cela je ne sais pas trop comment faire, j'ai regardé un peu sur diverses FAQ et autre et j'ai l'impression que l'on peut faire quelque chose avec:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    find_first_of()
    size()
    substr (..,..)
    mais je ne sais pas comment faire.

    ==> je pensais faire variable.size() pour avoir le nombre de caracteres et ensuite faire variable.find_first_of() pour detecter le nombre d'espaces mais je ne sais pas comment faire pour detecter des espaces et je n'arrive pas non plus à m'en sortir avec les positions des espaces.

    ensuite je voudrais stocker le nombre de mot de chaque line dans des variables:
    je pense qu'il n'y aura pas de problèmes si le truc d'avant est résolu

    J'espere que vous pourrez m'aider....

    merci d'avance

  2. #2
    Membre éclairé
    Profil pro
    Inscrit en
    Février 2010
    Messages
    2 051
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 2 051
    Points : 877
    Points
    877
    Par défaut
    Bonjour,
    je viens de regarder sur le net et j'ai trouvé pas mal de fonction pour les string mais pas pour compter le nombre de mots dans un lignes.

    ==> au lieu de faire ce que je cherche à faire peut etre qu'il existe une fonction toute prete capable de faire cela?

  3. #3
    Membre habitué

    Profil pro
    Inscrit en
    Septembre 2010
    Messages
    18
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2010
    Messages : 18
    Points : 144
    Points
    144
    Par défaut
    Salut, ce que tu cherches à faire s'appelle un split. Tu as plusieurs pistes sur ce lien http://stackoverflow.com/questions/2...split-a-string

  4. #4
    Membre éclairé
    Profil pro
    Inscrit en
    Février 2010
    Messages
    2 051
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 2 051
    Points : 877
    Points
    877
    Par défaut
    super! merci d'avoir pris le temps de répondre ce lien à l'air pas mal du tout

  5. #5
    Membre éclairé
    Profil pro
    Inscrit en
    Février 2010
    Messages
    2 051
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 2 051
    Points : 877
    Points
    877
    Par défaut
    je reviens car j'ai quelques petits soucis de comprehension du programme

    ==> j'ai mis mais commentaires dans le code ci dessous

    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
     
    #include <iostream>  //permet gérer flux
    #include <sstream>   //pour manipuler les string
    #include <string>     //permet gérer objet string
    using namespace std;
     
    int main()
    {
    //on attribut à variable s une chaine de caractere
        string bibi=("Somewhere down the road"); 
    //ISS est un objet de type istringstream il contient le string 
    //bibi
        istringstream iss(bibi);
     
        while (iss)
        {
            string sub;
            iss >> sub;
    //c'est operation je ne la comprend pas on met tout le contenu "bibi"
    //dans la variable sub ?
            cout << "Substring: " << sub << endl;
        }
        return 0;
    }
    Je vous pose cette question car bien que le code fonctionne j'aimerai comprendre comment il "marche".

    De plus j'aimerai connaitre la taille de ISS avant de faire la boucle mais j'ai remarqué que
    ne fonctionne pas et j'aimerai comprendre pourquoi

    j'ai regardé sur la faq et j'ai vu que istringstream sert à faire des convertion donc je ne comprends pas comment il est utilisé ici pour que ca fonctionne

    merci d'avance pour votre aide

  6. #6
    Membre habitué

    Profil pro
    Inscrit en
    Septembre 2010
    Messages
    18
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2010
    Messages : 18
    Points : 144
    Points
    144
    Par défaut
    Je te conseille de regarder ce lien http://www.cplusplus.com/reference/iostream/istream/ et notamment la partie sur l'opérateur <<.

    Tu peux re-coder une fonction split() pour avoir un code plus propre.

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

    Informations professionnelles :
    Activité : aucun

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

    Si tu veux juste compter le nombre de mots qu'il y a dans ta variable, sans pour autant récupérer chacun de ceux-ci, il existe, dans le fichier d'en-tête <algorithm>, une fonction nommée count_if, placée, comme tout ce qui vient du standard, dans l'espace de noms std.

    Son prototype est du genre de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    template <typename iter, typename functor>
    count_if(iter begin, iter end, functor func)
    Et, devine quoi son but est de compter le nombre d'éléments compris entre begin et en qui renvoient vrai lorsqu'ils sont soumis au foncteur func

    Or, il se fait que, justement, la classe string dispose des fonctions membre begin() et end() qui renvoient respectivement un itérateur sur le premier caractère et un autre sur ce qui suit le dernier caractère

    De plus, il existe une fonction nommée isspace qui permet de déterminer si un caractère donné est considérable comme un espace (car il n'y a pas que " " qui peut être considéré comme tel ).

    La solution élégante pour compter le nombre de mots pourrait donc parfaitement passer par la création d'un foncteur qui permet de savoir si un caractère donné est un espace, qui prendrait la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    struct isSpace
    {
        bool operator()(char const c) const
        {
            return std::isspace(c);
        }
    };
    et de l'utiliser dans la fameuse fonction count_if, sous une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    int main()
    {
        std::string str("A ferrite 2.85 1e-30");
        std::cout<<std::count_if(str.begin(),str.end(),isSpace())+1;
    }
    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
    Membre éclairé
    Profil pro
    Inscrit en
    Février 2010
    Messages
    2 051
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 2 051
    Points : 877
    Points
    877
    Par défaut
    merci pour votre aide mon probleme est résolu avec la premiere méthode

    (je vais surement j'etais un coup d'oeil sur la 2eme car elle a l'air tres bien aussi)

    A bientot et encore merci

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Citation Envoyé par 21did21 Voir le message
    je reviens car j'ai quelques petits soucis de comprehension du programme

    ==> j'ai mis mais commentaires dans le code ci dessous

    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
     
    #include <iostream>  //permet gérer flux
    #include <sstream>   //pour manipuler les string
    #include <string>     //permet gérer objet string
    using namespace std;
     
    int main()
    {
    //on attribut à variable s une chaine de caractere
        string bibi=("Somewhere down the road"); 
    //ISS est un objet de type istringstream il contient le string 
    //bibi
        istringstream iss(bibi);
     
        while (iss)
        {
            string sub;
            iss >> sub;
    //c'est operation je ne la comprend pas on met tout le contenu "bibi"
    //dans la variable sub ?
            cout << "Substring: " << sub << endl;
        }
        return 0;
    }
    Je vous pose cette question car bien que le code fonctionne j'aimerai comprendre comment il "marche".
    Le fait est que les opérateurs << et >> s'arrêtent au premier caractère pouvant passer pour un espace.

    L'espace (ou tout caractère pouvant passer pour) est en effet le caractère qui sert "classiquement" pour séparer les informations .

    Or, l'idée est que chaque valeur à convertir sera, fatalement séparée des autres, et que le caractère idéal pour ce faire est... l'espace (ou tout autre caractère pouvant passer pour).

    il est donc normal que l'opérateur >> s'arrête au premier espace qu'il rencontre, pour éviter de traiter deux valeurs différentes comme s'il s'agissait d'une seule, et qu'il supprime l'espace rencontré et tous ceux qui pourraient suivre, de manière à ce que la prochaine utilisation de l'opérateur >> donne le résultat attendu
    De plus j'aimerai connaitre la taille de ISS avant de faire la boucle mais j'ai remarqué que
    ne fonctionne pas et j'aimerai comprendre pourquoi
    Parce que tu n'as, simplement, pas besoin de connaitre la taille...

    En effet, on pourrait parfaitement envisager une situation dans laquelle ton istringstream est rempli d'un coté (un thread qui envoie des informations, par exemple) et vidé par un autre (un deuxième thread qui converti les informations que le premier a envoyé dedans).

    De plus, la taille que tu obtiendrais serait la taille totale du flux, incluant tous les caractères utiles à la conversion mais n'intervenant pas dans la valeur convertie(espace, tabulation, retour à la ligne, ...)

    Or, ce n'est, très certainement pas ce genre d'information que tu espère obtenir en en demandant la taille

    C'est la raison pour laquelle on ne travaille jamais avec une boucle se basant sur la taille du flux, mais bien avec une boucle dans laquelle on entre uniquement si le flux est valide

    Si la conversion des données était dévolue à un thread particulier, nous pourrions parfaitement envisager de travailler avec deux boucles imbriquées sous une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    void foo(stringstream & ss)
    {
        while (thread_not_dead) tant que le thread est actif
        {
            while(ss) // tant qu'il y a quelque chose à récupérer
            {
                // on récupère ce que l'on doit
            }
            /* et on attend qu'un autre thread remplice de nouveau le flux
        }
    }
    (bon, d'accord, il faudrait sans doute prendre quelques précautions supplémentaires
    j'ai regardé sur la faq et j'ai vu que istringstream sert à faire des convertion donc je ne comprends pas comment il est utilisé ici pour que ca fonctionne

    merci d'avance pour votre aide
    istringstream est ce que l'on appelle un "flux", comme l'indique le stream à la fin de son nom

    C'est à dire que c'est une classe qui est prête à recevoir "en permanence" des données destinées à un usage à déterminer.

    L'autre partie du nom t'indique qu'il traite des chaines de caractères (string) entrantes (i pour In), et sous entend donc que l'on ne sait, a priori, pas ce qu'il y aura en sortie (car les flux on systématiquement une entrée et une sortie... autrement, ils ne pourraient pas suivre leur cours )

    Si l'on met le tout ensemble, on se rend compte qu'il s'agit d'un flux de conversion permettant de convertir une chaine de caractères en... à peu près n'importe quoi.

    La seule contrainte qu'il impose, c'est que l'opérateur >> soit défini pour le type dans lequel on souhaite convertir la chaine de caractères.

    A la base, cet opérateur est défini pour les types primitifs (caractères, entiers et réels) et pour certains types "définis par l'utilisateur" (par la norme, en réalité) comme... les chaines de caractères.

    Cela peut paraitre paradoxal, mais il faut bien comprendre que la chaine de caractères est un type de données régulièrement utilisé dans des structures plus complexes.

    Nous pourrions ainsi avoir une structure produit proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    struct Produit
    {
        std::string nom;
        double prix_de_vente;
        double prix_d_achat;
        std::string fournisseur;
    };
    et nous voudrions donc pouvoir sauvegarder, et surtout récupérer par la suite, le nom du produit, le fournisseur et les prix de vente et d'achat

    Si l'on récupère les informations permettant de donner les valeurs adéquates à cette structure sous la forme d'une chaine de caractères, ce sera sans doute sous une forme proche de
    et nous en arriverons donc à les récupérer grace à un code proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    std::istringstream iss(chaine_lue); // on place la ligne lue dans le flux;
    produit prod; // on crée un produit "non initialisé"
    iss>>prod.nom // on récupère le nom (qui est une chaine de caractère)
       >>prod.prix_de_vente // le prix de vente
       >>prod.prix_d_achat // le prix d'achat
       >>prod.fournisseur; // et le fournisseur
    Et tu pourrais donc redéfinir l'opérateur >> de manière à ce qu'il agisse de la sorte pour un produit, sous une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    istringstream & operator(istringstream & iss, produit & prod)
    {
    iss>>prod.nom // on récupère le nom (qui est une chaine de caractère)
       >>prod.prix_de_vente // le prix de vente
       >>prod.prix_d_achat // le prix d'achat
       >>prod.fournisseur; // et le fournisseur
       return iss;
    }
    qui te permettrait, si tu veux récupérer les informations à plusieurs endroits, d'écrire simplement iss>>prod au lieu de devoir copier encore et toujours le même code de quatre lignes

    Maintenant, si ta question est de savoir comment on arrive à convertir une chaine de caractères en un type primitif, la réponse que je te ferai ne va sans doute pas te satisfaire: il n'est pas utile, dans un premier temps, en tout cas, de t'interroger sur le sujet. Sache simplement que istringstream fait parfaitement cela et profites-en quand tu en as besoin
    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
    Membre éclairé
    Profil pro
    Inscrit en
    Février 2010
    Messages
    2 051
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 2 051
    Points : 877
    Points
    877
    Par défaut
    merci Koala pour ce cours

    Citation Envoyé par koala01 Voir le message
    Le fait est que les opérateurs << et >> s'arrêtent au premier caractère pouvant passer pour un espace.
    L'espace (ou tout caractère pouvant passer pour) est en effet le caractère qui sert "classiquement" pour séparer les informations .
    Or, l'idée est que chaque valeur à convertir sera, fatalement séparée des autres, et que le caractère idéal pour ce faire est... l'espace (ou tout autre caractère pouvant passer pour).
    il est donc normal que l'opérateur >> s'arrête au premier espace qu'il rencontre, pour éviter de traiter deux valeurs différentes comme s'il s'agissait d'une seule, et qu'il supprime l'espace rencontré et tous ceux qui pourraient suivre, de manière à ce que la prochaine utilisation de l'opérateur >> donne le résultat attendu
    d'accord j'ai bien saisi à présent

    Citation Envoyé par koala01 Voir le message
    Parce que tu n'as, simplement, pas besoin de connaitre la taille...
    En effet, on pourrait parfaitement envisager une situation dans laquelle ton istringstream est rempli d'un coté (un thread qui envoie des informations, par exemple) et vidé par un autre (un deuxième thread qui converti les informations que le premier a envoyé dedans).
    De plus, la taille que tu obtiendrais serait la taille totale du flux, incluant tous les caractères utiles à la conversion mais n'intervenant pas dans la valeur convertie(espace, tabulation, retour à la ligne, ...)
    Or, ce n'est, très certainement pas ce genre d'information que tu espère obtenir en en demandant la taille
    C'est la raison pour laquelle on ne travaille jamais avec une boucle se basant sur la taille du flux, mais bien avec une boucle dans laquelle on entre uniquement si le flux est valide
    en fait je pense que ca aurait été utile une fonction qui donne le nombre de "mot" séparé par un espace ou autre caractere de separation.

    c'est ce type de fonction que je croyais qu'il existait, ca eviterai de faire une boucle comme j'ai pu faire.

    Citation Envoyé par koala01 Voir le message
    C'est à dire que c'est une classe qui est prête à recevoir "en permanence" des données destinées à un usage à déterminer.
    L'autre partie du nom t'indique qu'il traite des chaines de caractères (string) entrantes (i pour In), et sous entend donc que l'on ne sait, a priori, pas ce qu'il y aura en sortie (car les flux on systématiquement une entrée et une sortie... autrement, ils ne pourraient pas suivre leur cours )
    Si l'on met le tout ensemble, on se rend compte qu'il s'agit d'un flux de conversion permettant de convertir une chaine de caractères en... à peu près n'importe quoi.
    La seule contrainte qu'il impose, c'est que l'opérateur >> soit défini pour le type dans lequel on souhaite convertir la chaine de caractères.
    A la base, cet opérateur est défini pour les types primitifs (caractères, entiers et réels) et pour certains types "définis par l'utilisateur" (par la norme, en réalité) comme... les chaines de caractères.
    OK pour toutes ces infos complementaires,

    j'ai bien saisi à présent et je t'en remercie

  11. #11
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 275
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 275
    Points : 10 985
    Points
    10 985
    Par défaut
    Il y a une façon STLienne de découper les chaines dans la zone source de dvpz.
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  12. #12
    Membre éclairé
    Profil pro
    Inscrit en
    Février 2010
    Messages
    2 051
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 2 051
    Points : 877
    Points
    877
    Par défaut
    Je ne connais pas la STL (je suis grand débutant), je conserve donc la méthode que j'ai cité ci dessus

    merci quand meme

  13. #13
    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
    Je te conseille de lire http://www.developpez.net/forums/d10...s/#post5631661
    J'y donne un code complet pour découper une chaîne selon une expression régulière.
    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.

  14. #14
    Membre éclairé
    Profil pro
    Inscrit en
    Février 2010
    Messages
    2 051
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 2 051
    Points : 877
    Points
    877
    Par défaut
    Citation Envoyé par JolyLoic Voir le message
    Je te conseille de lire http://www.developpez.net/forums/d10...s/#post5631661
    J'y donne un code complet pour découper une chaîne selon une expression régulière.
    merci

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

Discussions similaires

  1. récupérer des mots séparés par un espace dans une ligne
    Par laurentze dans le forum Shell et commandes GNU
    Réponses: 2
    Dernier message: 14/06/2010, 16h04
  2. Réponses: 1
    Dernier message: 15/04/2009, 18h28
  3. [RegEx] Détecter des mots séparés par différents espaces
    Par lorange dans le forum Langage
    Réponses: 4
    Dernier message: 03/03/2009, 21h20
  4. Récupérer des mots séparés par un espace dans un .txt
    Par elnino67 dans le forum Débuter
    Réponses: 2
    Dernier message: 28/05/2008, 22h13
  5. enlever des espaces dans un texte
    Par juin29 dans le forum Langage SQL
    Réponses: 6
    Dernier message: 22/03/2007, 15h45

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