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 :

Présentation: | Question: String -> ASCII code puis ASCII code -> string


Sujet :

C++

  1. #1
    Membre averti
    Homme Profil pro
    Curieux acharné
    Inscrit en
    Octobre 2018
    Messages
    13
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Curieux acharné
    Secteur : Santé

    Informations forums :
    Inscription : Octobre 2018
    Messages : 13
    Par défaut Présentation: | Question: String -> ASCII code puis ASCII code -> string
    Bonjour,

    Présentation:
    Je suis nouveau sur cette board et ..
    hyper débutant en C++ (je parts de 0 connaissances avec juste l'envie de comprendre, apprendre et jouer avec ce langage).
    J'essai de refaire des petits tutos et j'essai, autant que possible, de trouver sur le web des réponses et des bouts de codes que je puisse comprendre utiliser, assembler.
    Mais je dois aussi être "noob" dans mes recherches car j'ai parfois beaucoup de mal à trouver et comprendre seul.
    J'espère avoir un peu de votre temps et de votre bienveillance pour me permettre d'apprendre un peu plus facilement.


    Question:
    Pour jouer a crypter/decrypter.

    J'aimerai passer d'une chaîne de cratère longue (le texte a crypter) -> en ça valeur decimale (ou hexa si nécessaire) ASCII.
    Pour ce faire j'ai trouvé ce bout de 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
     
    #include <iostream>
     
    using namespace std;
     
    int main()
    {
        string str;
        cout << "Entrez un mot ou phrase" <<endl;
        cin >> str;
     
        char ch;
        for(int i=0; i < str.length() ; i++)
        {
           ch = str.at(i);   //retourne une référence au caractère à la position pos dans la chaîne
           cout << (int) ch;  // le (int) fait la transformation des caractère en ascii
        }
        cout << endl;
        cout << ch;
     
     
        return 0;
    }
    Output:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    Entrez un mot ou phrase
    es pace
    101115
    Process returned 0 (0x0)   execution time : 35.235 s
    Press any key to continue.
    Déjà, un truc auquel je ne m’attendez pas ,
    on voit juste le code ASCII de "es" (et pas le code (32) de " " ni les codes du "pace" qui suit).

    Dans un second temps, quelle technique utiliser pour faire marche arrière et "scanner" une suite de chiffre décimaux (représentant une chaîné ASCII ex 7210110810811132119111114108100) en ça chaîne originale écrite (ici Hello world)?
    Comme il y a des codes ASCII à un, deux ou trois chiffres on ne pourra pas savoir où doivent se faire les découpes pour retrouver les bonnes lettre..

    Suis curieux d'avoir vos conseils, avis..
    Bonne journée

  2. #2
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut, et bienvenue à bord .

    Il faut faire attention à un truc lorsque tu veux utiliser l'opérateur >> sur une std::string: cet opérateur est prévu pour s'arrêter ... à la fin de la première chaîne de caractères, à la fin du premier mot, si tu préfères.

    Or, l'espace est typiquement considéré comme ... le séparateur que l'on trouve entre deux mots.

    Il est donc "tout à fait normal" que la chaine de caractères que tu obtiens s'arrête ... juste avant le premier espace que tu auras introduit. Parce que c'est ce qu'on attend de sa part.
    Déjà, un truc auquel je ne m’attendezais pas ,
    on voit juste le code ASCII de "es" (et pas le code (32) de " " ni les codes du "pace" qui suit).
    Dans le cas présent, ta chaîne de caractères contient uniqueme es et ton flux d'entrée (std::cin) n'est pas vide, et contient encore pace\n (note bien la présence de l'espace avant le p!!!)

    Si tu t'attends à obtenir un (des) espace(s) (ou tabulations) de la part de l'utilisateur, tu dois utiliser la fonction std::getline, sous une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    int main(){
        std::string myString;
        std::getline(std::cin, myString);
    }
    Mais tu dois faire attention, à ce moment là. Car cette fonction ne va s'arrêter qu'au premier délémiteur qu'elle doit utiliser ('\n' par défaut), si bien que ta chaine de caractères contiendra -- entre autres -- tous les espaces que tu aura pu introduire.

    Ainsi, si tu introduit les mots es pace (notes qu'il y a trois espaces entre le s et le p), ta chaine contiendra ... es pace (avec trois espaces entre le s et le p).

    Dans un second temps, quelle technique utiliser pour faire marche arrière et "scanner" une suite de chiffre décimaux (représentant une chaîné ASCII ex 7210110810811132119111114108100) en ça chaîne originale écrite (ici Hello world)?
    Comme il y a des codes ASCII à un, deux ou trois chiffres on ne pourra pas savoir où doivent se faire les découpes pour retrouver les bonnes lettre..
    Tu n'as pas besoin de le faire! Ou, plutôt, tu n'as pas vraiment besoin d'afficher les valeurs pour pouvoir les prendre en compte

    Le type char n'est jamais qu'un type permettant de représenter des valeurs numériques entières "comme les autres" (shor, int, long ou long long) qui a la particularité:
    • de n'être composé d'un nombre de bits juste suffisant pour pouvoir représenter n'importe quel indice de la table ASCII
    • de pouvoir être interprété par le processeur de manière à ce qu'il aille chercher le "glyphe", le "symbole" qu'il doit afficher par rapport à la valeur qu'il représente dans la table ASCII

    D'ailleurs, lorsque l'ordinateur affiche 101115, il n'a -- là aussi -- fait qu'interpréter les valeurs 101 et 115 (en réalité, les valeurs binaires 0110 0101 et 0111 0011) de manière à aller chercher (dans la table ASCII) les symboles qui permettent de représenter ces valeurs d'une manière "compréhensible par les humains".

    Il faut savoir que la notation décimale (celle que l'on utilise tous les jours), la notation binaire (celle qui est réellement utilisée par l'ordinateur) et la notation hexadécimale (celle qui facilite la lecture de valeurs binaires) ne sont que des conventions permettant de représenter la même chose, et que l'ordinateur se charge de faire la conversion de l'une à l'autre en fonction des besoins.

    Du coup, si tu fais une boucle proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    for(int i = 0; i<str.size();++i){
        char ch = str[i];
    }
    ch va correspondre à l'indice dans la table ASCII du symbole qui devrait être affiché, mais que "dans les entrailles du processeurs", cet indice sera forcément une valeur numérique représentée par une succession de 8 bits dont certains "laissent passer" le courant (et seront du coup représentés par la valeur 1) et d'autres ne le laisseront pas passer (et seront du coup représentés par la valeur 0)

    Comme il s'agit d'une valeur numérique, nous pourrons utiliser les opérations mathématiques de base dessus, à savoir : l'addition, la multiplication, la division et le modulo (le calcul du reste d'une division par un autre entier), et il n'y a que l'interprétation qui sera faite de cette donnée qui changera au final, surtout si l'idée est d'arriver à l'afficher:
    • Si nous gardons le type char, l'opérateur << va considérer que nous voulons afficher le symbole correspondant
    • si nous décidons de le convertir (par exemple, en int), l'opérateur << ira rechercher les symboles (les chiffres, dans le cas présent) qui permettent de représenter la valeur indiquée sous une forme décimale
    • si nous décidons d'utiliser le modificateur de flux std::hexa, l'opérateur << ira rechercher les syboles (les chiffres plus les lettres A, B, C, D, E et F pour représenter des valeurs comrises entre 11 et 15) qui permettront de représenter cette valeur sous une forme hexadécimale
    • si nous voulons un affichage sous forme binaire de la valeur, il faudra ruser un tout petit peu , mais cela n'a rien de bien compliqué

    Mais ce qu'il est important de comprendre, c'est que cela reste toujours fondamentalement la même valeur!!! C'est comme si tu décidais de comparer 2€ à 200 cent ou 2km à 2 000 m (ou à 200 000 cm) : la valeur ne change pas, il n'y a que l'unité, la représentation qui en est faite qui change


    Enfin, je ne peux laisser passer ton code sans émettre les remarques classiques qu'il m'inspire :

    1- on n'utilise pas la directive using namespace std; : cette directive a été offerte au développeurs au tout début de la normalisation, quand il a été décidé de placer les fonctionnalités de la bibliothèque standard dans l'espace de noms std, pour que les programmes créés avant la normalisation puissent continuer à compiler "avec un minimum de modifications".

    Mais cette directive pose beaucoup plus de problèmes qu'elle n'en résout, et, on ne peut pas vraiment dire que le code que tu écris aujourd'hui date ... d'avant la normalisation (d'avant 1998)

    2- Ce n'est qu'un détail, mais c'est toujours une bonne chose que de veiller à déclarer les variable au plus près de leur utilisation :

    Ta variable str pourrait très bien être déclarée après ta ligne std::cout, et ta variable ch pourrait parfaitement être déclarée dans la boucle.

    D'ailleurs, la variable ch n'a absolument rien d'indispensable, car tu pourrais très bien t'en passer avec un code proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::cout<<(int) str.at(i);
    3- Au sujet de cette fonction at(), justement : cette fonction est une pure aberration du point de vue conceptuel, car elle dénote une approche basée sur la programmation défensive, alors qu'elle devrait dénoter une approche basée sur la programmation par contrat.

    Je m'explique: Cette fonction va lancer une exception si l'on essaye d'accéder à un caractère "hors limites", ce qui laisse présumer que le développeur n'a absolument aucun moyen d'éviter que le problème survienne, un peu comme s'il s'agissait d'un fichier qui est absent du disque dur ou un serveur distant qui "tombe en panne".

    Les exceptions sont donc là pour présenter ... des situations exceptionnelles : des situations dont "on espère qu'elles ne surviendront jamais" sans pour autant pouvoir garantir qu'elles ne surviendront effectivement jamais. Et, surtout, auxquelles il est impossible d'apporter une solution correcte au moment où elles surviennent.

    En effet, si tu essayes d'accéder à un fichier qui n'existe pas ou à un serveur qui vient de tomber en panne, tu ne sais pas faire grand chose en tant que développeur de ta fonction Tout ce que tu peux faire, c'est ... en prendre acte, et faire "remonter l'information" en espérant qu'il soit possible d'apporter une solution "plus haut dans la logique" avant de recommencer.

    Et, dans le pire des cas (s'il n'y a effectivement aucune solution pour résoudre le problème), tu préféreras laisser "planter" ton application, qui ne pourra -- de toutes façons -- pas fournir le résultat attendu.

    Or, le fait d'essayer d'accéder au onzième caractère d'une chaine qui n'en contient que dix n'a rien à voir avec ce genre de situation "dont on espère qu'elle ne survienne jamais" : c'est une situation qui survient parce que le développeur a fait une erreur de logique.

    La programmation par contrat est une approche par laquelle nous lions le développeur d'une fonctionnalité (celui qui en écrit le code) et son utilisateur (celui qui va l'utiliser "ailleurs", même si c'est celui qui en a écrit le code) par un "contrat" tout simple :
    passe moi des données cohérentes, tu obtiendras le résultat que tu attend
    (sous entendu : si tu ne me passe pas des données cohérentes, attends toi à obtenir un résultat ... surprenant )

    Le fait de vérifier que l'on n'essaye d'accéder qu'à des caractères qui existent dans la chaîne de caractères fait partie de ce contrat : si on essaye d'accéder au onzième caractère d'une chaine qui n'en contient que dix, l'utilisateur nous fournit ... des données incohérentes

    On désigne ce genre de vérification sous le terme de pré condition (des conditions qui doivent être respectées au plus tard au moment où l'on commence à exécuter une fonction)

    Il se fait que ce genre d'erreur doit être corrigée avant de fournir la version release du programme, avant que le programme ne passe "en production". Mais, du coup, la vérification qui est demandée n'a absolument plus aucune raison d'être effectuée dans le programme de production, vu que ... nous nous serons assurés que la logique est correcte avant de parvenir à cette étape

    Idéalement, ce genre de vérification devrait être effectué à l'aide d'une assertion.
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  3. #3
    Membre averti
    Homme Profil pro
    Curieux acharné
    Inscrit en
    Octobre 2018
    Messages
    13
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Curieux acharné
    Secteur : Santé

    Informations forums :
    Inscription : Octobre 2018
    Messages : 13
    Par défaut Woaow! merci
    Bonjour koala01,

    Un grand merci pour le temps que tu as du passer sur ta réponse. Ton implication pour aider est remarquable ... vraiment!.
    Bien évidemment, j'ai des tas de questions qui me viennent en supplément de tes explications et remarques (vu que j'ai tout à apprendre....
    mais je vais tout de même essayer, de ne pas trop diverger, et m'en tenir à un pragmatisme de forum (et de circonstance ;-))).

    En utilisant tes propositions de code j'ai :
    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
    #include <iostream>
     
    using namespace std;
     
    int main()
    {
     
        cout << "Entrez un mot ou phrase" <<endl;
        std::string myString;
        std::getline(std::cin, myString);
     
        for(int i = 0; i<myString.size();++i)
        {
        char ch = myString[i];
        cout << (int) ch;
        }
     
        return 0;
    }
     
    Output:
     
    Entrez un mot ou phrase
    Hello world !
    72101108108111321191111141081003233
    Process returned 0 (0x0)   execution time : 5.559 s
    Press any key to continue.
    Ca semble faire le travail demandé..

    Au vu de tes explications koala01, je comprends que les valeurs ASCII sont, de base, liées à des nombres qui sont ensuite traduits en binaire, hexa , decimal, glyphe..
    et donc on devrait pouvoir passer de la série de chiffres "72101108108111321191111141081003233" à "Hello world !" aussi facilement que ce que l'on ai passé de "Hello world !" à "72101108108111321191111141081003233"... mais...tant qu'on reste dans le programme? Je m'explique.

    Si avec ce petit programme je transforme "Hello world !" en "72101108108111321191111141081003233".
    Puis j'envoie cette série de chiffre par email à mon ami Robert.
    Quel programme Robert pourrait-il imaginer pour être sûr de bien retransformer cette série de chiffre en "Hello world !"?
    N'y a-t-il pas, dans ce cas, un risque de confusion des correspondances chiffre/caractère, selon les découpes?

    Bon dimanche tous,

  4. #4
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    En fait, ce serait plutôt
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    72 101 108 108 111 32 119 111 114 108 100 32 33
    (en séparant correctement chaque nombre)
    Sinon, ton ami pourrait se dire que les nombres doivent être
    • plus grands ou égaux à 32 (le caractère espace)
    • strictement plus petit que 255


    A priori, cela ne laisse pas beaucoup de possibilités de se tromper dans le calcul, surtout quand on sait :
    • que les chiffres sont représentés par des valeurs comprise entre 48 (pour le '0') et et 57 (pour le '9')
    • que les majuscules sont représentées par des valeurs comprises entre 65 (pour le 'A') et 90 (pour le 'Z')
    • que les lettres minuscules sont représentées par des valeurs comprises entre 97 (pour le 'a') et 122 (pour le 'z')

    Ceci dit, si tu veux mettre en place un chiffrement quelconque, tu dois te dire que la logique que tu mettra en place risque de chambouler tout cela:

    La méthode la plus simple consiste à additionner (ou à soustraire) une valeur clairement définie à chaque caractère (mettons : 5) : si tu décides d'ajouter 5 au chiffrement (et donc de soustraire 5 au déchiffrement), il n'y aura pas de problème, car il suffit d'additionner 5 aux valeurs que je t'ai indiquées, et que nous restons dans la limite 32 <= caractère <255.

    Mais, si tu décide de soustraire 5 au chiffrement, les caractères représentés par les valeur 32, 33, 34, 35 et 36 (respectivement : l'espace, !,# et $ ) prendront des valeurs inférieures à 32, qui représentent des caractères "non affichables", qui ont une signification particulière.

    C'est la raison pour laquelle il est préférable d'envoyer le fichier sous forme binaire, qui contiendra (sous une forme binaire) les valeurs de chaque caractère (avec les éventuelles modifications apportées lors du chiffrement).

    Ton ami n'aura donc "plus qu'à" extraire les valeurs "une à une" (dans un char), et à appliquer la méthode de déchiffrement, qui exécutera les opérations inverses, dans l'ordre inverse de leur exécution lors du chiffrement
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  5. #5
    Membre averti
    Homme Profil pro
    Curieux acharné
    Inscrit en
    Octobre 2018
    Messages
    13
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Curieux acharné
    Secteur : Santé

    Informations forums :
    Inscription : Octobre 2018
    Messages : 13
    Par défaut Merci !
    Merci beaucoup koala01!
    bye

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

Discussions similaires

  1. Affichage de CODE en ASCII et hexa des caractères
    Par Ojiuiookojbezib dans le forum Contribuez
    Réponses: 4
    Dernier message: 01/12/2014, 10h21
  2. Conversion ascii etendu en alt-code?
    Par andromeda dans le forum Langage
    Réponses: 3
    Dernier message: 06/11/2013, 12h44
  3. Stratégie pour OCX, affichage code ascii ou image du code ascii désiré
    Par ProgElecT dans le forum VB 6 et antérieur
    Réponses: 9
    Dernier message: 04/08/2007, 14h00
  4. Convertir du code en ascii
    Par BernardT dans le forum Langage
    Réponses: 5
    Dernier message: 27/03/2007, 21h32
  5. Réponses: 2
    Dernier message: 30/05/2006, 08h04

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