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

Embarqué Discussion :

Trouver l'indice d'une chaine à partir d'un mot


Sujet :

Embarqué

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Septembre 2007
    Messages
    36
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Septembre 2007
    Messages : 36
    Points : 7
    Points
    7
    Par défaut Trouver l'indice d'une chaine à partir d'un mot
    Bonjour à tous,
    j'utilise pour un systeme embarqué, un buffer circulaire recevant des données venant d'un port série. J'aimerai analyse ces données.
    C'est basé sur des commandes AT pour GSM.
    Dès que je recois un texto, le buffer se remplit et recoit +CGMI:"1" pour dire 1 texto recu.
    J'ai fait un if (strstr(buffer, "CGMI") != 0 ) pour savoir si j'ai recu un texto. Ensuite, j'appuie sur un bouton qui envoie la commande pour afficher les textos non lus. Du coup, apparaissent les textos non lus dans le buffer.
    J'aimerai les stocker dans un autre buffer.
    Comment m'y prendre ?
    J'ai pensé à une fonction du genre:
    qui trouve où est écrit UNREAD (le message se situe apres le mot UNREAD dans le buffer). et qui copie tout ce qu'il y a après jusqu'au mot "OK". (qui est situé à la fin).
    Ma question est donc: comment faire, en langage C, une fonction qui trouve un mot (UNREAD), et qui, à partir de ce mot, jusqu'à un autre mot (OK), copie les caractères dans un buffer?
    Merci d'éclairer ma lanterne.

  2. #2
    Membre chevronné

    Homme Profil pro
    .
    Inscrit en
    Janvier 2006
    Messages
    703
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : .

    Informations forums :
    Inscription : Janvier 2006
    Messages : 703
    Points : 1 950
    Points
    1 950
    Par défaut
    Pourrais-tu copier ton code actuel s'il te plaît (avec les balises CODE associées) ? Ou tu peux détailler plus à la limite. J'ai du mal à comprendre ce que tu cherches à faire.

    Mais ça m'a l'air d'être une manipulation de string classique. Si je crois comprendre ce que tu veux, utiliser strstr puis strncpy devrait suffire.

    C'est à dire avoir le pointeur de la chaine UNREAD, puis le pointeur de OK. (pointeurs retournés par strstr), puis en faisant le diff des pointeurs tu as la différence en octets. Tu n'as alors plus qu'à copier avec un strncpy depuis la position de "UNREAD"+1

    Sinon, quoi qu'il en soit, je t'invite à regarder du côté du header "strings.h"

    Si tu es sous Linux :

    et man <nom_de_la_fonction>

    Sinon, tu cherches le .h en question dans tes dossiers includes.
    Et si en regardant les explications relatives à ces fonctions tu ne trouves toujours pas, décris nous plus ton problème.

  3. #3
    Futur Membre du Club
    Profil pro
    Inscrit en
    Septembre 2007
    Messages
    36
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Septembre 2007
    Messages : 36
    Points : 7
    Points
    7
    Par défaut
    Merci de ta réponse.
    Voici l'interruption de mon GSM, et le buffer circulaire qui se remplit:
    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
    void Usart0IrqHandler (void)
    {
      volatile AT91PS_USART pUsart0 = AT91C_BASE_US0; // create a pointer to USART0 structure
      if ((pUsart0->US_CSR & AT91C_US_RXRDY) == AT91C_US_RXRDY   )
      {
        
        char ch;
    
        ch = pUsart0->US_RHR;
    
        Buffer_gsm[end] = ch;
        end = (end + 1) % BUFFER_SIZE;
        if (active < BUFFER_SIZE)
        {
            active++;
        } else {
            /* Overwriting the oldest. Move start to next-oldest */
            start = (start + 1) % BUFFER_SIZE;
        }
       /* if (strstr(Buffer_gsm, "+CMTI") != 0 ){
          drawEnvelop(TRUE);
          memset(Buffer_gsm, '\0', BUFFER_SIZE);
        }*/
      }   
    }
    J'obtiens donc un buffer appelé Buffer_gsm, qui, quand je recois un sms, se remplit.
    à l'appel de la lecture du SMS dans le main, après avoir appuyé sur un bouton:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
          
          if (flag_but){
            memset(Buffer_gsm,'\0',BUFFER_SIZE);
            LCDClearScreen();
            drawEnvelop(FALSE);
            send_gsm_command("AT+CMGL=\"REC UNREAD\"");
            LCDPutStr("READING new SMS...",35,5, SMALL, WHITE,RED);
            Wait(2000);
            flag_but = 0;
            LCDClearScreen();
            LCDPutDefinitions();
          }
    j'envoie une AT commande qui lit les nouveaux SMS.
    Le buffer se remplit donc de ce SMS.
    Je veux simplement le récupérer.
    Dans le buffer apparait le mot REC UNREAD, suivi du SMS, et se termine par Ok.

  4. #4
    Membre chevronné

    Homme Profil pro
    .
    Inscrit en
    Janvier 2006
    Messages
    703
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : .

    Informations forums :
    Inscription : Janvier 2006
    Messages : 703
    Points : 1 950
    Points
    1 950
    Par défaut
    D'accord ! Donc ma technique s'adapte bien à ton cas.
    Utilise strstr pour :
    • trouver la position de "UNREAD"+1
    • trouver la position de "OK"


    Tu fais la différence des pointeurs retournés, tu obtiens la taille.
    Tu n'as alors plus qu'à faire un strncpy à partir du pointeur de char qui pointe sur "UNREAD"+1

    et voilà

  5. #5
    Futur Membre du Club
    Profil pro
    Inscrit en
    Septembre 2007
    Messages
    36
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Septembre 2007
    Messages : 36
    Points : 7
    Points
    7
    Par défaut
    J'ai suivi tes indications, et j'en sors ç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
    #include <stdio.h>
    
    
    int main (void){
    
    char buffer[100] = "avant le mot REC UNREAD salut je suis le sms OK \0";
    char sms[50];
    memset(sms,'\0', sizeof(sms));
    int taille=0;
    char *p;
    char *q;
    
    if ( (strstr(buffer, "REC UNREAD") != 0 ) && (strstr(buffer, "OK") != 0) ) {
        p = strstr(buffer, "REC UNREAD") + 10;
        q = strstr(buffer, "OK");
    
    }
    
    taille = q - p ;
    strncpy(sms, p, taille);
    
    printf("%s", sms);
    
    return 0;
    }
    ça marche parfaitement.
    Maintenant vient le probleme du buffer circulaire...si j'arrive à la fin de mon buffer, et que le sms n'est pas encore terminé, comment retourner au début?
    car dans ce cas là, le mot OK sera placé avant REC UNREAD, ce qui posera un probleme avec la taille...

  6. #6
    Membre chevronné

    Homme Profil pro
    .
    Inscrit en
    Janvier 2006
    Messages
    703
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : .

    Informations forums :
    Inscription : Janvier 2006
    Messages : 703
    Points : 1 950
    Points
    1 950
    Par défaut
    Pour ça je pense qu'il faut augmenter la taille de ton buffer.
    Ou opter pour autre chose qu'un buffer circulaire.

  7. #7
    Membre averti
    Homme Profil pro
    Enseignant
    Inscrit en
    Mars 2012
    Messages
    164
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2012
    Messages : 164
    Points : 356
    Points
    356
    Par défaut
    À ta place Arneau405, j’utiliserais un buffer linaire (avec l'index initialisé à 0 au début de la réception d'une nouvelle commande)

    Sinon faudrait te faire une petite fonction qui copie le contenu du buffer circulaire dans un buffer linéaire, puis utiliser la stratégie proposée par Aquanum.

    Si j'avais à résoudre ton problème arnaud405, je m'y prendrais d'une autre manière. Si tu me permets un petit jugement de valeur (c'est très sujectif la programmation), j'ai beaucoup de difficulté avec le "Wait(2000)" dans ton code. Geler un système pendant 2 secondes, je suis pas sûr que c'est une bonne idée. Le petit grille-pain vert Android est encore plus drastique, il va tout simplement tuer l'application quand il trouve que ça niaise trop

    Perso, j'irais avec une approche événementielle. Grosso modo, j'écrirais un module qui accumulerait la commande reçu en arrière plan en décortiquant la commande "on the fly", puis, quand c'est terminé, j appellerais une fonction de rappel dans l'activité principale du genre:

    (en C++)
    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
    TCmdInfo
    {
       int type ; // type de commande
       char Data ; // donnée extraite de la commande
    } ;
    
    void  CommandReceivedHandler(TCmdInfo info)
    // appelé quand commande recu
    {
       switch (info.type)
       {
          case SMS_CMD: TreatSmsCmd(info.data) ;
                                   break ;
          // autres commandes
       }
    }
    Si t'es en Java ou quelque chose du genre, la fonction de rappel devient une méthode dans un interface.

    Si ça t'intéresse, je pourrais élaborer sur le traitement en "background" de la commande.


    tourlou!

  8. #8
    Futur Membre du Club
    Profil pro
    Inscrit en
    Septembre 2007
    Messages
    36
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Septembre 2007
    Messages : 36
    Points : 7
    Points
    7
    Par défaut
    ok. Merci de tes conseils. Le Wait(2000) était là pour afficher pendant 2sec la phrase Reading SMS sur l'écran.
    Sinon j'ai tout simplement trouvé cette fonction sur internet:
    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
    char *str_sub (const char *s, unsigned int start, unsigned int end)
    {
       char *new_s = NULL;
    
       if (s != NULL && start < end)
       {
    /* (1)*/
          new_s = malloc (sizeof (*new_s) * (end - start + 2));
          if (new_s != NULL)
          {
             int i;
    
    /* (2) */
             for (i = start; i <= end; i++)
             {
    /* (3) */
                new_s[i-start] = s[i];
             }
             new_s[i-start] = '\0';
          }
          else
          {
             fprintf (stderr, "Memoire insuffisante\n");
             exit (EXIT_FAILURE);
          }
       }
       return new_s;
    }
    qui fait ce que je veux. Cependant, mon systeme plante apres une dizaine de passages...Je n'arrive pas à voir pourquoi. Surement un probleme de mémoire?

  9. #9
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    La fonction fait un malloc(), fais-tu le free() associé ?

    D'ailleurs, elle fait quoi quand "elle plante" ?

  10. #10
    Futur Membre du Club
    Profil pro
    Inscrit en
    Septembre 2007
    Messages
    36
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Septembre 2007
    Messages : 36
    Points : 7
    Points
    7
    Par défaut
    Il n'y a pas le free justement, c'est ce qui m'étonnait... Mais où le mettre? si je libère avant le return, je vais perdre mes données non ?

  11. #11
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par arnaud405 Voir le message
    Il n'y a pas le free justement, c'est ce qui m'étonnait... Mais où le mettre? si je libère avant le return, je vais perdre mes données non ?
    La programmation, ce n'est pas de la divination

    Il faut réfléchir à ce qui est fait et dans quel ordre. Cette fonction alloue de la mémoire, y met des informations et renvoie un pointeur pour que cette zone (et donc ce texte) soit accessible en dehors de la fonction. Dans un cas comme celui-ci, la libération de la mémoire ne peut pas être dans la fonction elle-même (comme tu l'as dit, tu perds cette zone). Il faut donc la libérer dans la fonction appelante, une fois que tes données auront été traitées et ne sont plus utiles. Schématiquement :
    • Réception du SMS
    • Extraction de la sous-chaine avec malloc --> ta fonction str_sub()
    • Utilisation de données extraites
    • Libération mémoire
    • Réception d'un second SMS
    • Etc...



    Citation Envoyé par Guyt54
    J'aime pas la fonction str_sub que tu utilises, parce que c'est elle qui alloue la mémoire dynamique exactement à la taille de la sous-chaine. Et si ça me tente plus tard d'ajouter des caractères à la chaine créée? Ou d'utiliser mon propre tableau?
    Elle pourrait aussi faire le café la fonction Il faut des fois savoir décider de ce que fait la fonction. Une fonction pour récupérer une sous-chaine, ça me parait pas mal que la zone allouée fasse la taille de la sous-chaine. Après, chacun son choix et ses besoins.


    Citation Envoyé par Guyt54
    En plusse une fonction de bas niveau qui écrit des messages d'erreurs et fait des "exit"
    En plus, je partage totalement cet avis ! Il faut mieux renvoyer NULL (ou un code retour si on veut distinguer les cas) et c'est à la fonction de plus haut niveau de gérer. Surtout, pour le exit() !


    EDIT : ah le coquinou de Guyt54 qui a supprimé son message !

  12. #12
    Membre averti
    Homme Profil pro
    Enseignant
    Inscrit en
    Mars 2012
    Messages
    164
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2012
    Messages : 164
    Points : 356
    Points
    356
    Par défaut
    Encore un peu de négativisme!

    J'aime pas la fonction str_sub que tu utilises, parce que c'est elle qui alloue la mémoire dynamique exactement à la taille de la sous-chaine. Et si ça me tente plus tard d'ajouter des caractères à la chaine créée? Ou d'utiliser mon propre tableau?

    Et puis, ça m'insécurise toujours de voir un "malloc" sans voir le "free" pas trop loin. En plusse une fonction de bas niveau qui écrit des messages d'erreurs et fait des "exit"...
    *
    La fonction, je la réécrirais comme ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
    void substr(char* dest, const char* src,  int fromIndex, int toIndex, int maxChars)
    {
       int destIndex ;
      
        destIndex = 0 ;
        while ( (fromIndex <= toIndex) && (destIndex < maxChars))
        {
           dest[destIndex++] =  src[fromIndex++]  ;
        }
       dest[destIndex] = NULL ;
    }
    Comme ça, c'est toi qui décides où vont les caractères et pas la fonction, par exemple:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    void traitement(void)
    {
       char sousCommande[256] ; 
      
       subStr(sousCommande,"abcdefghij",4,5,255) ;
       // bla bla 
    }

  13. #13
    Futur Membre du Club
    Profil pro
    Inscrit en
    Septembre 2007
    Messages
    36
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Septembre 2007
    Messages : 36
    Points : 7
    Points
    7
    Par défaut
    Merci beaucoup de vos réponses.
    Je n'y vois pas que de la négativité, au contraire, j'aime beaucoup avoir les avis, et des avis expliqués non juste des critiques balancées comme ça.
    J'étudie ça de plus près et vous tiens au courant.

  14. #14
    Membre averti
    Homme Profil pro
    Enseignant
    Inscrit en
    Mars 2012
    Messages
    164
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2012
    Messages : 164
    Points : 356
    Points
    356
    Par défaut
    Bon voilà arnaud405,

    Ton problème m'intéressait, alors juste pour le fun j'ai élaboré une solution plus globale au traitement d'une trame de caractères ascii délimitée par un "header" et un "footer".

    Même si je l'ai fait pour moi, j’apprécierais que tu regardes sérieusement le code, j'ai mis pas mal de temps là-dessus, histoire d'y inclure les trois principes qu'y m'apparaissent fondamentaux en programmation "moderne", soit:

    1) La programmation modulaire
    2) La programmation orientée objet (même avec du C)
    3) La programmation événementielle

    Bon, on y va.

    On suppose que l'on reçoit une la trame caractère par caractère, par exemple d'un port sériel. La trame est du type:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    <header> data <footer>
    où:
    <header>: caractères annonçant le début des données
    <footer>: caractères annoncant la fin de la trame
    À défaut de trouver mieux, j'ai appelé ce type de trame un "TComData". Un exemple de "TComData" que j'utilise avec mes étudiants:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    <-P1W2F->
    où:
    "<-": header
    "PAW2F": donnée (commande "Write 2F (0010 1111) to port A")
    "->" : footer
    L'idée, c'est qu'on appelle une fonction de traitement pour chacun des caractères reçus. Quand une trame aura été reçu, une fonction de rappel sera appelé automatiquement et on pourra récupérer les données (string terminée par un NULL), où les délimiteurs de commandes auront été enlevés.

    J'ai ramassé les fonctions qui font la job dans un module. Si mon module est bien pensé, il devrait être facile à utiliser. Je te montre ici un exemple (non testé) d'utilisation du module (testé), en supposant que les caractères proviennent du clavier. La trame sera affichée à l'écran lorsque reçue:
    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
    #include "TComData.h"
    
    #define HEADER "<-"
    #define FOOTER "->"
    #define MAX_DATA 80
    
    void ReceivedDataHandler(const char* dateStr)
    // appelée automatiquement lorsqu'une trame est recu
    {
       char data[MAX_DATA+1] ;
       strcpy(data,dataStr) ;
       // tu fais ce que tu veux avec "data", par exemple
       printf("\nData received=%s\n",data) ;
    }
    
    void main(void)
    {
      TComData comData ;
    
      bool done = false ;
      char car ;
    
      TComDataInit(&comData,HEADER,FOOTER,MAX_DATA,ReceivedDataHandler) ;
      while (!done)
      {
         car = getche() ;
         if (car == 'x') // "x" pour quitter
           done = true ;
         else
          TComDataTreatRxChar(&comData,car) ;
      }
      TComDataDone(&comData) ;
    }
    La fonction-clé du module "TComData" est:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    TComDataInit(&comData,HEADER,FOOTER,MAX_DATA,ReceivedDataHandler) ;
    Tu y précises le header, le footer, le nombre max ce car. dans la donnée et finalement, le nom de la fonction qui sera appelé automatiquement à la réception d'une trame.

    La fonction "TComDataTreatRxChar" devra évidemment être appelée pour chaque car reçu.

    Tu remarqueras que les fonctions du module "TComData" ont toujours comme premier paramètre l'adresse d'une structure de type "TComData", que tu devras définir. Son contenu? des données "privées" utilisées par la les fonctions du module. En véritable programmation orientée objet, cette structure serait cachée.

    Voici le code du module en question, que j'ai testé dans une application Windows (et non en console) en C++, mais le code est du "C" très standard (sauf le type "bool").

    L'interface du module (TComData.h) :
    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
    // TComData.h
    
    ifndef TCOMDATA_H
    #define TCOMDATA_H
    
    typedef void (*TComDataReceivedHandler) (const char* comData) ;
    
    typedef struct
      {
    
        TComDataReceivedHandler RxDataHandler ;
        char* Header ;
        int   HeaderLength ;
        char  HeaderIndex;
        bool  HeaderIn ;
    
        char* Footer ;
        int   MaxDataLength ;
        char* Buffer ;
        int   BufferLength ;
        int   BufferIndex ;
      }  TComData ;
    
    void TComDataInit(TComData* comData, char* header, char* footer,
                      int maxDataChars, TComDataReceivedHandler rxDataHandler) ;
    
    void TComDataDone(TComData* comData) ;
    
    void TComDataReset(TComData* comData) ;
    
    void TComDataTreatRxChar(TComData* comData, char car) ;
    
    #endif
    L'implémentation du module (TComData.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
    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
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    // TComData.cpp
    #include "TComData.h"
    #include <stdlib.h>
    #include <string.h>
    
    void TComDataInit(TComData* comData,
                      char* header,
                      char* footer,
                      int maxDataChars,
                      TComDataReceivedHandler rxDataHandler
                      )
    // initialisation
    {
      int size ;
    
      size = strlen(header) ;
      comData->HeaderLength = size ;
      comData->Header = (char*)malloc(size+1) ;
      strcpy(comData->Header,header) ;
    
      size = strlen(footer) ;
    
      comData->Footer = (char*)malloc(size+1) ;
      strcpy(comData->Footer,footer) ;
    
      comData->MaxDataLength = maxDataChars ;
    
      // le buffer va inclure temporairement le footer
      size = maxDataChars + strlen(footer) ;
      comData->Buffer = (char*) malloc(size+1) ;
      comData->BufferLength = size ;
      TComDataReset(comData) ;
      comData->RxDataHandler =  rxDataHandler ;
    }
    
    void TComDataDone(TComData* comData)
    // terminaison
    {
      free(comData->Header) ;
      free(comData->Footer) ;
      free(comData->Buffer) ;
    }
    
    void TComDataReset(TComData* comData)
    // Appelée automatiquement après la réception d'une commande mais peut
    // être appelée pour réinitialiser la lecture d'une nouvelle trame
    {
      comData->HeaderIn = false ;
      comData->HeaderIndex = 0 ;
      comData->BufferIndex = 0 ;
    }
    
    void TComDataTreatRxChar(TComData* comData, char car)
    // Traitement car recu
    {
      int index ; // utilisé pour minimiser acces indirect
      char* footerPtr ;
    
      if (!comData->HeaderIn)
      {   // le header n'a pas été ebcore recu
         index = comData->HeaderIndex ;
         if (car != comData->Header[index])
            index = 0 ;
         else
         {  // caractre fait parti du header
            index++ ;
            comData->HeaderIn =  (index == comData->HeaderLength) ;
         }
        comData->HeaderIndex =  index ;
      }
      else
      { // le heaader a été recu
        index = comData->BufferIndex ;
        if (index >= comData->BufferLength)
        { // on vérifie overflow
          strcpy(comData->Buffer,"overflow") ;
          comData->RxDataHandler(comData->Buffer) ;
          TComDataReset(comData) ;
        }
        else
        { // on ajoute caractere
          comData->Buffer[index] = car  ;
          comData->Buffer[index+1] = NULL ;
          footerPtr = strstr(comData->Buffer,comData->Footer) ;
          if (footerPtr != NULL)
          {  // le footer a été recu, on appelle la fonction de "callback"
             index = footerPtr - comData->Buffer;
             comData->Buffer[index] = NULL ;
             comData->RxDataHandler(comData->Buffer) ;
             TComDataReset(comData) ;
          }
          else
          {  // footer non recu
            comData->BufferIndex++ ;
          }
        }
      }
    }
    Tourlou!

  15. #15
    Futur Membre du Club
    Profil pro
    Inscrit en
    Septembre 2007
    Messages
    36
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Septembre 2007
    Messages : 36
    Points : 7
    Points
    7
    Par défaut
    J'ai lu ça de très près. C'est très détaille et très "clair".
    Ce que je fais est du bidouillage qui marche. Mais c'est clair que codé comme ça, ça a déjà beaucoup plus de forme.
    Je vais m'amuser à tester tout ça dans un autre projet.
    Merci beaucoup pour le partage.

Discussions similaires

  1. Extraire une chaine à partir d'un mot clé
    Par ouinih dans le forum PL/SQL
    Réponses: 3
    Dernier message: 19/10/2010, 09h25
  2. Extraction d'une chaine à partir d'une photo
    Par Julaie95 dans le forum Traitement d'images
    Réponses: 31
    Dernier message: 23/05/2006, 15h44
  3. Creation d'une chaine à partir d'un tuple
    Par Bayard dans le forum Général Python
    Réponses: 2
    Dernier message: 19/01/2006, 11h25
  4. Trouver la position d'une chaine
    Par xave dans le forum Langage
    Réponses: 2
    Dernier message: 04/10/2005, 13h48
  5. Trouver un fichier contenant une chaine ?
    Par narmataru dans le forum Linux
    Réponses: 2
    Dernier message: 29/04/2004, 10h49

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