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

SL & STL C++ Discussion :

Opérateur >> sur ifstream


Sujet :

SL & STL C++

  1. #1
    Membre émérite
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 764
    Points : 2 705
    Points
    2 705
    Par défaut Opérateur >> sur ifstream
    Hello,

    Si j'ai un fichier CSV dont les champs sont séparés par une tabulation, et que le contenu de certains champs peut contenir des espaces, comment faire en sorte que l'opérateur >> ignore les espaces pour ne "tokenizer" qu'en fonction des tabulations ?

  2. #2
    Membre expérimenté Avatar de Trademark
    Profil pro
    Inscrit en
    Février 2009
    Messages
    762
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2009
    Messages : 762
    Points : 1 396
    Points
    1 396
    Par défaut
    L'opérateur >> utilise std::isspace(x, stream.getloc()), reference. Faut que tu regardes du côté des locales pour en créer une qui considère que ' ' n'est pas une espace (le site précédent a toutes les références qu'il faut sur les locales pour faire ça).

    Sinon tu peux utiliser une solution de plus haut niveau en lisant toute ta ligne et la lire avec un token_iterator par exemple (dans Boost).

  3. #3
    Membre émérite
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 764
    Points : 2 705
    Points
    2 705
    Par défaut
    Citation Envoyé par Trademark Voir le message
    Sinon tu peux utiliser une solution de plus haut niveau en lisant toute ta ligne et la lire avec un token_iterator par exemple (dans Boost).
    C'est ce que j'ai fait à une autre occasion, mais là, j'ai besoin de perfs. Même si je sais que les flux ne sont pas encore la panacées, mais comme c'est plus lisible (du moins dans le cas que j'ai à traiter : pas de formatage de flottant).

    Je vais étudier ton autre solution.

  4. #4
    Membre émérite
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 764
    Points : 2 705
    Points
    2 705
    Par défaut
    Merci pour tes indications, Trademark !

    La solution figure sur cette page.

    EDIT : ça ne va pas ; l'extraction du flux s'arrête quand est rencontré le caractère espace

  5. #5
    Membre expérimenté Avatar de Trademark
    Profil pro
    Inscrit en
    Février 2009
    Messages
    762
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2009
    Messages : 762
    Points : 1 396
    Points
    1 396
    Par défaut
    Utilises-tu bien des char au lieu de wchar_t (dans l'exemple) ?
    Est-ce que l'exemple marche (à la base) ?

  6. #6
    Membre expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2011
    Messages
    746
    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 : 746
    Points : 3 667
    Points
    3 667
    Par défaut
    En fait l'exemple est fonctionnel mais la spécialisation de ctype<char> se fiche totalement de certaines fonctions virtuelles dont do_is fait partit (§22.4.1.3.2 petit 5 de la norme C++11).

    Alors du coup j'ai tenté avec un type mychar qui est une structure contenant un char et se cast implicitement en char. J'ai spécialisé ctype avec et définit toute les méthodes virtuelles qui redirigent vers locale.classic().methode_correspondante (vraiment fait à l'arrache).
    Ceci fonctionne mais il faut utiliser des basic_string<mychar>, basic_stringstream<mychar>, etc ce qui n'est pas vraiment pratique :/

  7. #7
    Membre émérite
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 764
    Points : 2 705
    Points
    2 705
    Par défaut
    Comme l'indique jo_link_noir, la norme de C++ prescrit que ctype<charT> soit accompagné d'une spécialisation ctype<char>, qui fonctionne selon d'autres principes, par souci d'optimisation.

    Je me suis donc inspiré de l'exemple donné en référence, et ai pondu ça :

    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 <iostream>
    #include <vector>
    #include <locale>
    #include <sstream>
     
    // Cette facette ctype ne considère pas le caractère espace comme un... espace
    // Ce caractère est donc ignoré par l'extracteur de flux.
    struct CSV_whitespace : std::ctype<char>
    {
        static const mask* make_table()
        {
            // Fait une copie de la table de localisation
            static std::vector<mask> v(classic_table(), classic_table() + table_size);
     
    	// Déclassifie le caractère espace de la catégorie des caractères vierges
            v[' '] &= ~space;
     
            return &v[0];
        }
     
        CSV_whitespace(std::size_t refs = 0) : ctype(make_table(), false, refs) {}
    };
     
    int main()
    {
        std::string token;
     
        std::string in = "chaine1\tchaine2 chaine3";
     
        std::istringstream s(in);
        s.imbue(std::locale(s.getloc(), new CSV_whitespace()));
        while (s >> token)
        {
            std::cout << "  " << token << '\n';
        }
    }
    Cela fonctionne !

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

Discussions similaires

  1. opérateur de bits sur type signé
    Par gronaze dans le forum C
    Réponses: 6
    Dernier message: 18/09/2009, 19h05
  2. Erreur de segmentation sur ifstream.close()
    Par tHE_fLAmMinG_mOE dans le forum SL & STL
    Réponses: 4
    Dernier message: 27/01/2009, 14h54
  3. Réponses: 7
    Dernier message: 22/01/2008, 15h18
  4. Opérateur max sur du varchar.
    Par kluh dans le forum Access
    Réponses: 4
    Dernier message: 23/11/2005, 21h31
  5. question sur les opérateurs
    Par isidore dans le forum C++
    Réponses: 10
    Dernier message: 25/02/2005, 18h46

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