Toupper avec lettres accentuées

Résolu/Fermé
steph31 - 3 janv. 2014 à 09:56
 steph31 - 8 janv. 2014 à 10:33
Bonjour, j'aurais voulu savoir comment faire pour mettre en majuscules avec accents des lettres minuscules avec accents, en utilisant des fonctions de base en C genre toupper() ou towupper() ?
En gros je voudrais à partir de cette lettre : 'é' arriver à 'É'

Merci d'avance

15 réponses

fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 835
3 janv. 2014 à 15:13
(Le fflush n'est pas superflu, car il y a un serveur de message qui tourne en parallèle et qui envoie des messages à l'écran, sans ce flush, les printf apparaissent à la fin de l'exécution :p ).
Bizarre ce que tu me dis. S'il y a un '\n' à la fin de la chaîne (ce qui est le cas ici) que tu affiches, cela fait un flush explicite (c'est la norme qui le dit). Après effectivement, si tu affiches une chaîne sans '\n', il faudra mettre un fflush(stdout).

les caractères ascii étendus classique (pas les caractères sur 3 octets on dirait)
Si tu parles de toupper(), il fait la conversion sur les caractères classiques (1 byte).
Mais, moi je te parlais de towupper() (et non c'est pas une faute de frappe le w ;-)). Cette fonction te permet de convertir les accents en lettre majuscule.
Pour l'implémentation, il te suffit de faire une boucle for sur tous les caractères et utiliser towupper(). Et c'est tout. 2 lignes ;-)
1
Je poste une solution à mon problème, il doit y'en avoir des dizaines, mais celle-ci me convient parfaitement, je la poste dans le cas où ça puisse servir à quelqu'un.

je ne vais pas mettre de code mais juste le principe !
Pour info j'utilise la librairie ICU.

Donc au départ on a une chaine de caractère, qui peut être en UTF-8, UTF-16, ISO etc, peut importe la locale utilisée.
Ensuite on convertit cette chaine en UTF-32 (avec un convertisseur ICU) en prenant en compte l'endianness du système : c'est là où était le piège dans mon cas, je convertissais en big endian sur une machine little endian, donc grosse prise de tête lol. Du coup la chaîne convertie en UTF-32 est maintenant au format wide char. On peut donc utiliser les fonctions C classiques (towupper() par exemple), mais j'ai préféré continuer avec ICU, vu que j'avais commencé avec !

Après on effectue un UPPER grâce à la fonction ICU u_strToUpper() (ou alors avec la fonction C towupper(), caractère par caractère).

Enfin on effectue une nouvelle conversion avec ICU vers la locale d'origine.

Voila, j'espère ne pas avoir dis de connerie, sinon reprenez moi :)
1
ellana29460 Messages postés 689 Date d'inscription lundi 7 octobre 2013 Statut Membre Dernière intervention 12 septembre 2015 172
3 janv. 2014 à 10:23
Il n'y a pas de methode rapide.
tu peux faire une fonction pour ca avec un enorme

void mon_toupper(char[] mot, int tailleDuMot)
{
    char lettre;
    for(lettre=0;lettre<tailleDuMot; lettre ++)
    {
        switch(mot[lettre])
        {
        case 'à':
            mot[lettre] = 'Á';
            break;
        case '...':
            mot[lettre] = '...';
            break;
        }
    }
}
0
ellana29460 Messages postés 689 Date d'inscription lundi 7 octobre 2013 Statut Membre Dernière intervention 12 septembre 2015 172
3 janv. 2014 à 10:24
voila un lien vers un autre sujet : mettre des accents sur les majuscules. la meilleure reponse donne la liste des lettres "bizares" et complexes a obtenir sur ordi.

