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 :

write un unicode


Sujet :

C

  1. #1
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2016
    Messages
    36
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2016
    Messages : 36
    Par défaut write un unicode
    Bonjour a tout le monde

    Bon ba je pense que le titre en dit gros lol...

    Je voudrais avec write afficher un caractère unicode.

    je sais que je dois utiliser le type wchar_t.

    mon problème est qu'a l'affichage, je me retrouve avec des 0 en plein milieu de ma chaine... je ne comprend pas pourquoi...

    Pouvez-vous m'aider svp?

    merci

  2. #2
    Expert confirmé
    Avatar de Mat.M
    Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2006
    Messages
    8 532
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2006
    Messages : 8 532
    Par défaut
    bonjour,
    ce serait possible de mieux écrire ses messages ? Merci
    Par "write" tu veux écrire dans un fichier ou à l'écran ?
    Tout dépend de l'OS utilisé.
    Si c'est pour afficher avec printf à l'écran il faut effectuer une conversion wchar_t vers char (mais il y a peut-être d'autres méthodes , je ne programme jamais en mode console)

    Mais sans code on peut pas répondre.

  3. #3
    Expert confirmé
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 771
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 771
    Par défaut
    Citation Envoyé par fpasquer Voir le message
    Mon problème est qu'a l'affichage, je me retrouve avec des 0 en plein milieu de ma chaine... je ne comprend pas pourquoi...
    Ce sont les caractères ASCII codés en UTF-16

  4. #4
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2016
    Messages
    36
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2016
    Messages : 36
    Par défaut
    Bonjour, merci de ta réponse.

    Je vais mieux écrire mes messages.

    Je suis sur el capitan.

    Dans un premier temps, le but serai d'afficher un caractère sur la sortie standard. Si je voudrais qu'avec peu de modifications pouvoir écrire sur un fichier bien sur.

    Je ne veux pas afficher avec printf, je dois utiliser write et juste write. Je ne cherche pas de code, je voudrais juste savoir comment faire.

    Merci

  5. #5
    Membre Expert
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Par défaut
    Unicode seul ça ne veut pas dire grand chose. Quelle est l'implémentation qui t'intéresses ? UTF-8, UTF-16/UCS-2, UTF-32..?

  6. #6
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2016
    Messages
    36
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2016
    Messages : 36
    Par défaut
    en faite, je dois faire pareil que printf("%S\n", L"texte").

    je pense que les caractères sont en UPF-8

    Merci

  7. #7
    Expert confirmé
    Avatar de Mat.M
    Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2006
    Messages
    8 532
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2006
    Messages : 8 532
    Par défaut
    mes excuses alors je ne peux pas t'aider je ne connais que la programmation Windows win32.
    Il n'y a pas une aide pour développeur équivalent au MSDN de Microsoft mais pour El Capitan ?

  8. #8
    Membre Expert
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Par défaut
    Citation Envoyé par fpasquer Voir le message
    en faite, je dois faire pareil que printf("%S\n", L"texte").


    Citation Envoyé par fpasquer Voir le message
    je pense que les caractères sont en UPF-8
    Tu penses ?

    Bon sans plus de détails :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    setlocale(LC_ALL, "" ou "fr_FR.UTF-8");
    printf("%s\n", anything);

  9. #9
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Je ne pense pas qu'il soit possible avec les restrictions Épitiennes d'afficher directement un wchar_t (ou un tableau de).

    Tu vas devoir toi-même convertir l'encodage du wchar_t en question en UTF-8, avec une longueur dépendant de la valeur du codepoint (ou partir directement d'un texte UTF-8) pour pouvoir l'afficher avec un write() sur STDOUT_FILENO (en supposant que la machine sur laquelle tu dois faire ça soit configurée pour UTF-8, si tu n'as pas le droit à setlocale()).
    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.

  10. #10
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2016
    Messages
    36
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2016
    Messages : 36
    Par défaut
    Bonjour, et merci pour vos réponses
    je suis sur la bonne voie, avec write, j'arrive a afficher des caractères sur 2 octés.
    Nom : Capture d’écran 2016-01-13 à 14.31.15.png
Affichages : 3589
Taille : 18,7 Ko
    par contre jái du faire une erreur dans les caractères sur plus de 2 octes, car ils ne s'affichent pas bien ...
    voici mon main : je suis obligé de faire un screen shot, les caracteres asiatique ne passent pas a l'affichage...
    Nom : Capture d’écran 2016-01-14 à 09.35.51.png
