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 :

split d'une chaine de caractere, + cast


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre très actif
    Homme Profil pro
    Second de cuisine
    Inscrit en
    Avril 2005
    Messages
    193
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Second de cuisine
    Secteur : Alimentation

    Informations forums :
    Inscription : Avril 2005
    Messages : 193
    Par défaut split d'une chaine de caractere, + cast
    Bonjour !

    Je cherche a splitter un char* (avec comme delimiteur, un espace), et que chaque petit char resultant soit transformé en unsigned short !

    Exemple:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    char* A = "01 05 05 FF";
    Je souhaite avoir au final un:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    vector<unsigned short> B;
    // contenant
    /* 1 5 5 255 */
    Pour tester, j'ai tenté ceci:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
        char* buf = "01 05 05 05 05";
        unsigned short b;
     
     
        b = (((unsigned short)buf[1] << 8 | (unsigned short)buf[0]) & 0xff);
        cout << "b = " << b << endl;
    ouput:
    b = 48
    au lieu de b=1.

    ---------

    Sehnsucht à proposé ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
            std::istringstream iss ("ab cd ef 01");
            iss >> std::hex;
            std::istream_iterator<unsigned short> in (iss);
            std::vector<int> v (in, std::istream_iterator<unsigned short> ());
    Ca marche niquel en effet.
    Mais est-ce vraiment bon niveau performances ?
    Si c'est plus rapide qu'un bit shifting, alors je garde, si non, j'aimerais etre éclairé/corrigé sur ma methode qui ne marche pas !
    merci !

  2. #2
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    27 128
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Mai 2008
    Messages : 27 128
    Billets dans le blog
    149
    Par défaut
    Bonjour,

    J'imagine que c'est pour faire de la lecture binaire (de fichiers, ou de paquets). Du coup, je pense que vous pourriez faire des read() ou fonction équivalent, qui à la place de vous donner des char* de caractère, vous donnera directement des code hexa (enfin, je me comprend ). Du coup, même si la méthode de Sehnsucht ne semble pas avoir trop de problème en performance, je ne suis pas sur que ce soit ce que vous voulez.
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  3. #3
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 151
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 151
    Billets dans le blog
    4
    Par défaut
    Bonjour,

    le fait de transformer un char en unsigned int de cette manière ne me parait pas correct. Et à priori ton test va en mon sens.

    Les nombres ne sont pas placés de cette manière sur la table ASCII.
    Essaye ce code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    char* buf = "01 05 05 05 05";
        unsigned short b;
     
     
        b = (unsigned short)(((buf[1] - '0') << 8 | (buf[0] - '0')) & 0xff);
        cout << "b = " << b << endl;
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  4. #4
    Membre très actif
    Homme Profil pro
    Second de cuisine
    Inscrit en
    Avril 2005
    Messages
    193
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Second de cuisine
    Secteur : Alimentation

    Informations forums :
    Inscription : Avril 2005
    Messages : 193
    Par défaut
    Pas mal Bousk, voici une correction


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    char* buf = "01 05 05 05 05";
        unsigned short b;
     
     
        b = (unsigned short)(((buf[0] - '0') << 8 | (buf[1] - '0')) & 0xff);
        cout << "b = " << b << endl;
    L'ordre de ton shirt, cest dabord le premier char ensuite le 2e.

    Voici apres quelques minutes de recherche et de tests, comment récuperer un unsigned int (2 short), et un unsigned long long (4 short)

    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
        char* buf = "01 05 05 05 05";
     
        // short 01 (premier)
        unsigned short b;
        b = (unsigned short)(((buf[0] - '0') << 4 | (buf[1] - '0')) & 0xff);
        cout << "b (01) = " << b << endl;
        //--------------------------------
        // int 01 05 (premier et second)
        unsigned int c;
        c = (b << 8) & 0xffff;
        c += (unsigned short)(((buf[3] - '0') << 4 | (buf[4] - '0')) & 0xff);
        cout << "c (01 05) = " << c << endl;
        //--------------------------------
        // short 05 (troisieme)
        unsigned short d1;
        d1 = (unsigned short)(((buf[6] - '0') << 4 | (buf[7] - '0')) & 0xff);
        //--------------------------------
        // int 05 05 (troisieme et quatrieme)
        unsigned int d;
        d = (d1 << 8) & 0xffff;
        d += (unsigned short)(((buf[9] - '0') << 4 | (buf[10] - '0')) & 0xff);
        //--------------------------------
        // long long 01 05 05 05
        unsigned long long e;
        e = (c << 16) & 0xffffffff;
        e += d;
        cout << "e (01 05 05 05) = " << e << endl;
    Pour le string je bloque légèrement !

    Voici le code:
    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
            // Maintenant hex > string
        char* buf2 = "68 65 6C 6C 6F 20 77 6f 72 6c 64 21"; // hello world!
        // on assume que l'on avait deja la longueur du string !
        int len = 12;
        // la ou on recupere le string
        char out[50];
        // comptage des lettres
        int charr = 0;
        // boucle sur buf2
        for(int i = 0; i < strlen(buf2); i+=2)
        {
            if(buf2[i] == 32) { // espace, on passe !
                i -=1;
                continue;
            }
            unsigned short c = (((buf2[i] - '0') << 4 | (buf2[i+1] - '0')) & 0xff);
            cout << "char n" << charr << " is (" << i << "; " << i+1 << ") " <<  char(c)   << endl;
            // on recupere le caractere
            out[charr] = char(((buf2[i] - '0') << 4 | (buf2[i+1] - '0')) & 0xff);
            ++charr;
        }
        out[len] = 0;
        cout << "out = " << out << endl;
    Et sur la console j'ai:
    hessv wvrsd!

    Ya un petit probleme avec le l et o qui sont affichés s & v

  5. #5
    Membre Expert
    Avatar de Sehnsucht
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Octobre 2008
    Messages
    847
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Lot et Garonne (Aquitaine)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Octobre 2008
    Messages : 847
    Par défaut
    Personnellement je l'aime bien mon code, même si d'aucuns pensent qu'il ne répond pas à la problématique.
    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 <algorithm>
    #include <iostream>
    #include <iterator>
    #include <sstream>
    #include <vector>
     
    int main ()
    {
            std::istringstream iss ("68 65 6C 6C 6F 20 77 6f 72 6c 64 21");
            iss >> std::hex;
            std::istream_iterator<unsigned short> in (iss);
            std::vector<unsigned char> v (in, std::istream_iterator<unsigned short> ());
            std::copy (v.begin (), v.end (), std::ostream_iterator<unsigned char> (std::cout));
            // affiche bien hello world!
     
            return 0;
    }
    Je ne prétends pas non plus qu'il n'y ait pas plus performant, voire adapté ? (surtout que le C++ n'est pas le langage que je pratique ou maîtrise le mieux), mais en attendant il veux mieux une solution qui fonctionne même moins bien non ?

    Cordialement !

  6. #6
    Membre très actif
    Homme Profil pro
    Second de cuisine
    Inscrit en
    Avril 2005
    Messages
    193
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Second de cuisine
    Secteur : Alimentation

    Informations forums :
    Inscription : Avril 2005
    Messages : 193
    Par défaut
    Voici une classe pour faire tout le boulot ^^

    Header:
    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
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    #ifndef PACKET_H
    #define PACKET_H
     
     
    #include <string.h>
    #include <string>
     
    using namespace std;
     
    class Packet
    {
        public:
            Packet() {}
            Packet(char* buffer) :
                packet(buffer),
                pos(0),
                length(strlen(buffer))
            {}
            virtual ~Packet() { delete packet; }
     
            const unsigned short        ReadShort();
            const unsigned int          ReadInt();
            const unsigned long long           ReadLong();
            const string&                      ReadString(unsigned short length);
     
            const char* Buffer() { return packet; }
            void Skip() { pos += 3; }
     
        protected:
        private:
            char* packet;
            int pos;
            int length;
     
    };
     
    inline unsigned short htos(char h, int shift)
    {
        switch(h)
        {
            case 'a':
            case 'A':
                return 10 << shift;
                break;
            case 'b':
            case 'B':
                return 11 << shift;
                break;
            case 'c':
            case 'C':
                return 12 << shift;
                break;
            case 'd':
            case 'D':
                return 13 << shift;
                break;
            case 'e':
            case 'E':
                return 14 << shift;
                break;
            case 'f':
            case 'F':
                return 15 << shift;
                break;
            default:
                return (h-'0') << shift;
                break;
        }
    }
     
    #endif // PACKET_H
    Cpp:
    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
    #include "Packet.h"
     
    const unsigned short Packet::ReadShort()
    {
        unsigned short b = static_cast<unsigned short>((htos(packet[pos], 4) | htos(packet[pos+1], 0)) & 0xff);
        Skip();
        return b;
    }
    const unsigned int Packet::ReadInt()
    {
        return static_cast<int>(((ReadShort() << 8) & 0xffff) + ReadShort());
    }
    const unsigned long long Packet::ReadLong()
    {
        return static_cast<long long>(((ReadInt() << 16) & 0xffffffff) + ReadInt());
    }
    const string& Packet::ReadString(unsigned short length)
    {
        if(pos + (length*2 + (length-1)) > strlen(packet))
        {
            //exit(0); // cela ne devrait jamais arriver.
        }
        string out;
        for(int i = 0; i < length; ++i)
        {
            out += char(((htos(packet[pos],4) | htos(packet[pos+1], 0)) & 0xff));
            Skip();
        }
        return out;
    }
    Maintenant nous allons tester cette classe
    Le packet a pour 'structure'
    [short] [string] [long] [int] [short]
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
        Packet p = Packet("08 42 6f 6e 6a 6f 75 72 21 ad 52 01 03 99 ff 50");
        short length = p.ReadShort();
        string A = p.ReadString(length);
        long long L = p.ReadLong();
        int I = p.ReadInt();
        short S = p.ReadShort();
        // on affiche :p
        cout << A << endl;
        cout << "long = " << L << endl << "int = " << I << endl << "short = " << S << endl;
    Résultat:
    Bonjour!
    long = 2907832579
    int = 39423
    short = 80
    Merci à tous :]

    J'accepte avec plaisir des améliorations de ma classe niveau performances !

    nico

Discussions similaires

  1. Split une chaine de caractere
    Par steeves5 dans le forum Général Java
    Réponses: 3
    Dernier message: 06/03/2008, 16h47
  2. Réponses: 9
    Dernier message: 06/11/2007, 12h36
  3. Extraire un nom d'une chaine de caractere
    Par iamspacy dans le forum Linux
    Réponses: 4
    Dernier message: 03/05/2004, 21h34
  4. Réponses: 2
    Dernier message: 30/03/2004, 11h31
  5. Controler une chaine de caracteres ou d'entiers?
    Par Le druide dans le forum C
    Réponses: 6
    Dernier message: 25/09/2003, 08h48

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