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 :

parsage de chaine


Sujet :

C

  1. #1
    Membre éprouvé
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    1 821
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 1 821
    Points : 979
    Points
    979
    Par défaut parsage de chaine
    Bonjour,

    J'ai une chaine de caractère à parser qui représente une liste de nombre. Cette chaine ne contient pas d'espace et chaque nombre est séparé par le caractère ',' ou '-'.
    Le résultat est stocké dans la variable valRet (signed int de 32bits). Si j'ai le nombre 1 dans ma chaine, alors je dois mettre le premier bit de valRet à 1; si j'ai le nombre 2 dans ma chaine, alors je dois mettre le second bit de valRet à 1...


    Donc :
    si j'ai la chaine "1,3,4,11", je dois avoir comme résultat 0b10000001101 (nombres 1 et 3 et 4 et 11)
    si j'ai la chaine "1-3", je dois avoir comme résultat 0b111 (nombres de 1 à 3)
    => J'espère que vous avez compris le principe

    Autres règles :
    - Si j'ai une erreur de parsing, je dois avoir comme valeur de retour -1.
    - Si j'ai la chaine "none", je dois avoir comme valeur de retour 0 (designe une liste vide).
    - Si j'ai la chaine "all", je dois avoir comme valeur de retour 0x7FFFFFFF (désigne tous les éléments de la liste).
    => vu que j'utilise un signed int de 32 bits, je dois donc générer une erreur s'il y a un nombre supérieur à 31 ou inférieur à 1.

    Je pensais partir sur l'utilisation de sscanf mais a priori ce n'est pas le bonne méthode : comment feriez vous ?

    --------------------------------
    Amélioration de mon algo :
    J'aimerais aussi pourvoir rajouter des noms pour définir un nombre (ex: toto = 1, tutu = 3, ...).
    si j'ai la chaine "toto,tutu,4", je dois avoir comme résultat 0b1101 (nombres 1 et 3 et 4)

    Mon algo ne doit pas être sensible à la casse.


    Merci d'avance

    PS : je ne dois pas utiliser de malloc car je programme sur un µControlleur

  2. #2
    Membre expérimenté

    Homme Profil pro
    Collégien
    Inscrit en
    Juillet 2010
    Messages
    545
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Afghanistan

    Informations professionnelles :
    Activité : Collégien

    Informations forums :
    Inscription : Juillet 2010
    Messages : 545
    Points : 1 429
    Points
    1 429
    Par défaut
    Pas simple ton histoire...

    Je pense que tu peut oublier le sscanf si tu est sur un uC, (Voir la libC fournie avec le micro, en plus je pense que sscanf utilise le malloc/free).

    Si tu est dans un environnement où la librairie standard est limitée, je pense qu'il faut commencer par réécrire certaines procédure de string.h, comme

    strncmp, isdigit etc...

    Après il faut te lancer... C'est un fonction complexe que tu demande, ne t'attend pas a avoir une solution complète est fonctionnelle directement postée sur le forum..

    Bon courage.

  3. #3
    Membre éprouvé
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    1 821
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 1 821
    Points : 979
    Points
    979
    Par défaut
    oki, je suis entrain de réfléchir...

    Pour le moment, je vois comment récupérer un pointeur sur le début de chaque élément (ensuite, je modifie les '-' et les ',' par des '\0').
    => comment on fait ensuite, pour convertir ma sous-chaine en nombre ?

    je pensais utiliser cette solution :
    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
     
    INT8 convertStrToNumber(UINT8 *str){
     
        int val;
        int result;
    	UINT8 loc_str[2];
     
    	result = sscanf(str, "%d%1s", &val, loc_str);
    	if (result == 1){ // la conversion a réussi
    		if (
    			(val >= MAX_VAL) ||
    			(val < 0)
    		){
    			return -1; // erreur
    		} else {
    			return val;
    		}
    	}
     
    	return -1; // erreur
    }
    => mais vu que tu me dis que sscanf utilise des malloc, ça ne va pas aller...

  4. #4
    Membre expérimenté

    Homme Profil pro
    Collégien
    Inscrit en
    Juillet 2010
    Messages
    545
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Afghanistan

    Informations professionnelles :
    Activité : Collégien

    Informations forums :
    Inscription : Juillet 2010
    Messages : 545
    Points : 1 429
    Points
    1 429
    Par défaut
    Je vois plus un truc comme ca:
    Mais c'est façon de voir les choses. Il existe plusieurs solution a ce problème

    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
    int32_t convertStrToNumber(const char *str, size_t str_len)
    {
        size_t cmp_len = min(str_lenn,strlen("all"));
        if(strncmp(str,"all",cmp_len) == 0){return 0x7FFFFFFF;}
        cmp_len = min(str_lenn,strlen("none"));
        if(strncmp(str,"none",cmp_len) == 0){return 0x0;}
     
        char c;
        unsigned int i = 0;
        int32_t return_value = 0;
        bool exit_loop = false;
        while(((c = str[i++]) != \'0') && !exit_loop)
        {
            if(isdigit(c))
            {   /* mettre a '1' le c ème bit*/
                unsigned int bit = (c-'0');
                if(bit >= 0 && bit < 32)
                {
                     return_value |= 1<<bit ;
                 }
                 else
                 {
                      exit_loop = true;
                      return_value = -1;
                 }
            }
            else if(ispace(c))
            {
     
            }
            else if(c == '-')
            {
     
            }
            else
            {   /* erreur*/
                exit_loop = true;
                return_value = -1;
            }
        }
        return return_value;
    }

  5. #5
    Membre éprouvé
    Profil pro
    Inscrit en
    Septembre 2009
    Messages
    1 821
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 1 821
    Points : 979
    Points
    979
    Par défaut
    Bon, j'ai fais ça mais je pense que ça doit largement optimisable :
    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
     
    // recuperation d'une liste de nombre dans une chaine
    // => attention, cette fonction modifie la chaine a parser
    #define PARSINGVAL_NONE  (0x00000000)
    #define PARSINGVAL_ALL   (0x7FFFFFFF)
    #define PARSINGVAL_ERROR (0xFFFFFFFF)
    UINT32 parseListeNumber(UINT8 *str){
    	UINT8 i;
    	UINT8 nbElements;
    	UINT8 *ptChar;
    	UINT8 *ptCharStart;
    	UINT32 ret;
    	INT32 val, oldVal;
    	UINT8 delim;
     
    	nbElements = 0;
    	ret = 0;
    	ptChar = str;
     
     
    	oldVal = -1;
    	while(*ptChar != '\0'){
    		ptCharStart = ptChar;
     
    		while(
    			(*ptChar != ',') && 
    			(*ptChar != '-') && 
    			(*ptChar != '\0') 
    		){
    			ptChar++;
    		};
     
    		if(ptChar == ptCharStart){
    			return PARSINGVAL_ERROR; // erreur
    		}
     
    		nbElements++;
     
    		delim = *ptChar;
    		*ptChar ='\0';
     
    		val = atoi(ptCharStart); // recuperation du nombre
     
    		// TODO
    		if(val == 0){
    			// rechercher si la sous-chaine correspond à un nom défini
    			// ...
    		}
     
     
    		if((val < 1) || (val > 31)){
    			return PARSINGVAL_ERROR; // erreur
    		}
     
    		if(delim == '-'){
    			if(nbElements > 1){
    				return PARSINGVAL_ERROR; // erreur
    			}
    			oldVal = val;
    		}
     
     
    		if(oldVal != -1){ // delimiter '-' trouvé précédement
    			if(oldVal >= val){
    				return PARSINGVAL_ERROR; // erreur
    			}
     
    			for(i=oldVal; i<val; i++){
    				ret &= (1 << i);
    			}
     
    		} else {
    			ret &= (1 << val);
    		}
     
    	}
     
    	return ret;
    }

Discussions similaires

  1. [Batch] [Exp.reg. ou parsage] isoler la derniere chaine de caracteres.
    Par gretch dans le forum Scripts/Batch
    Réponses: 6
    Dernier message: 02/06/2011, 18h50
  2. tri de liste chainée
    Par RezzA dans le forum C
    Réponses: 7
    Dernier message: 26/01/2003, 20h25
  3. [TP]lire une ligne de l'ecran et la stocker dans une chaine
    Par Bleuarff dans le forum Turbo Pascal
    Réponses: 26
    Dernier message: 02/07/2002, 10h08
  4. Réponses: 3
    Dernier message: 12/06/2002, 21h15
  5. Probleme sur les chaines de caractere
    Par scorpiwolf dans le forum C
    Réponses: 8
    Dernier message: 06/05/2002, 19h01

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