Multi-bytes characters - C - Programmation
Marsh Posté le 26-10-2007 à 18:30:38
Je sais pas ce que veut dire MCBS.
Laisse tomber les str*, utilise une API dédiée au traitement des chaînes dans le codage de caractères que tu utilises.
Marsh Posté le 26-10-2007 à 18:32:10
nan c'est un exo donc je dois le faire moi même à la main.
Je vais probablement stoquer cela dans un char* pour ce que ca change.
Mais là j'ai un problème de compréhension de la logique et je ne trouve pas de doc parlant de la carry (surement parce que normalement des bibliothèques standards s'en occupent).
Merci
(sinon MBCS et non MCBS pardon, c'est pour multi-bytes character set).
Marsh Posté le 26-10-2007 à 18:37:45
mais quel jeu de caractères justement ?
Si on s'en fout et que c'est juste un exercice, on peut comprendre que carry == bit de poids fort et voilà ? (ce qui serait sinistrement stupide)
Marsh Posté le 26-10-2007 à 18:40:20
hmm on m'a laissé le choix pour le langage et tout et tout. C'est plus un test de logic qu'autre chose.
Le jeu de charactère est censé pouvoir tenir du Jap et on n'est pas en UTF mais toujours en ISO-machin.
La carry == bit de poids fort en effet.
Marsh Posté le 26-10-2007 à 18:45:27
A moins d'avoir un marqueur en début de fichier, je pense que deviner le codage d'un fichier demande une heuristique assez lourde.
Vérifier un bit de poids fort, à part savoir si c'est de l'ascii ou pas, y a rien de plus à en tirer.
Marsh Posté le 26-10-2007 à 18:45:37
grossièrement la question posée, vu que ca pourrait aider les gens à comprendre (encore une fois je sais plus ou moins comment le coder, j'ai juste un problème de logic là) :
"Un jeu de caractères a des caratères de 1 et 2 bytes. Les caractères d'1 byte ont leur 1er bit à 0. Les caractères de 2 bytes ont leur 1er bit de leur 1er byte à 1, le 1er bit de leur 2nd byte peut être à 1 ou 0. On accumule les caratères dans un buffer et à un moment on souhaite enlever le dernier charactère du buffer. Comment faire."
Marsh Posté le 26-10-2007 à 18:47:41
Pas de marqueur non
En fait je sais que mon string alterne 1 bytes et 2 bytes, et je dois trouver si le dernier est 1 byte ou 2 byte en formant des couples/
Marsh Posté le 26-10-2007 à 18:50:47
Ah ouais, dis comme ça c'est tout de suite plus simple
La t'es typiquement sur le problème de certains codages qui sont chiants parce que justement il faut les lire dans un sens. Mais ici, je vois pas trop la difficulté. Tu regardes l'avant dernier, s'il a sa retenu, bah tu le vires aussi ?
Marsh Posté le 26-10-2007 à 18:52:33
haha tu viens de compléter l'énoncé ! Je relis.
edit: Si sur les deux derniers bytes, les carries sont
- 0 0: bah t'as un 1B à la fin, tu supprimes le dernier
- 0 1: peut pas de produire, parce que dernier octet est le début d'un caractère sur 2B
- 1 0: t'as un caractère sur 2B, tu vires les 2B
- 1 1: t'as un caractère sur 2B, tu vires les 2B
non ?
Marsh Posté le 26-10-2007 à 19:05:37
voilà tu as compris
Mais faut aller plus loin que l'avant dernier charactère.
Genre:
1 0 peut être en fait
- 0 1 0 là pas de soucis je sais que "10" est mon couple
- 1 1 0 : là je ne sais toujours pas qu'est ce qui est en couple, peut être que "11" est une lettre et "0" une autre ou peut être que le 1er "1" est en couple avec une lettre avant que je n'ai pas encore lu et que "10" est une lettre.
C'est pour cela qu'on m'a dit de remonter à 2 0. Mais je ne comprend pas pourquoi.
0111 ne fonctionne pas ca on est d'accord.
0110 fonctionne par contre, et il y a bien 2 0 (j'ai oublié de demander si c'était 2 0 de suite ou pas ).
Le truc qui me bloque c'est que n'importe quoi après un 0 est forcément séparé de ce 0, mais effectivement un seul zéro à gauche ca ne fonctionne pas dans tous les cas:
- 0111 : là j'ai une corruption de donnée
- 011 ca fonctionne bien... Alors je ne sais pas pourquoi j'ai besoin de 2 0
Merci
Marsh Posté le 26-10-2007 à 19:43:50
c'est bien ce que je disais
Je suis parti sur cela:
je cherche le dernier 0 avant le dernier byte et je m'y arrête.
Après je crée des couples jusqu'à l'avant dernier byte.
Si au dernier byte je suis toujours en mode couple alors j'enlève les 2 derniers bytes, sinon j'enlève uniquement le dernier byte.
Pour le mode couple j'ai un bool qui passe à true quand je tombe sur un 1 et que je suis à false, et qui passe à false quand je tombe sur n'importe quoi et que je suis à true.
Ca a l'air de tourner.
J'imagine que j'ai besoin de 2 0, quand mon dernier byte a 0 sinon 1 seul suffit.
Pour vérifier le bit de poid fort je pensais utiliser un masque genre 10000000. Je n'ai que très rarement travailler en binaire, donc c'est stupide ou?
Merci Taz!
Marsh Posté le 26-10-2007 à 19:44:34
Si tu as 1 0, l'avant dernier pourrait aussi être le 2ème d'un groupe de 2 (donc en fait 1 1 0), auquel cas il faudrait virer seulement le dernier byte, non ?
En fait on a :
- x y 1 : 2B (en fait, forcément x 1 1)
- x 0 0 : 1B
- 0 1 0 : 2B
- 1 1 0 : 1B
Marsh Posté le 26-10-2007 à 19:52:49
sauf que t'as pas de binaire littéral en C.
Donc si t'as des octets, un if (x & 0x80) devrait suffit.
Marsh Posté le 26-10-2007 à 19:54:46
tout à fait.
C'est pour cela que je cherche le dernier 0 avant le dernier byte.
En gros je cherche:
0 X X X ..... X Y
Y étant mon derniey byte.
Marsh Posté le 26-10-2007 à 19:55:27
Taz a écrit : sauf que t'as pas de binaire littéral en C. |
Parfait merci.
Marsh Posté le 26-10-2007 à 20:28:03
ReplyMarsh Posté le 26-10-2007 à 20:29:56
Bon encore un autre soucis
Pour supprimer mon dernier char je ne sais pas comment faire (l'habitude des String en C++, j'aurais peut être du le faire en C++ plutôt qu'en C mon exo, mais c'est plus drôle en C je trouve).
realloc ca a l'air parfait, mais n'est-ce pas lourd?
Marsh Posté le 26-10-2007 à 20:35:22
matafan a écrit : Tu n'as pas besoin de lire toute la chaine, juste au pire les 3 dernier bytes. |
bah non.
Si j'ai 110 ca ne m'avance pas vu que le 0 peut être seul ou pas.
Marsh Posté le 26-10-2007 à 20:52:27
Si t'as des chaines C et que tu dois toutes façons partir du début, autant pas réfléchir et faire en avançant plutôt qu'à reculons ?
Marsh Posté le 26-10-2007 à 20:53:53
Ah oui je suis con
Oui, realloc c'est lourd. Pour supprimer le dernier caractère, tout dépend comment sont codées tes chaines... J'imagine que tu as soit un caractère spécial pour marquer la fin, soit la longueur est indiquée ailleurs ? Dans le premier cas tu remplace le dernier caractère par ton caractère spécial. Dans le deuxième cas tu décrémentes la longueur de la chaine. Pour ce qui est de la mémoire, tout dépend comment sont stockées tes chaines en mémoire. Tu n'as pas focément besoin de "libérer" 1 ou 2 bytes immédiatement, c'est potentiellement lourd pour pas grand chose.
Marsh Posté le 26-10-2007 à 20:55:06
@Taz:
bah d'après ce qu'on ma dit c'est souvent plus rapide de commencer par la fin, mais pas toujours.
En gros on espère avoir un flag avant le milieu pour justifier le fait de commencer par la fin. Mais on peut commencer aussi par le début, c'est juste moins souvent intéressant.
@matafan:
Mes chaines se terminent pas '\0' oui mais j'ai besoin de libérer la mémoire. Vu que c'est un exercice et que je ne code que la fonction. Par contre ta remarque est intéressante. Si tu ne libères pas la mémoire de suite, tu le notes quelque part et tu feras tout d'un coup plus tard?
Marsh Posté le 26-10-2007 à 20:59:12
Mon code actuel
Code :
|
donc le coup du realloc c'est peut être trop lourd.
ensuite je me demande si y'a moyen que realloc change l'adresse de départ, enfin je ne vois pas de raison tant que je demande plus petit qu'avant.. (sinon j'ai lu quelque part qu'un realloc sur plus petit bypass tout ce qui est allocation de mémoire, donc tout ce qui est lourd, que ca 'libère' la mémoire et change la taille de mon tableau et stou).
Merci les gars!
Marsh Posté le 26-10-2007 à 21:15:39
Le truc c'est que si tu ne stoques pas par ailleurs la taille de tes chaines, ou un pointeur vers la fin, tu es de toute façon obligé de la parcourir entièrement à la recherche du 0 final... Donc tu ne gagne rien ou vraiment pas grand chose en faisant des trucs compliqués, par rapport à décoder séquentiellement ta chaine.
Le realloc peut renvoyer une adresse différente de celle passée en argument. Tu DOIS prendre l'adresse qui t'es renvoyée. Ne fait pas de suppositions sur ce que fait realloc en interne.
Marsh Posté le 26-10-2007 à 21:22:54
Pour la parcours bah regarde la liste suivante :
1111111111111111111111111111111111111111011.
Si je parcours depuis le début j'ai 43 bytes à lire.
Si je parcours depuis la fin j'ai 2 + 1 = 3 bytes à lire. Je m'explique je lis le 1, puis le 0 m'arrête et repars dans l'autre sens donc je relis le 1 de toute à l'heure. Ca fait tout de même pas mal moins que 43 bytes
Pour le realloc ok je vais faire ainsi alors merci.
Marsh Posté le 26-10-2007 à 22:14:50
nan mais strlen partage déjà une fois la chaîne ...
Donc autant partir de puis le début, si on suis ton calcul, cette méthode est celle qui lit le moins de bytes, exactement n.
Marsh Posté le 26-10-2007 à 22:17:39
c'est pas vraiment la peine de realloc tu sais. Surtout que c'est faire l'hypothèse que *table a été alloué avec malloc et est le début d'une allocation avec malloc. Donc mieux vaut ne rien faire, juste tronquer. Keep It Stupid Simple.
Sinon bool c'est du C++ ou C99, si tu sais pas.
Marsh Posté le 26-10-2007 à 23:57:50
Pour strlen c'est vrai. Mais c'est probablement plus rapide que les tests que je fais. Enfin bon c'est ce qu'on m'a conseillé de faire, donc je vais faire comme cela.
Pour le realloc c'est pas faux, sur mon test je fais un malloc avant mais on ne sait pas ce que ca peut être bonne remarque merci.
Pour le bool je sais oui Il vaut mieux utiliser un int en C normalement?
Merci
Marsh Posté le 27-10-2007 à 00:09:11
non c'est pas mieux. C'est juste que si tu veux bool en C, il faut include <stdbool.h>. Le coup du strlen c'est un peu bête. Pour realloc, si tu vires cet aspect inutile, ça simplifie d'autant ta fonction et son utilisation
Marsh Posté le 27-10-2007 à 00:14:15
ooh je ne savais pas j'ai toujours utilisé bool sans header.
Ca fait plus 'clean' dans un exo avec header si on fait du C j'imagine.
Pour le strlen je vais y réfléchir mais je n'ai plus beaucoup de temps.
Pour realloc ca simplifie à peine ma fonction (bon plus besoin de char** et (*table) partout c'est sûr).
Ce qui m'embete c'est que là je peux tester mon code avec de l'ASCII standard, mais aucune idée de comment faire avec des MBCS Si ca se trouve mon algo est foireux mais je n'arrive pas à tester, VS me demande toujours un encoding et j'ai beau tout essayé je n'arrive à rien ;'(
Vraiment merci pour ton aide depuis ce matin
Marsh Posté le 27-10-2007 à 00:18:51
gee a écrit : ooh je ne savais pas j'ai toujours utilisé bool sans header. |
vade retro vc++
gee a écrit :
Pour realloc ca simplifie à peine ma fonction (bon plus besoin de char** et (*table) partout c'est sûr). |
Si tu veux, son utilisation est aussi plus simple à comprendre.
Ce travail avec realloc, c'est du hors-sujet.
Si tu veux le faire, tu peux faire une fonction après genre trim_alloc
Code :
|
Marsh Posté le 27-10-2007 à 00:21:32
ok je vois ce que tu veux dire.
(je me met a GCC là mais au travail j'ai du VS...)
Sinon si tu as une idée pour tester sur d'autre charset je prend. J'ai essayé de copier des charactères depuis wikipedia en Japonais mais ce n'était pas une bonne idée
Marsh Posté le 27-10-2007 à 00:23:49
Si t'es sous windows, je sais pas, prend jedit et enregistres des textes dans différents codages ... mais je vois pas à quoi ça servirait vu que ton codage 1 ou 2 B il est fictif (du moins que j'en connais pas).
Marsh Posté le 27-10-2007 à 00:25:38
t'as pas tort. je n'ai rien trouvé qui suit ce codage, en japonais ca n'a pas l'air bien loin mais y'a des précisions. Genre ca commence par un 1 et après ca doit être entre telle et telle valeurs et trucs du genre.
En fait je ne peux que tester à la main alors
Bon bah je vais relire boucler le tout.
Merci!
Marsh Posté le 27-10-2007 à 00:58:42
bon bah voilà c'est bouclé.
Taz et Matafan je vous dédirai ma gloire si c'était bien fait
Marsh Posté le 26-10-2007 à 18:26:55
Salut,
j'aurais surement pas mal de questions là-dessus mais pour l'instant une simple.
Voilà je dois enlever la dernière lettre d'une string mais je ne sais pas s'il s'agit d'une lettre sur une ou deux bytes (MBCS). On m'a dit que pour savoir sur quoi je me trouve il faut regarder la valeur de la carry à 1 ou 0 du 1er byte pour savoir si c'est un couple ou non. Mais le 2e byte peut ou pas avoir la bonne valeur de la carry aussi.
On m'a donc dit de remonter ma chaine de chars jusqu'à avoir 2 carry de suite à 0 mais je ne comprend pas pourquoi j'en ai besoin de 2, pour moi une seule suffit car je sais que forcément ce qui est après une carry à 0 n'est pas lié au byte avec une carry à 0.
Bref mon explication est surement un peu tordue, mais si vous voyez de quoi je parle ca m'interresse merci.
Message édité par gee le 26-10-2007 à 18:33:25
---------------
"Phildar t'es vraiment une pute pas finie toi! Et Manu le gros porc arrete de t'marrer!"