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 :

Un autre souci de comparaison de codes ASCII


Sujet :

C

  1. #1
    Candidat au Club
    Inscrit en
    Novembre 2007
    Messages
    6
    Détails du profil
    Informations forums :
    Inscription : Novembre 2007
    Messages : 6
    Points : 4
    Points
    4
    Par défaut Un autre souci de comparaison de codes ASCII
    Re bonjour à tous,
    Grâce à vous mon projet avance à toute vitesse. Je me heurte cependant à un dernier souci:
    j'ai un fichier texte en mode binaire qui contient entre autre des caractères accentués. Je dois placer le caractère hexa 0x83 devant chaque caractère accentué

    Fonctionnement souhaité: on ouvre le fichier source et on compare chaque caractère à la valeur 0xC0. S'il est supérieur (4 dernières lignes de la table ascii étendue), il s'agit d'un caractère accentué on ajoute au fichier cible le caractère 0x83 puis on poursuit la copie fichier à fichier.

    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
    char precedent=0x00;
     
    	do
        { 
     
            char caractere_lu = fgetc(fichierorigine); //lecture dans le fichier source d'un caractère
     
            // Checking for end of file 
            if (feof(fichierorigine)) //sortie de boucle si fin de fichier atteinte
                break ; 
     
     
    		  // on cherche si le caractère lu est accentué (si son code hexa est sur les 4 dernières lignes de la table ascii étendue)
    		  // il faut aussi prévoir le fait qu'on doit pouvoir exécuter plusieurs fois la moulinette sans rajouter à chaque fois le caractèe 0x83 s'il est déjà présent
     
    			if (caractere_lu>0xC0 && precedent!=0x83)	//
    			{
    				fputc(0x83, fichierdestination);   //ecriture dans le fichier cible d'un caractère
         		}
     
      		 fputc(caractere_lu, fichierdestination);
      		 precedent=caractere_lu;
     
        }  while(1);
    Merci d'avance pour votre aide. Promis c'est la dernière fois que je vous embête.

  2. #2
    Candidat au Club
    Inscrit en
    Novembre 2007
    Messages
    6
    Détails du profil
    Informations forums :
    Inscription : Novembre 2007
    Messages : 6
    Points : 4
    Points
    4
    Par défaut essai infructueux
    Je viens de tester ça sans succès:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if (caractere_lu>'à' && caractere_lu<'ÿ' && precedent!=0x83)
    autant le code précédant ne changeait absolument rien à mon fichier d'origine autant cette fois le caractère 0x83 est présent avant chaque caractère, accentué ou non.

  3. #3
    Candidat au Club
    Inscrit en
    Novembre 2007
    Messages
    6
    Détails du profil
    Informations forums :
    Inscription : Novembre 2007
    Messages : 6
    Points : 4
    Points
    4
    Par défaut solution
    je me répond à moi même: j'ai trouvé la solution en relisant les posts de ma question précédente:

    un char est codé de -127 à +127 (decimal). J'ai donc cherché une table ascii correspondante. J'y ai trouvé que le caractère 0xC0 se code -64 (dec) et que le caractère 0xFF se code -1 (dec)
    J'ai converti mon char en int et fait une simple comparaison d'int:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    char caractere_lu = fgetc(fichierorigine); //lecture dans le fichier source d'un caractère
    int codeascii = caractere_lu;
    et
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if (codeascii>=-64 && codeascii<=-1 && precedent!=0x83)
    Il me reste juste un souci: le fichier se code parfaitement mais sans aucune raison le codage s'arrête brutalement en plein milieu du mot <message id=....>
    Si quelqu'un a une idée, qu'il n'hésite pas !

  4. #4
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 677
    Points : 30 965
    Points
    30 965
    Billets dans le blog
    1
    Par défaut
    Bonjour

    Citation Envoyé par vincentetcarine Voir le message
    Promis c'est la dernière fois que je vous embête.
    Ca ne nous embête pas quand on pose des questions. Si on est là, c'est surtout pour le plaisir de transmettre nos connaissances à ceux qui le demandent...

    Citation Envoyé par vincentetcarine Voir le message
    j'ai un fichier texte en mode binaire
    Ca déjà c'est un truc que j'ai du mal à me représenter. Je pense même que si je te demandais de t'en expliquer tu aurais toi aussi quelques soucis...

    Il n'y a à la base aucune différence entre "fichier texte" et "fichier binaire" mais que du fichier. Un film, c'est un fichier. Un mp3 c'est un fichier. Un bmp c'est un fichier. Et "toto.txt" c'est aussi un fichier.
    Ensuite, il y a certains fichiers qui sont spécifiquement écrits qu'avec des caractères affichables à l'écran plus une spécification indiquant une fin de ligne. Et là on entre dans une distinction non pas "texte/binaire" mais "windows/unix" car dans windows la fin de ligne est représentée par deux caractères '\r' + '\n' tandis que dans Unix il n'y a que le '\n'. Et c'est simplement à cause de cette différence qu'on est obligé de spécifier qu'on lit du texte (dans ce cas le doublé '\r\n' devient "une" fin de ligne) ou du binaire (et là, tout '\r' suivi d'un '\n' seront traités de façon distincte). Et tu remarqueras que cette distinction n'est réellement utilisable que dans windows parce que dans unix, elle existe pour des raisons de portabilité mais n'a aucun effet (ben oui, dans unix il n'y a pas besoin de regrouper deux caractères accolés vu qu'il n'y en a qu'un seul pour représenter cette notion qu'est la "fin de ligne").

    Citation Envoyé par vincentetcarine Voir le message
    J'y ai trouvé que le caractère 0xC0 se code -64 (dec) et que le caractère 0xFF se code -1 (dec)
    Encore raté. 0xC0 correspond à une écriture en hexadécimal. Les règles mathématiques de lecture d'un nombre sont qu'on multiplie chaque chiffre qui décompose le nombre par sa base élevée à la puissance du rang dudit chiffre (en considérant que le premier rang vaut 0 et que les rangs se lisent de la droite vers la gauche). Par exemple dans 874 on a un "8" au rang 2, un "7" au rang 1 et un 4 au rang 0 donc si la base d'écriture est 10, alors ce nombre représente 8*10^2 + 7*10^1 + 4 * 10^0 (=874). Mais si sa base d'écriture est 9, alors ce nombre représente 8*9^2 + 7*9^1 + 4 * 9^0 (=715).
    Si on applique cette règle à C0, alors il vaut C*16^1 + 0*16^0. "C"(16) valant 12(10), ça donne 12*16 soit 192.

    Ensuite, vient le problème de l'encodage de ce nombre. C0(16) se code 1100 0000(2) (et là encore la valeur peut se calculer comme 1*2^7 + 1*2^6 soit 128 + 64=192). Or quand on travaille en char signé, le 8° bit n'est plus un bit de valeur mais un bit de signe. Ce qui peut alors, dans le monde signé, représenter aussi -64. Mais ça, ça ne dépend que de toi et de ta façon d'afficher cette valeur. Exemple printf("%hu %hd\n", (unsigned char)0x0C, (char)0x0C) te donnera "192 -64".
    Mais ce n'est pas anodin ce bit de signe. Parce que si la valeur est copiée dans un espace plus grand (ex char dans short ou short dans int), et que son premier bit vaut 1, et qu'elle est signée, alors l'espace vide est alors rempli de 1 (extension du bit de signe afin de conserver la même valeur).
    Donc si on reprend ce "0xC0" qu'on le stocke dans un signed char puis qu'on copie ce char dans un short, alors ça donnera 0xFFC0. Ensuite selon que le short est lui-même signé ou pas cette valeur 0xFFC0 vaudra soit 65472 (unsigned) soit -64 (signé).
    en revanche, si 0xC0 est stocké dans un unsigned char puis qu'on copie ce char dans un short, alors ça donnera 0x00C0 qui vaudra toujours 192 quelle que soit la façon dont on le considère (signed/unsigned).

    Bref quand le premier bit d'une variable vaut "1", la valeur de la variable dépend d'abord de son type de codage. Et ensuite, ce qui s'affiche à l'écran dépend lui-aussi du format d'affichage demandé.

    Citation Envoyé par vincentetcarine Voir le message
    J'ai converti mon char en int et fait une simple comparaison d'int:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    char caractere_lu = fgetc(fichierorigine); //lecture dans le fichier source d'un caractère
    int codeascii = caractere_lu;
    C'est dommage. fgetc() renvoie déjà un int et ça on te l'a déjà dit (oui, j'ai lu ton autre topic mais je n'y ai pas répondu car tout avait été dit). Donc tu tronques cet int dans un char (tu perds l'octet de poids fort) et tu recopies ce char (l'int tronqué) dans un vrai int. Tu perds de l'info pour rien. Et en plus tu ne peux même plus distinguer le caractère 0xFF éventuellement lu de l'entier 0xFFFF (-1) renvoyé par la fonction quand elle est arrivée au bout du fichier.

    Citation Envoyé par vincentetcarine Voir le message
    Il me reste juste un souci: le fichier se code parfaitement mais sans aucune raison le codage s'arrête brutalement en plein milieu du mot <message id=....>
    Si quelqu'un a une idée, qu'il n'hésite pas !
    Donne un petit exemple de ton fichier. Accessoirement ta façon de traiter le fichier (je lis puis je teste feof() le tout dans un do...while) fonctionne mais il y a plus simple: tester directement la lecture elle-même => while ((c=fgetc(fichierorigine)) != EOF) {...} (sous réserve que "c" soit un int mais j'espère qu'on te l'a déjà dit).

    D'autant plus que le but premier de feof() n'est pas d'indiquer une "fin de fichier". Ou plus spécifiquement, n'est pas d'indiquer une fin de fichier durant le traitement du fichier. On peut le faire bien sûr mais comme on détourne son utilité, on est alors obligé de passer par des tournures alambiquées telles que ta façon (et encore c'est la moins pire qui soit car au-moins elle fonctionne tandis que la majorité y vont allègement avec leur while(!feof(fichier)) et viennent ensuite pleurer parce que leur boucle tourne une fois de plus que ce qu'il y a à lire !!!)
    Le but de cette fonction est d'indiquer, une fois que le fichier a été lu et que la lecture s'est arrêté (donc qu'on est sorti de la boucle), si l'arrêt de la lecture est dû à une "fin de fichier atteinte" ou bien autre chose (erreur, etc).
    Pour sortir d'une boucle de lecture, le plus simple est de checker la fonction de lecture elle-même car quand elle ne lit plus le fichier, elle renvoie alors une valeur spéciale qu'on peut tester.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

Discussions similaires

  1. problème de comparaison de codes ascii
    Par vincentetcarine dans le forum Débuter
    Réponses: 4
    Dernier message: 20/11/2018, 09h22
  2. Comparaison par code ascii
    Par lazins dans le forum ASP.NET
    Réponses: 4
    Dernier message: 13/11/2008, 15h50
  3. Code ASCII du symbole Euro
    Par FW-S dans le forum Delphi
    Réponses: 9
    Dernier message: 03/04/2007, 01h27
  4. [LG] Transformer un code ascii en un autre
    Par JoseF dans le forum Langage
    Réponses: 8
    Dernier message: 29/12/2005, 11h47
  5. [Hardware portable] Comment entrer un code Ascii?
    Par l.sage dans le forum Ordinateurs
    Réponses: 13
    Dernier message: 11/08/2005, 13h04

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