1. #1
    Membre à l'essai
    Homme Profil pro
    Responsable du parc et des réseaux de télécommunication
    Inscrit en
    mars 2017
    Messages
    13
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Vaucluse (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Responsable du parc et des réseaux de télécommunication
    Secteur : Enseignement

    Informations forums :
    Inscription : mars 2017
    Messages : 13
    Points : 10
    Points
    10

    Par défaut Conversion (int) <-> (char) et entier supérieur à 256, sur plusieurs char.

    Bonjour,
    J'ai la contrainte de devoir stocker des entiers dans un fichiers et je me retrouve avec des fichiers plutôt volumineux.
    Même si tout fonctionne correctement je me posais la question suivante :
    J'utilise parfois la correspondance (char)mon_entier pour me renvoyer le caractère ascii d'un entier (inférieur à 256), je me demandais si il était possible de stocker sur deux char un entier supérieur à 256 (pour réduire dans la foulée la taille de mon fichier).
    Exemple (char)mon_entier avec mon_entier variable int qui vaut 257 me renvoi un caractère, mais si je fait (int)(char)mon_entier me renvoi 1, ce qui est a priori logique vu que j'ai bouclé ma table ASCII non?
    J'aimerais une méthode pour un renvoi de mon entier sur deux chars et plus mais ma méthode/approche n'est clairement pas la bonne.
    Comment faire.?
    Merci

  2. #2
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    août 2004
    Messages
    5 414
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    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 414
    Points : 15 565
    Points
    15 565

    Par défaut

    Ce que tu veux faire s'appelle sauver les données en binaire (tu sauves directement les différents bits représentant ton entier, et non pas la représentation en base 10 de ceux-ci)

    La FAQ présente une méthode, à base de reinterpret_cast, que je n'aime pas trop car vraiment non portable : https://cpp.developpez.com/faq/cpp/?...ans-un-fichier (mais la partie ouverture du fichier est bonne quand même !)

    Par exemple, pour sauver des entiers sur 16 bits, tu peux faire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    auto lower = static_cast<unsigned char> (i);
    auto higher = static_cast<unsigned char> (i >> 8);
    stream << lower << higher; // Ou l'autre sens, comme tu veux
    Et pour relire, un truc à base de :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    unsigned short result = higher;
    result << 8;
    result += lower;
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  3. #3
    Membre à l'essai
    Homme Profil pro
    Responsable du parc et des réseaux de télécommunication
    Inscrit en
    mars 2017
    Messages
    13
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Vaucluse (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Responsable du parc et des réseaux de télécommunication
    Secteur : Enseignement

    Informations forums :
    Inscription : mars 2017
    Messages : 13
    Points : 10
    Points
    10

    Par défaut

    Super et un grand merci à toi c'est exactement cela que je cherchais, du coup j'ai codé ces deux petites fonctions pratique pour moi :

    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
    string ul_to_str(unsigned long nombre)
    {
    string str(4, ' ');
    str[0] = static_cast<char>((nombre >> 24) & 0xFF);
    str[1] = static_cast<char>((nombre >> 16) & 0xFF);
    str[2] = static_cast<char>((nombre >> 8) & 0xFF);
    str[3] = static_cast<char>((nombre) & 0xFF);
    return str;
    }
     
    unsigned long str_to_ul(string str)
    {
    unsigned long result;
    result = static_cast<unsigned long>((str[0]) & 0xFF) << 24;
    result += static_cast<unsigned long>((str[1]) & 0xFF) << 16;
    result += static_cast<unsigned long>((str[2]) & 0xFF) << 8;
    result += static_cast<unsigned long>((str[3]) & 0xFF);
    return result;
    }
    Ça marche même si j'avoue ne pas trop comprendre le pourquoi du & 0xFF
    Je poste car sait on jamais c’est très probablement mal codé et peux être sujet à critique,
    du coup tu me dit que c'est pas terrible niveau portabilité, c'est à dire?
    J'aurais des problèmes si j'exporte ce code sous Linux?
    Merci en tout cas.

  4. #4
    Membre averti Avatar de Matthieu76
    Homme Profil pro
    Consultant informatique
    Inscrit en
    mars 2013
    Messages
    371
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : mars 2013
    Messages : 371
    Points : 449
    Points
    449

    Par défaut

    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
    #include <iostream>
    #include <bitset>
     
    using namespace std;
     
    int main()
    {
        	char i = 0xFF;	
            char j = 0x76;
    	char k = i & j;
     
    	cout << std::bitset<8>(i) << endl;
    	cout << std::bitset<8>(j) << endl;
    	cout << std::bitset<8>(k) << endl;
    	return 0;
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    11111111
    01110110
    01110110
    Le 0xFF ne sert à rien.

  5. #5
    Expert éminent sénior
    Homme Profil pro
    Développeur informatique
    Inscrit en
    février 2005
    Messages
    4 526
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : février 2005
    Messages : 4 526
    Points : 10 322
    Points
    10 322

    Par défaut

    Le 0xFF ne sert à rien.
    Bin si, pour éviter la propagation de signe avec les opération de shift.
    Mais comme d'habitude, avec les bons outils, tout est toujours plus simple.

  6. #6
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    septembre 2005
    Messages
    26 704
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : septembre 2005
    Messages : 26 704
    Points : 39 060
    Points
    39 060

    Par défaut

    Citation Envoyé par neokal Voir le message
    Super et un grand merci à toi c'est exactement cela que je cherchais, du coup j'ai codé ces deux petites fonctions pratique pour moi :
    Ça marche même si j'avoue ne pas trop comprendre le pourquoi du & 0xFF
    Je poste car sait on jamais c’est très probablement mal codé et peux être sujet à critique,
    du coup tu me dit que c'est pas terrible niveau portabilité, c'est à dire?
    J'aurais des problèmes si j'exporte ce code sous Linux?
    Merci en tout cas.
    Côté portabilité, pour ce genre de choses tu devrais utiliser les types de tailles fixe (genre uint32_t, uint64_t) plutôt que les types comme unsigned long, parce que si (sous Linux, par exemple) tu sérialises un unsigned long de 64 bits sur quatre octets, tu en perds la moitié!

    Ensuite, ce qu'il faut garder en mémoire, c'est que le résultat que tu mets dans une string n'est pas forcément une chaîne valide. Même si on décide que les problèmes de "chaînes de caractères C" (qui ne peuvent pas contenir d'octet nul) sont hors-sujet car on est en C++, il reste les problèmes d'encodage: Sous Linux, il est très courant que le système soit configuré pour utiliser des chaînes de caractères encodées en UTF-8, et dans ce cas beaucoup de combinaisons sont invalides! Par exemple, si tu sérialises 0x00FFFFFF, tu obtiens un 0xFF suivi d'un autre 0xFF, ce qui est invalide en UTF-8.
    Sans parler de tous les caractères non-imprimables, etc.

    Personnellement, je suis réticent à appeler string une suite de caractères contenant des données brutes comme celle-ci. Tu devrais plutôt utiliser un vecteur de unsigned char (std::vector<unsigned char>), où là il est évident que ce sont des données brutes que tu manipules.

    ...Ou bien, tu sérialises sous forme de texte plutôt que faire une sérialisation binaire. C'est ce que semble recommander le C++, vu que la bibliothèque standard offre des objets ne pouvant être sérialisés que sous forme de texte (notamment les générateurs de nombres aléatoires).
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

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

Discussions similaires

  1. Conversion int en char *
    Par Trunks dans le forum C
    Réponses: 6
    Dernier message: 18/03/2006, 16h44
  2. Réponses: 12
    Dernier message: 12/03/2006, 15h53
  3. conversion int---->char
    Par andurand dans le forum C++
    Réponses: 10
    Dernier message: 30/05/2005, 17h36
  4. Réponses: 2
    Dernier message: 01/07/2004, 11h36

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