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 :

Conversion de nombre en base 36


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut Conversion de nombre en base 36
    Salut,


    Je souhaiterais manipuler des nombres en base 36 dans des chaines de caractères.

    J'arrive déjà à convertir une chaine représentant un nombre en base 36 vers une variable de type long long (ce qui m'est nécessaire étant donné la longueur de certaines valeur) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    long long value = strtoll("zz", NULL, 36); // donne 1295

    Mais je n'arrive pas à faire l'inverse, c'est à dire à transformer une variable long long en chaine de caractère en base 36. C'est à dire que je voudrais à partir de 1295 obtenir la chaine "zz".

    Malheureusement je suis bloqué : je ne trouve pas la fonction inverse de strtoll(). Apparemment il existe une fonction lltostr() sur certain système mais elle ne gère que la base 10...


    Bref : comment convertir un nombre de type long long en base 36 ?


    d'avance

    a++

  2. #2
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Salut,


    Bon en cherchant encore j'ai trouvé l'algo permettant la conversion. C'est en fait assez simple puisqu'il suffit de diviser la valeur par la base pour obtenir les chiffres/lettres de droite à gauche...

    Ce qui donne :
    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
    /*------------------------------------------------------*/
    /* Convertion d'un nombre dans une base spécifique      */
    /*------------------------------------------------------*/
    /* Paramètres :                                         */
    /* ------------                                         */
    /* value :      La valeur à convertir.                  */
    /* ptr :        La chaine de destination.               */
    /* maxlen :     Longueur maximum de la chaine.          */
    /* base :       Base à utiliser.                        */
    /*------------------------------------------------------*/
    /* Retour :                                             */
    /* --------                                             */
    /* Nombre de caractères insérés dans la chaine.         */
    /*------------------------------------------------------*/
    int lltostr(long long value, char *ptr, int maxlen, int base) {
    long long nb;
    int r;
    int i, sz;
    char c;
    char tmp[maxlen];
     
    memset(tmp, 0, sizeof(tmp));
    sz = 0;
    nb = value;
    do {
            /* On calcule le reste de la division */
            r = nb % base;
     
            if (r<=9) {
                    /* Si le reste est inférieur à 9, on utilise les chiffres : */
                    c = '0' + r;
            } else {
                    /* Sinon on utilise les lettres : */
                    c = ('a'-10) + r;
            }
            /* On ajoute le nouveau caractère dans le tableau : */
            tmp[sz++] = c;
     
            /* On calcule le quotient en divisant par la base : */
            nb = nb / base;
    } while(nb!=0 && sz!=maxlen);
     
    /* Si on a atteint la taille max on renvoi une erreur */
    if (sz>=maxlen) {
            return -1;
    }
    /* Sinon on reconstruit la chaine en sens inverse : */
    for (i=0; i<sz; i++) {
            ptr[i] = tmp[sz-1-i];
    }
    return sz;
    }

    Mais je reste à l'écoute si quelqu'un a une solution un peu plus standard

    a++

  3. #3
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Plutot que supposer que les lettres sont adjacantes (ce qu'elles ne sont pas en EBCDIC), indexer un tableau "0123456789ABCDE...Z" (ce qui a l'avantage supplementaire de ne pas devoir separer les cas 0-9 des autres).

    J'aurais eu tendance a construire la chaine directement dans la destination (avec des -- plutot que des ++) et en la recopiant avec memmove a la position finale (pas memcpy qui ne supporte pas les recouvrements). Mais c'est aussi un peu fonction de la spec qui peut preciser que la destination n'est pas modifiee en cas d'erreur. Ca evite l'utilisation des VLA, qui sont du C99 ou une extension de gcc. Note qu'une borne superieure est facile a trouver (sizeof(long long)*CHAR_BIT+1)

  4. #4
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Salut,

    Pas bête l'idée du tableau ! Pour le memmove() ce pourrait être pratique en effet... même si je n'en ai pas vraiment l'utilité (la fonction ne sera pas appelé beaucoup de fois et je ne pense pas m'embêter avec cela).

    Citation Envoyé par Jean-Marc.Bourguet Voir le message
    Ca evite l'utilisation des VLA, qui sont du C99 ou une extension de gcc. Note qu'une borne superieure est facile a trouver (sizeof(long long)*CHAR_BIT+1)
    Là par contre cela sort de mes capacités ! Pourrais-tu détailler un peu plus ?




    a++

  5. #5
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par adiGuba Voir le message
    Citation Envoyé par Jean-Marc.Bourguet Voir le message
    Ca evite l'utilisation des VLA, qui sont du C99 ou une extension de gcc. Note qu'une borne superieure est facile a trouver (sizeof(long long)*CHAR_BIT+1)
    Là par contre cela sort de mes capacités ! Pourrais-tu détailler un peu plus ?
    1/ VLA: Tu utilises comme taille d'un tableau un parametre d'une fonction. C90 n'accepte que des expressions constantes a la compilation. gcc a depuis longtemps une extension acceptant cela; (relativement) plus recemment C99 a normalise quelque chose de plus ou moins equivalent.

    2/ Une borne superieure du nombre de chiffres necessaires pour exprimer un long long dans une base superieure ou egale a 2 est sizeof(long long)*CHAR_BIT+1; sizeof donnant une taille en nombre de char et CHAR_BIT indiquant le nombre de bits par char. +1 pour le '\0' final.

  6. #6
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Jean-Marc.Bourguet Voir le message
    1/ VLA: Tu utilises comme taille d'un tableau un parametre d'une fonction. C90 n'accepte que des expressions constantes a la compilation. gcc a depuis longtemps une extension acceptant cela; (relativement) plus recemment C99 a normalise quelque chose de plus ou moins equivalent.
    Ok merci pour cet éclaircissement !
    Il me semblait bien que ce n'était pas possible en C... mais je pensais que c'était ma mémoire qui me jouait des tours

    Citation Envoyé par Jean-Marc.Bourguet Voir le message
    2/ Une borne superieure du nombre de chiffres necessaires pour exprimer un long long dans une base superieure ou egale a 2 est sizeof(long long)*CHAR_BIT+1; sizeof donnant une taille en nombre de char et CHAR_BIT indiquant le nombre de bits par char. +1 pour le '\0' final.
    Je ne pense pas que cela me serait utile... mes valeur sont limité en taille (max 12 char en base 36).


    Voici mon code mis à jour avec tes conseils :
    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
    int lltostr(long long value, char *ptr, int maxlen, int base) {
    char letters[] = "0123456789abcdefghijklmnopqrstuvwxyz";
    long long nb;
    int r;
    int i, pos;
     
    ptr[maxlen] = '\0';
    pos = maxlen-1;
    nb = value;
    do {
            /* On calcule le reste de la division : */
            r = nb % base;
     
            /* On ajoute le nouveau caractère à la fin de la chaine : */
            ptr[pos--] = letters[r];
     
            /* On calcule le nouveau quotient en divisant par la base : */
            nb = nb / base;
    } while(nb!=0 && pos>=0);
     
    /* Si on a atteint la taille max on renvoi une erreur */
    if (nb!=0 && pos<0) {
            return -1;
    }
    /* On decale le texte si besoin : */
    if (pos>0) {
            memmove(ptr, &ptr[pos+1], maxlen-pos);
    }
    return maxlen-pos;
    }



    a++

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

Discussions similaires

  1. Fonction de conversion de nombre en lettres
    Par david_chardonnet dans le forum Langage
    Réponses: 21
    Dernier message: 08/12/2021, 17h51
  2. [VBS] Fonction de conversion de nombres vers la base 10
    Par l_autodidacte dans le forum Vos Contributions VBScript
    Réponses: 2
    Dernier message: 18/02/2014, 19h43
  3. [ASA]Conversion de nombres decimaux en toute lettre
    Par Fab_57 dans le forum Sybase
    Réponses: 1
    Dernier message: 22/08/2006, 14h49
  4. conversion access vers autre base de données
    Par Anthony17 dans le forum Access
    Réponses: 1
    Dernier message: 16/06/2006, 13h50
  5. Conversion de nombres
    Par moonia dans le forum Langage
    Réponses: 2
    Dernier message: 17/01/2006, 11h09

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