Affichages : 3923
Taille : 113,3 Ko


    voici les fonctions qui transforme un wchar_t en plusieurs octés.
    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
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
     
    static int		type_four_c(char **s, int **i, wchar_t data, t_dat **d)
    {
    	char		*sdata;
    	int			ret;
     
    	if ((sdata = ft_memalloc(sizeof(char) * 5)) == NULL)
    		return (-1);
    	sdata[0] = (((data & 0x1c0000) >> 18) + 0xF0);
    	sdata[1] = (((data & 0x03F000) >> 12) + 0x80);
    	sdata[2] = (((data & 0x0Fc0) >> 6) + 0x80);
    	sdata[3] = ((data & 0x003F) + 0x80);
    	sdata[4] = '\0';
    	ret = type_str(s, i, sdata, d);
    	ft_memdel((void**)&sdata);
    	return (ret);
    }
     
    static int		type_three_c(char **s, int **i, wchar_t data, t_dat **d)
    {
    	char		*sdata;
    	int			ret;
     
    	if ((sdata = ft_memalloc(sizeof(char) * 4)) == NULL)
    		return (-1);
    	sdata[0] = (((data & 0xF000) >> 12) + 0xE0);
    	sdata[1] = (((data & 0x0Fc0) >> 6) + 0x80);
    	sdata[2] = ((data & 0x003F) + 0x80);
    	sdata[3] = '\0';
    	ret = type_str(s, i, sdata, d);
    	ft_memdel((void**)&sdata);
    	return (ret);
    }
     
    static int		type_two_c(char **s, int **i, wchar_t data, t_dat **d)
    {
    	char		*sdata;
    	int			ret;
     
    	if ((sdata = ft_memalloc(sizeof(char) * 3)) == NULL)
    		return (-1);
    	sdata[0] = (((data & 0x07c0) >> 6) + 0xc0);
    	sdata[1] = ((data & 0x003F) + 0x80);
    	sdata[2] = '\0';
    	ret = type_str(s, i, sdata, d);
    	ft_memdel((void**)&sdata);
    	return (ret);
    }
     
    int				type_one_c(char **s, int **i, char data, t_dat **d)
    {
    	char	*sdata;
    	int		ret;
     
    	if ((sdata = ft_memalloc(sizeof(char) * 2)) == NULL)
    		return (-1);
    	(*d)->type = OTHER;
    	sdata[0] = (data == 0) ? '~' : data;
    	sdata[1] = '\0';
    	ret = type_str(s, i, sdata, d);
    	ft_memdel((void**)&sdata);
    	if (data == 0)
    		(*(*s + **i)) = 0;
    	return (ret);
    }
     
    int				type_wchar(char **s, int **i, wchar_t data, t_dat **d)
    {
    	(*d)->type = OTHER;
    	if (data <= 0x7f)
    		return (type_one_c(s, i, data, d));
    	else if (data <= 0x7FF)
    		return (type_two_c(s, i, data, d));
    	else if (data <= 0xFFFF)
    		return (type_three_c(s, i, data, d));
    	else if (data <= 0x1FFFFF)
    		return(type_four_c(s, i, data, d));
    	return (-1);
    }
    voici aussi la fonction qui place la suite d'octe dans la chaine de caractere

    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
    int				jump = 1;
     
    int				decalage(char *s, int i)
    {
    	int			mem;
     
    	mem = i;
    	while (i >= 0)
    	{
    		if ((*(s + i)) == '%' && mem > i)
    			break ;
    		i--;
    	}
    	return ((i < 0) ? mem : i);
    }
     
    int				type_str(char **s, int **i, char *data, t_dat **d)
    {
    	char		*s_ret;
    	char		*s_end;
    	char		*tmp;
    	int			len;
     
    	if (data == NULL)
    		data = ft_strdup("(null)");
    	s_ret = ft_strndup(*s, decalage(*s, **i));
    	s_end = ft_strsub(*s, **i + jump, ft_strlen(*s));
    	if (data == NULL || s_ret == NULL || s_end == NULL)
    		return (-1);
    	if (inser_flags(&data, d) == -1)
    		return (-1);
    //	printf("test >%s<>%s<>%s<\n", s_ret, data, s_end);
    	if ((tmp = ft_multijoin(3, s_ret, data, s_end)) == NULL)
    		return (-1);
    	ft_memdel((void**)s);
    	*s = tmp;
    	(**i) = ft_strlen(s_ret) + ft_strlen(data) - 1;
    	len = **i + ft_strlen(s_end) - 1;
    	ft_memdel((void**)&s_ret);
    	ft_memdel((void**)&s_end);
    	return (**i);
    }
    Pouvez-vous m'aider a trouver mon erreur svp ? Mon erreur est dans la fonction type_three_c je pense Merci

  11. #11
    Membre Expert
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Par défaut
    Que sont sensées faire toutes ces fonctions ? Quelles sont leurs pré- et post-conditions ? C'est pas que je rechigne à t'aider mais déchiffrer les walls of code pour moi c'est pas ultra fun.

    Je n'ai pas bien compris pourquoi tu as besoin de wchar_t pour lire de l'UTF-8.

  12. #12
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2016
    Messages
    36
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2016
    Messages : 36
    Par défaut
    Le but de mon ft_printf est d'afficher l'ensemble des caractères possible en UTF-8. (Je gère les caractères ascii différemment pour optimiser mon programme.)

    quand ft_printf, tombe sur une conversion de type %S majuscule, il attend une chaine de caractère de type L"texte". Pour gérer ce type de paramètre, j'appel en boucle pour chaque caractère la fonction type_wchar.

    son prototype est :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int				type_wchar(char **s, int **i, wchar_t data, t_dat **d)
    >s< est la chaine de caractère format de ft_printf : Ex dans mon main "{%S}"
    >i< est mon index, ma position dans s. Ce qui me determine ou je place data dans s.
    >data< est le caractère wchar_t pas encore converti en char que je vais placer dans s a la position du premier % a gauche.
    >d< c'est pour les flags (pas utile dans l'exemple)

    type_wchar peut appeler 4 fonctions en fonction de la valeur de data.
    Si data est sur 1 octe type_char appel type_one_c
    Si data est sur 2 octes type_char appel type_two_c
    Si data est sur 3 octes type_char appel type_three_c
    Si data est sur 4 octes type_char appel type_four_c

    Les fonctions type_one_c type_two_c type_three_c type_four_c coupe la valeur de data en octe en suivant le masque unicode suivant : lien
    C'est 4 fonctions envoient donc soit 1 2 3 ou 4 octes a la fonction type_str qui place ces octes a la place du premier % a gauche trouvé dans s. Cette fonction fait aussi avancer i (mon index)

  13. #13
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Citation Envoyé par Matt_Houston Voir le message
    Que sont sensées faire toutes ces fonctions ? Quelles sont leurs pré- et post-conditions ? C'est pas que je rechigne à t'aider mais déchiffrer les walls of code pour moi c'est pas ultra fun.

    Je n'ai pas bien compris pourquoi tu as besoin de wchar_t pour lire de l'UTF-8.
    C'est un épitarque, il ne peut donc pas utiliser les fonctions autre que write() pour l'affichage. Et write() sur STDOUT_FILENO s'attend à des caractères étroits, et non larges.

    Mais ça n'excuse en rien les noms de paramètres à un seul caractère et l'absence totale de commentaires documentant ces fonctions.
    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.

  14. #14
    Membre Expert
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Par défaut
    C'est mieux avec ces informations effectivement.


    Citation Envoyé par fpasquer Voir le message
    Le but de mon ft_printf est d'afficher l'ensemble des caractères possible en UTF-8. (Je gère les caractères ascii différemment pour optimiser mon programme.)
    Premature optimization et source d'erreurs supplémentaire si tu veux mon avis. UTF-8 a justement été conçu pour être compatible avec ASCII et ne pas générer de différence de traitement. Tu économises une comparaison par caractère, c'est peanuts.


    Citation Envoyé par Médinoc Voir le message
    C'est un épitarque, il ne peut donc pas utiliser les fonctions autre que write() pour l'affichage. Et write() sur STDOUT_FILENO s'attend à des caractères étroits, et non larges.
    Justement, si la chaîne d'entrée est en UTF-8 (taille de caractère variable multiple de sizeof(char)), pourquoi est-ce une séquence de wchar_t (taille de caractère fixe) ? C'est imposé ?


    Citation Envoyé par Médinoc Voir le message
    Mais ça n'excuse en rien les noms de paramètres à un seul caractère et l'absence totale de commentaires documentant ces fonctions.
    Oui c'est surtout la petite ligne qui explicite le comportement de la fonction qui suit qui est importante.

  15. #15
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Citation Envoyé par Matt_Houston Voir le message
    Justement, si la chaîne d'entrée est en UTF-8 (taille de caractère variable multiple de sizeof(char)), pourquoi est-ce une séquence de wchar_t (taille de caractère fixe) ? C'est imposé ?
    Là façon dont je comprenais le problème, c'est qu'on se voit imposer une chaîne de wchar_t en entrée (qui sous *n*x, représente directement des code points contrairement à Windows, donc pas de problèmes d'UTF-16), qu'il faut donc convertir en UTF-8 pour pouvoir l'afficher avec write().

    Là où le code posté peut paraître contre-intuitif, c'est qu'il est programmé par exceptions (que des switchs et des cas particuliers hard-codés) là où je j'aurais plutôt codé la conversion avec des boucles (avec probablement quand même un cas particulier pour l'ASCII).
    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.

  16. #16
    Membre Expert
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Par défaut
    Ok c'est une restriction imposée par la séquence d'entrée, pigé !

  17. #17
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2016
    Messages
    36
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2016
    Messages : 36
    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
    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
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    #include "type_char.h"
    #include "libft.h"
    #include "type_str.h"
     
    static int			type_four_c(char **format, unsigned int **i, wchar_t data,
    		t_flags *flags)
    /*
    **	alloue une nouvelle chaine de caractere de 5 octets
    **	assigne la valeur data a sdata[0]
    **	place l'octet avec type_str
    **	free la chaine allouee
    **	retourne le resultat de type_str
    */
    {
    	char			*sdata;
    	int				ret;
     
    	if ((sdata = ft_strnew(5)) == NULL)
    		return (-1);
    	sdata[0] = (((data & 0x1c0000) >> 18) + 0xF0);
    	sdata[1] = (((data & 0x03F000) >> 12) + 0x80);
    	sdata[2] = (((data & 0x0Fc0) >> 6) + 0x80);
    	sdata[3] = ((data & 0x003F) + 0x80);
    	ret = type_str(format, i, sdata, flags);
    	ft_memdel((void**)&sdata);
    	return (ret);
    }
     
    static int			type_three_c(char **format, unsigned int **i, wchar_t data,
    		t_flags *flags)
    /*
    **	alloue une nouvelle chaine de caractere de 4 octets
    **	assigne la valeur data a sdata[0]
    **	place l'octet avec type_str
    **	free la chaine allouee
    **	retourne le resultat de type_str
    */
    {
    	char			*sdata;
    	int				ret;
     
    	if ((sdata = ft_strnew(4)) == NULL)
    		return (-1);
    	sdata[0] = (((data & 0xF000) >> 12) + 0xE0);
    	sdata[1] = (((data & 0x0Fc0) >> 6) + 0x80);
    	sdata[2] = ((data & 0x003F) + 0x80);
    	ret = type_str(format, i, sdata, flags);
    	ft_memdel((void**)&sdata);
    	return (ret);
    }
     
    static int			type_two_c(char **format, unsigned int **i, wchar_t data,
    		t_flags *flags)
    /*
    **	alloue une nouvelle chaine de caractere de 3 octets
    **	assigne la valeur data a sdata[0]
    **	place l'octet avec type_str
    **	free la chaine allouee
    **	retourne le resultat de type_str
    */
    {
    	char			*sdata;
    	int				ret;
     
    	if ((sdata = ft_strnew(3)) == NULL)
    		return (-1);
    	sdata[0] = (((data & 0x07c0) >> 6) + 0xc0);
    	sdata[1] = ((data & 0x003F) + 0x80);
    	ret = type_str(format, i, sdata, flags);
    	ft_memdel((void**)&sdata);
    	return (ret);
    }
     
    int					type_char(char **format, unsigned int **i, char data,
    		t_flags *flags)
    /*
    **	alloue une nouvelle chaine de caractere de 2 octets
    **	assigne la valeur data a sdata[0]
    **	place l'octet avec type_str
    **	free la chaine allouee
    **	retourne le resultat de type_str
    */
    {
    	char			*sdata;
    	int				ret;
     
    	if ((sdata = ft_strnew(2)) == NULL)
    		return (-1);
    	sdata[0] = data;
    	ret = type_str(format, i, sdata, flags);
    	ft_memdel((void**)&sdata);
    	return (ret);
    }
     
    int					type_wchar(char **format, unsigned int **i, wchar_t data,
    		t_flags *flags)
    /*
    **	compte le nomdre d'octet(s) qui compose data
    **	appel la bonne fonction en fonction du nombre d'octet(s) qui compose data
    **	place la suite d'octets
    */
    {
     
    	if (data < 128)
    		return (type_char(format, i, data, flags));
    	else if (data < 2048)
    		return (type_two_c(format, i, data, flags));
    	else if (data < 65536)
    		return (type_three_c(format, i, data, flags));
    	else if (data < 2097152)
    		return (type_four_c(format, i, data, flags));
    	return (-1);
    }
    Voici mon dernier code, je ne trouve toujours pas mon erreur... elle est dans les fonctions type_three_c et type_four_c ...

    Merci de votre aide

    Voici en plus type_str

    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
    53
    54
    55
    56
    int				type_str(char **format,unsigned int **i, char *data,
    		t_flags *flags)
    /*
    **	place data dans format a la position flags->start.
    **	les flags sont placees grace a la fonction inser_flags
    **	decale i en fonction du nombre de caracteres insere dans format
    */
    {
    	char		*s_ret;
    	char		*s_end;
    	char		*tmp;
    	int			len;
     
    	if (data == NULL)
    		data = ft_strdup("(null)");
    	s_ret = ft_strndup(*format, flags->start);
    	s_end = ft_strsub(*format, **i + 1, ft_strlen(*format));
    	if (data == NULL || s_ret == NULL || s_end == NULL)
    		return (-1);
    	if (inser_flags(&data, flags) == -1)
    		return (-1);
    //	printf("\ntest >%s<>%s<>%s<\n", s_ret, data, s_end);
    	if ((tmp = ft_multijoin(3, s_ret, data, s_end)) == NULL)
    		return (-1);
    //	ft_memdel((void**)format);
    	*format = tmp;
    	(**i) = ft_strlen(s_ret) + ft_strlen(data) - 1;
    	len = **i + ft_strlen(s_end) - 1;
    	ft_memdel((void**)&s_ret);
    	ft_memdel((void**)&s_end);
    	return (**i);
    }
     
    int					type_wstr(char **format, unsigned int **i, wchar_t *data,
    		t_flags *flags)
    /*
    **	convertie data en plusieurs octets
    **	place octets par octets dans format a la position de flags->position
    **	retourne la nouvelle valeur de i + le nombre d'octets ajoute, ou -1 s'il y a
    **		une erreur.
    */
    {
    	int				ret;
    	unsigned int 	j;
    char	*l = setlocale(LC_ALL, "");
    	j = 0;
    	if (data == NULL)
    		return (type_str(format, i, "(null)", flags));
    	while (data[j] != L'\0')
    	{
    		if ((ret = type_wchar(format, i, data[j++], flags)) == -1)
    			return (-1);
    		flags->start = ret + 1;
    	}
    	return (ret);
    }

  18. #18
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Je vais jeter un coup d'œil à ça, mais je vois déjà un problème flagrant qui augmente la difficulté sans grande raison: Pour i, une seule étoile suffit, il n'y a pas besoin de deux.

    De plus, pour type_str(), data devrait être un pointeur const (et tu ne devrais pas faire de strdup quand c'est nul, un simple = "(null)" suffira, puisque type_str() n'est pas censée toucher à la chaîne)
    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.

  19. #19
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    J'ai également remarqué que tu faisais des allocations là où un buffer statique alloué sur la pile par l'appelant aurait suffit...

    Finalement j'ai fait ma propre fonction de conversion d'un codePoint en UTF-8, qui me parait quand même beaucoup plus simple.
    Ça utilise la technique de remplir un buffer par la fin, également très utile quand il s'agit de formater un nombre entier par divisions successives par la base.
    D'ailleurs, d'un certain point de vue, l'encodage en UTF-8, c'est juste ça: Formater un nombre entier par divisions successives par 64...
    Code C : 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
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    int nombreBits(unsigned int valeur)
    {
    	int ret = 0;
    	unsigned int masque = 1;
    	/*cas particulier*/
    	if(valeur < 2) { return 1; }
     
    	while(valeur >= masque)
    	{
    		++ret;
    		masque <<= 1;
    		if(masque == 0)
    			return CHAR_BIT * sizeof valeur;
    	}
    	return ret;
    }
     
    /*Ajoute un caractère dans un buffer, décalant l'index vers le début*/
    void push_char(char* buffer, size_t *pIndex, char ch)
    {
    	assert(buffer != NULL);
    	assert(pIndex != NULL);
     
    	if(*pIndex == 0) { return; }
    	-- *pIndex;
    	buffer[*pIndex] = ch;
    }
    void push_uchar(char* buffer, size_t *pIndex, unsigned char ch) { push_char(buffer, pIndex, (char)ch); }
     
    char* conversion_utf8(char* buffer, size_t cchTailleBuffer, int codePoint)
    {
    	/*Indications sur le premier octet de la séquence*/
    	const int BitsUtilesDansPremierOctet[] = { 7, 5, 4, 3 };
    	const unsigned char MasquePremierOctet[] = { 0x7F, 0x1F, 0x0F, 0x07 }; /*CORRECTION: Changer dernière valeur de 3 à 7*/
    	const unsigned char PrefixePremierOctet[] = { 0x00, 0xC0, 0xE0, 0xF0 };
    	const int MaxHexetsPlus1 = sizeof MasquePremierOctet / sizeof MasquePremierOctet[0];
    	const size_t TailleMaxRequise = MaxHexetsPlus1 + 1; /*Un premier octet, 0-3 hexets, et un caractère nul terminal*/
     
    	size_t index = cchTailleBuffer;
    	unsigned int bitsCodePoint = codePoint;
    	int nbTotalBits = nombreBits(bitsCodePoint);
    	int nbBitsRestants = nbTotalBits;
    	int nbHexetsEcrits = 0;
     
    	if(buffer == NULL || cchTailleBuffer < TailleMaxRequise) { return NULL; } /*Buffer trop petit pour taille maximale d'un codePoint UTF-8*/
    	if(codePoint < 0 || nbTotalBits > 21) { return NULL; } /*codePoint hors plage*/
     
    	/* On remplit le buffer en commençant par la fin */
    	push_char(buffer, &index, '\0');
     
    	while(nbBitsRestants > BitsUtilesDansPremierOctet[nbHexetsEcrits])
    	{
    		/*La valeur est trop grande pour entrer dans le premier octet: On ajoute ses six bits de poids faible à la fin.*/
    		const unsigned int MasqueHexet = 0x0000003F;
    		const unsigned char PrefixeHexet = 0x80;
    		unsigned int bitsHexet = bitsCodePoint & MasqueHexet;
    		unsigned char hexet = (unsigned char)(bitsHexet) | PrefixeHexet;
    		push_uchar(buffer, &index, hexet);
     
    		++nbHexetsEcrits;
    		bitsCodePoint >>= 6;
    		nbBitsRestants -= 6;
    		assert(nbHexetsEcrits < MaxHexetsPlus1);
    	}
     
    	/*Et maintenant le premier octet*/
    	{
    		unsigned int bitsPremierOctet = bitsCodePoint & MasquePremierOctet[nbHexetsEcrits];
    		unsigned char premierOctet = (unsigned char)bitsPremierOctet | PrefixePremierOctet[nbHexetsEcrits];
    		push_uchar(buffer, &index, premierOctet);
    	}
     
    	/*Retourne le début de la partie 'écrite' dans le buffer*/
    	return buffer + index;
    }
    J'ai même fait quelques fonctions de test; par contre, c'est du Quick'n' dirty, pas du tout Épitesque:
    Code C : 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
    void TestUtf8(int codePoint)
    {
    	char buffer[8];
    	char* chn = conversion_utf8(buffer, sizeof buffer / sizeof buffer[0], codePoint);
     
    	/*Ici, chn contient le texte qu'il te faut. Et il pointe à l'intérieur de buffer.*/
     
    	static const char* bin4[] = { "0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111",
    	 "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111" };
    	size_t i;
    	if(chn == NULL) { printf("conversion_utf8 a retourné NULL pour %d\n", codePoint); return; }
     
    	/*La console Windows n'étant pas compatible avec UTF-8, je ne peux pas afficher directement chn ici.
    	  Par contre, je pourrais écrire chn dans un fichier, par exemple.
    	  Ici, je vais juste l'afficher en binaire pour bien vérifier les valeurs.*/
    	printf("conversion_utf8(0x%06X) (%7d): ", codePoint, codePoint);
    	for(i=0 ; chn[i]!='\0' ; i++)
    	{
    		unsigned char ch = (unsigned char)chn[i];
    		if(i != 0) { putchar(' '); }
    		printf("%s%s", bin4[(ch >> 4) & 0x0F], bin4[ch & 0x0F]);
    	}
    	putchar('\n');
    }
     
    void TestConversion(void)
    {
    	//int i;
    	//for(i=0 ; i<10 ; i++)
    	//{
    	//	printf("Nombre de bits de %2d: %d\n", i, nombreBits(i));
    	//}
    	TestUtf8('a');
    	TestUtf8(0x00007F);
    	TestUtf8(0x000080);
    	TestUtf8(0x0000A0); /*Quelques valeurs exemple*/
    	TestUtf8(0x002554);
    	TestUtf8(0x00FEFF); /*La fameuse BOM*/
    	TestUtf8(0x00FFFF);
    	TestUtf8(0x010000);
    	TestUtf8(0x10000 * 17 - 1);
    	/*Cette valeur est illégale en Unicode (car elle ne peut pas être encodée en UTF-16),
    	  mais reste acceptée par la fonction car elle ne dépasse pas 21 bits.*/
    	TestUtf8(0x1FFFFF);
    	/*Cette valeur-ci dépasse la capacité de la fonction et est donc refusée.*/
    	TestUtf8(0x200000);
    }
    Code X : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    conversion_utf8(0x000061) (     97): 01100001
    conversion_utf8(0x00007F) (    127): 01111111
    conversion_utf8(0x000080) (    128): 11000010 10000000
    conversion_utf8(0x0000A0) (    160): 11000010 10100000
    conversion_utf8(0x002554) (   9556): 11100010 10010101 10010100
    conversion_utf8(0x00FEFF) (  65279): 11101111 10111011 10111111
    conversion_utf8(0x00FFFF) (  65535): 11101111 10111111 10111111
    conversion_utf8(0x010000) (  65536): 11110000 10010000 10000000 10000000
    conversion_utf8(0x10FFFF) (1114111): 11110000 10001111 10111111 10111111
    conversion_utf8(0x1FFFFF) (2097151): 11110011 10111111 10111111 10111111
    conversion_utf8 a retournÚ NULL pour 2097152

    Edit: Attention, j'ai dû corriger un bug sur le masque du premier octet (en ligne 34), qui était invalide pour des valeurs codées sur quatre octets.
    Cela a affecté la sortie des deux avant-dernières lignes du test:
    Code X : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    conversion_utf8(0x10FFFF) (1114111): 11110100 10001111 10111111 10111111
    conversion_utf8(0x1FFFFF) (2097151): 11110111 10111111 10111111 10111111
    Je me disais bien qu'il y avait un truc bizarre.
    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.

  20. #20
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2016
    Messages
    36
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2016
    Messages : 36
    Par défaut
    Merci Medinoc,

    Tes fonctions sont plus coutes, j'aime beaucoup celle qui compte les bits.

    Ce qui me derange, c'est que j'ai exactement le meme résultat que toi ...
    Nota: j'ai gardé mes fonctions

    Le premier data est est celui de type_str, celui avec les tabs sont celui de type_four_c

    Nom : Capture d’écran 2016-01-15 à 17.13.07.png
Affichages : 3677
Taille : 58,8 Ko

    J'ai essayé avec et sans locale.h en initialisant setlocale(LC_ALL, ""); dans le main, rien a faire ...

Discussions similaires

  1. Utilisation de l'unicode dans un algo de cryptage
    Par Zazeglu dans le forum Algorithmes et structures de données
    Réponses: 2
    Dernier message: 28/10/2003, 14h38
  2. [Unicode] Internationalisation d'une application
    Par Thierry Laborde dans le forum Langage
    Réponses: 4
    Dernier message: 21/10/2003, 20h15
  3. conversion Unicode -> ASCII
    Par juzam dans le forum C
    Réponses: 8
    Dernier message: 24/07/2003, 10h07
  4. [debutant] unicode
    Par dadou91 dans le forum XML/XSL et SOAP
    Réponses: 7
    Dernier message: 23/05/2003, 10h12
  5. write() dans une socket.. unix
    Par slack dans le forum Réseau
    Réponses: 5
    Dernier message: 18/12/2002, 20h42

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