>>> le lien <<<
0
ellana29460 Messages postés 689 Date d'inscription lundi 7 octobre 2013 Statut Membre Dernière intervention 12 septembre 2015 172
5 janv. 2014 à 19:29
ATTENTION : erreur dans le code : ligne 1 : char mot[] et non pas char[] mot
0
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 835
5 janv. 2014 à 20:17
Oui, c'est ce que j'ai dit en post #5 ;-)
0
Merci pour ta réponse, ça fait un peu bourrin en effet :p!
Je vais voir ce que je peux faire!
0
ellana29460 Messages postés 689 Date d'inscription lundi 7 octobre 2013 Statut Membre Dernière intervention 12 septembre 2015 172
3 janv. 2014 à 10:32
effectivement, mais dans le table ascii, les caracteres ne se suivent pas dans le meme ordre, donc on ne peut pas tout simplement ajouter X a la lettre ...
0
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 835
3 janv. 2014 à 12:01
char[] mot
Ce n'est pas char [] mot mais char mot[]...
0
ellana29460 Messages postés 689 Date d'inscription lundi 7 octobre 2013 Statut Membre Dernière intervention 12 septembre 2015 172
5 janv. 2014 à 19:28
ah oui, désolé, j'avais pas fait gaffe... (j'ai voulu gagner 30 secondes en ne compilant pas, j'aurai pas du ...).

merci d'avoir vu l'erreur =) je corrige ça tout de suite
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 835
3 janv. 2014 à 12:03
Bonjour,

Effectivement, il faut que tu te créées la fonction toi-même.
Mais tu arrives sur un sujet pas évident : l'encodage.
Dans ton éditeur, les caractères sont encodées en quoi ?
Dans ta console, en quoi c'est encodé ?

Cdlt,
0
La locale de la console est "en_US.UTF-8", et je pense que l'éditeur (KDevelop) est également en UTF8.
J'essaye d'utiliser la librairie ICU, mais visiblement je suis confronté au même soucis, ça convertit très bien les caractères "normaux", et dès qu'il y a un accent, la lettre n'est pas convertie...
0
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 835
3 janv. 2014 à 13:49
En UTF8, les caractères dont tu parles (avec caractères) sont stockés sur 2 bytes. Il faut donc passer par les wide char (wchar_t).
Tu utilises quelle version de C ? C89/90 ou C99 ?

Cdlt,
0
Je ne sais pas quelle est la version, dans le makefile j'ai rien précisé de particulier donc ça doit être la valeur par défaut.

En effet j'ai remarqué que ces lettres étaient sur plusieurs octets (genre le 'é' c'est C3A9 en héxa), mais après j'ai pas très bien compris le principe des wide char, hier il me semble que j'ai essayé, sans succès; je vais retenter au cas ou j'aurais loupé un truc !
0
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 835
Modifié par fiddy le 3/01/2014 à 14:01
Tu es sous GNU/Linux, j'imagine donc que tu compiles avec gcc.
Lorsque tu compiles, utilise -std=c99 (pour compiler en C99). Ainsi tu pourras utiliser les caractères étendus.
Teste :
wchar_t test[]=L"aééa";
wprintf(L"Avant conversion : %ls\n",test);
if(test[1]==L'é') {
     test[1]=L'É';
}
wprintf(L"Après conversion : %ls\n",test);

N'oublie pas de rajouter wchar.h (#include).

Google is your friend
0
J'ai essayé ton bout de code, visiblement rien ne s'affiche. Après je ne peux pas utiliser "-std=c99" car je développe sur une application de l'entreprise où je travaille, et malheureusement je ne peux pas faire des choses comme ça :D.
C'est pour ça que je suis coincé!
Le fait que rien ne s'affiche est lié au fait que std=c99 ne soit pas spécifié ?
0
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 835
3 janv. 2014 à 14:23
Tu dis que rien ne s'affiche. C'est bizarre, il devrait au moins affiché la chaîne (même si l'encodage n'est pas correct).
As-tu eu des warnings remontés par le compilateur ?
Peux-tu poster le code entier que tu as mis lorsque tu as testé mon code.
0
Bon en fait y'avais des warnings (mélangés à d'autres qui non rien à voir c'est pour ça je les avaient pas vu)
Bon du coup j'arrive à avoir quelque chose en mettant des printf au lieu des wprintf :

wchar_t test[]=L"aééa";

    printf("(printf) Avant conversion : [%ls]\n",test);
    wprintf(L"(wprintf) Avant conversion : [%ls]\n",test);
    if(test[1]==L'é') {
        test[1]=L'É';
    }
    printf("(printf) Après conversion : [%ls]\n",test);
    wprintf(L"(wprintf) Après conversion : [%ls]\n",test);
    fflush(stdout);


Résultat :
(printf) Avant conversion : [aééa]
(printf) Après conversion : [aÉéa]

