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 :

Extraction des éléments d'une chaine de caractères


Sujet :

C++

  1. #1
    Nouveau membre du Club
    Inscrit en
    Juillet 2007
    Messages
    69
    Détails du profil
    Informations forums :
    Inscription : Juillet 2007
    Messages : 69
    Points : 36
    Points
    36
    Par défaut Extraction des éléments d'une chaine de caractères
    Bonjour,

    J'ai une petite question: comment peut-on extraire les différents morceaux d'une chaine de caractère un à un ?
    J'aimerais en fait extraire tous les "digits" d'une chaine de caractère du type ne comportant que des chiffres ("12345678987654321" par exemple) et les mettre dans un tableau d'entiers.

    Comment qu'on fait ?

    Merci.

  2. #2
    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 : 50
    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
    Extraire un caractère de fait par l'opérateur []

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    string s = "Salut";
    char c = s[3]; // c == 'u'
    Interpréter une chaîne pour en extraire un entier se fait à l'aide d'ostringstream (cf la faq).

    Là, tu veut interpréter un caractère unique, aussi il y a plus rapide

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    int interprete(char c)
    {
      switch (c)
      {
      case '1' : return 1;
      case '2' : return 2;
      ....
      }
    }
    Tu pourras tomber sur du code comme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    int interprete(char c)
    {
      return c - '0';
    }
    Mais ce genre de code suppose que les différents chiffres sont codés de manière continue dans la table de caractères, ce qui n'a rien de garanti.

  3. #3
    Membre éprouvé
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    1 064
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2005
    Messages : 1 064
    Points : 1 053
    Points
    1 053
    Par défaut
    Citation Envoyé par JolyLoic Voir le message
    Mais ce genre de code suppose que les différents chiffres sont codés de manière continue dans la table de caractères, ce qui n'a rien de garanti.
    Je crains que si. A ma connaissance la table de caractère utilisée pour les chars en C/C++ doit au minimum supporter l'ASCII pour que ce soit standard, et comme les chiffres font partie d'ASCII,... De toutes façons si tu veux être sur stringstream le fait à ta place, avec un mode de fonctionnement implementation dependent supposé fournir toujours le même résultat.

  4. #4
    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 : 50
    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
    Le standard cite 96 caractères que toute implémentation se doit de supporter (le basic source character set). Il ne précise pas comment ces caractères se situent les uns par rapport aux autres. Ensuite, il définit le basic execution character set :

    Citation Envoyé par Le standard 2.2.3.
    The basic execution character set and the basic execution widecharacter
    set shall each contain all the members of the basic source character set, plus control characters representing alert, backspace, and carriage return, plus a null character (respectively, null wide character), whose representation has all zero bits.
    For each basic execution character set, the values of the members shall be nonnegative and distinct from one another. The execution character set and the execution widecharacter set are supersets of the basic execution character set and the basic execution widecharacter set, respectively. The values of the members of the execution character sets are mplementationdefined, and any additional members are localespecific.
    C'est ce jeu de caractères qui compte en l'occurrence, et là encore je ne vois aucune référence à quelques relations que ce soit par exemple entre '1' et '2'. A moins qu'il y ait des contraintes supplémentaires causées par la compatibilité C (dont je ne possède pas la norme), je maintiens donc mon affirmation. Même s'il est très probable que ça marche sur toutes les machines modernes.

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

    Informations professionnelles :
    Activité : aucun

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

    une boucle correctement réfléchie et un petit coup de stringstream devraient pouvoir t'arranger cela en un clin d'oeil

    Exemple:
    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
    #include <iostream>
    #include <string>
    #include <vector>
    #include <sstream>
    using namespace std;
    int main()
    {
        vector<int> tab;
        string str="123456789987654321";
        for(size_t i=0;i<str.size();i++)
        {
            stringstream ss;
            ss<<str[i];
            int recup;
            ss>>recup;
            tab.push_back(recup);
        }
        for(size_t i=0;i<tab.size();i++)
            cout<<tab[i]<<endl;
     
        return 0;
    }

  6. #6
    Nouveau membre du Club
    Inscrit en
    Juillet 2007
    Messages
    69
    Détails du profil
    Informations forums :
    Inscription : Juillet 2007
    Messages : 69
    Points : 36
    Points
    36
    Par défaut
    Ok merci, ca marche impec' !

    Edit: est-ce que par hasard on pourrait faire fonctionner le même bout de code en remplacant tab par un int[1000] au lieu d'un element de type vector ?

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 629
    Points : 30 692
    Points
    30 692
    Par défaut
    La règle de base en C++, c'est d'utiliser la std::string tant que c'est possible...

    Cela signifie que, dés que tu dois utiliser une chaine de caractères, tu as très fortement intérêt à l'utiliser, même si la chaine de caractères est en réalité issue d'un programme C.

    Ceci dit, tu as de la chance, du fait que les *stringstream fonctionnent aussi bien avec les chaines "C style" qu'avec les std::string, et du fait que, si tu déclare un paramètre de fonction sous forme de référence constante vers une std::string, il existe un opérateur de conversion implicite qui transformera le char* en std::string

    Ainsi, et pour t'éviter d'avoir à recopier 100 fois le code, tu pourrais très bien factoriser le code sous la forme d'une fonction du genre 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
    /* Fonction qui extrait tous les chiffres d'une chaine de caractères et qui les
     * insère dans un tableau d'entiers
     * @in: référence constante sur la chaine à traiter
     * @in/out: référence sur le vector à remplir
     * requires: <vector>, <string>
     */
    void stringToTabInt(const std::string& str, std::vector<int>& tab)
    {
        for(size_t i=0;i<str.size();i++)
        {
            std::stringstream ss;
            ss<<str[i];
            int recup;
            ss>>recup;
            tab.push_back(recup);
        }
    }
    elle pourra tout aussi bien être appelée sous la forme 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
    int main()
    {
        std::vector<int> tab;
        std::string str="012345678987654321";
        stringToTabInt(str, tab);
        std::cout<<"l'affichage du tableau rempli grace à la std::string"<<std::endl;
        for(size_t i=0;i<tab.size();i++)
            std::cout<<tab[i]<<std::endl;
        std::vector<int> tabchar;
        char strchar[]="9874561230123456789";
        stringToTabInt(strchar, tabchar);
        std::cout<<"l'affichage du tableau rempli grace au char*"<<std::endl;
        for(size_t i=0;i<tabchar.size();i++)
            std::cout<<tabchar[i]<<std::endl;
        return 0;
    }
    [EDIT]Ceci dit, si le stringstream arrive à introduire un char venant d'une std::string, il n'y a aucune raison pour qu'il n'arrive pas à introduire un char venant d'un char [ ]

    ca pourrait se faire 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
    12
    13
    14
    /* utilise une chaine de caractères "C style" (tableau de caractères terminé 
     * par un '\0'
     * tout ce qu'il y a autour de la boucle reste identique ;)
     */
    size_t i=0;
    while(str[i]!='\0')
    {
        stringstream ss;
        ss<<str[i];
        int recup;
        ss>>recup;
        tab.push_back(recup);
        ++i;
    }

  8. #8
    Nouveau membre du Club
    Inscrit en
    Juillet 2007
    Messages
    69
    Détails du profil
    Informations forums :
    Inscription : Juillet 2007
    Messages : 69
    Points : 36
    Points
    36
    Par défaut
    Super !

    Grand merci pour ces précisions Koala.

  9. #9
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Points : 4 551
    Points
    4 551
    Par défaut
    Et puis, parce que c'est joli (et remboursé par la sécurité sociale):
    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 <vector>
    #include <string>
    #include <algorithm>
     
    namespace 
    { 
      class ascii_to_i_translator
      {
        int base;
      public:
        ascii_to_i_translator(int b) : base(b) { }
        int operator()(int n) const { return n - base; }
      };
    }
     
    void istring_to_int_array(const string& input, vector<int>& output)
    {
      std::transform(input.begin(), input.end(), 
                           std::back_inserter(output),
                           ascii_to_i_translator('0');
    }
    @JolyLoic: la norme C99, section 5.2.1 §3 :
    In both the source and execution basic character sets, the value of each character after 0 in the above list of decimal digits shall be one greater than the value of the previous.
    Ce qui rend l'expression x - '0' compatible avec la norme C (et donc C++, par extension).

  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 : 50
    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
    Faudrait que je me la procure, cette norme, quand même...

    Y a-t-il un passage semblable sur les lettres ?

  11. #11
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Points : 4 551
    Points
    4 551
    Par défaut
    Citation Envoyé par JolyLoic Voir le message
    Faudrait que je me la procure, cette norme, quand même...

    Y a-t-il un passage semblable sur les lettres ?
    Hélas non.

    Le §3 complet:

    Both the basic source and basic execution character sets shall have the following members:

    the 26 uppercase letters of the Latin alphabet
    A B C D E F G H I J K L M
    N O P Q R S T U V W X Y Z

    the 26 lowercase letters of the Latin alphabet
    a b c d e f g h i j k l m
    n o p q r s t u v w x y z

    the 10 decimal digits
    0 1 2 3 4 5 6 7 8 9

    the following 29 graphic characters
    ! " # % & ' ( ) * + , - . / :
    ; < = > ? [ \ ] ^ _ { | } ~

    the space character, and control characters representing horizontal tab, vertical tab, and form feed. The representation of each member of the source and execution basic character sets shall fit in a byte. In both the source and execution basic character sets, the value of each character after 0 in the above list of decimal digits shall be one greater than the value of the previous. In source files, there shall be some way of indicating the end of each line of text; this International Standard treats such an end-of-line indicator as if it were a single new-line character. In the basic execution character set, there shall be control characters representing alert, backspace, carriage return, and new line. If any other characters are encountered in a source file (except in an identifier, a character constant, a string literal, a header name, a comment, or a preprocessing token that is never converted to a token), the behavior is undefined.

Discussions similaires

  1. [Tableaux] Extraire des mots d'une chaine de caractères
    Par pratiquement dans le forum Langage
    Réponses: 5
    Dernier message: 24/01/2008, 09h20
  2. [DOM] Rajouter des éléments à l’aide de chaine de caractère
    Par loic911 dans le forum Format d'échange (XML, JSON...)
    Réponses: 5
    Dernier message: 05/04/2007, 16h14
  3. extraire des entiers d'une chaine de caractère
    Par 18Marie dans le forum Langage
    Réponses: 9
    Dernier message: 10/08/2006, 11h17
  4. [MySQL] extraire des nombre d'une chaine de caractères et addition
    Par Yotho dans le forum PHP & Base de données
    Réponses: 1
    Dernier message: 04/03/2006, 16h54
  5. Réponses: 9
    Dernier message: 17/01/2003, 11h45

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