(je ne sais pas comment on met un bloc de code^^)
0
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 835
Modifié par fiddy le 3/01/2014 à 14:48
Pour le bloc de code, il suffit de cliquer sur la balise "code" (à droite du bouton "souligné") et de choisir "C".
Pour info, ton fflush(stdout) est superflu puisqu'il y a un flush explicite ci-dessus.
Sinon, le code fonctionne bien. Tu as aééa, qui devient aÉéa. Ca ne te convient pas ? Il te suffit maintenant de te créer la fonction en utilisant la notation ci-dessus.

Niveau algorithmique et si tu veux le faire toi-même, tu peux utiliser deux tableaux pour convertir les lettres majuscules. Si tu vois pas comment faire, je peux te mettre un exemple.
Sinon tu peux utiliser la fonction towupper() (sur le même principe que toupper())
0
(Le fflush n'est pas superflu, car il y a un serveur de message qui tourne en parallèle et qui envoie des messages à l'écran, sans ce flush, les printf apparaissent à la fin de l'exécution :p ).

Donc en fait après réflexion ça peut le faire, car en fait je dois reproduire le comportement d'une fonction de la database DB2, et visiblement DB2 effectue un toupper() uniquement sur les caractères ascii étendus classique (pas les caractères sur 3 octets on dirait). Maintenant faut que je trouve une façon propre de coder tout ça et ça devrait le faire.

En tout cas merci beaucoup de ton aide !
0
Ben oué je sais pas ça dépend des endroits où sont placés les printf, en tout cas c'est sur que si je fais pas un fflush en dur, ils apparaissent à la fin (c'est peut être lié à la config du pc ou du compilateur je ne sais pas!).

Non je parlais pas de la fonction toupper() C, mais d'une fonction de DB2 qui fait un équivalent à toupper()
En gros pour résumer ça sera beaucoup plus simple à comprendre :
db2 "select upper('é'), hex(upper('é')), hex('é') from temp"

va donner comme résultat :
É C389 C3A9

Et donc je dois via un programme en C, obtenir le même résultat que DB2.

Donc ce que je disais, et qui n'était certainement pas clair^^, c'est que DB2 convertit uniquement les caractères ascii étendus, mais si je fais un test sur des caractères qui sont sur 3 octets par exemple :
db2 "select upper('€'), hex(upper('€')), hex('€') from temp"

avec comme résultat :
€ E282AC E282AC
0
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 835
3 janv. 2014 à 16:37
Je ne suis pas spécialiste de db2, mais à mon avis ce n'est pas qu'il ne convertit pas les caractères qui sont codés sur plusque 2 bytes, mais tout simplement qu'il convertit ce qu'il sait convertir. Pour toi, c'est quoi la majuscule de € ?
0
steph31 Messages postés 9 Date d'inscription jeudi 20 septembre 2012 Statut Membre Dernière intervention 3 janvier 2014
Modifié par steph31 le 3/01/2014 à 17:54
Ben justement pour moi y'a pas de majuscule pour €, mais je voulais vérifier directement avec DB2 pour être sur, on sait jamais ^^
Mais du coup avec towupper() je devrais m'en sortir, vu que visiblement je dois convertir les caractères de la table ascii classique.
Après la j'ai dégrossi la partie facile de l'histoire, c'est à dire partir de caractères écrits en UTF-8; mais en fait les données que j'ai en entrée sont en UTF-16. Maintenant la problématique ça va être de convertir les données utf16 en wide char pour pouvoir faire towupper(), et d'après mes tests tout à l'heure ça à pas l'air de marcher des masses lol.

En tous les cas je suis parti du boulot donc je reprendrai tout ce schmilblick lundi matin à la 1ère heure :)

Bon weekend et a+ :p
0
Je viens de comprendre ce que tu disais avec towupper(), je viens de tester ce code :
  int i=0;
  wchar_t str[] = L"Tést String.\n";
  wchar_t c;
  while (str[i])
  {
    c = str[i];
    putwchar (towupper(c));
    i++;
  }


et j'obtiens :
T?ST STRING.

Tu saurais par hasard comment voir le code hexa de chaque caractère au moment du print?
0
Bon en fait j'ai trouvé c'est bon pour afficher la valeur
0