Formater string C/C++ avec caractères spéciaux sous Linux

Résolu
zaraki21 Messages postés 31 Date d'inscription lundi 2 juin 2008 Statut Membre Dernière intervention 22 avril 2011 - 21 avril 2010 à 14:45
zaraki21 Messages postés 31 Date d'inscription lundi 2 juin 2008 Statut Membre Dernière intervention 22 avril 2011 - 27 avril 2010 à 09:16
Bonjour,

Je développe actuellement une application C/C++ sous Linux destinée a un périphérique électronique embarqué. Je dois dans l'implémentation écrire une fonction qui communique avec un écran LCD externe. Cette fonction doit obligatoirement prendre en paramètre d'entrée une chaîne de caractères qui va être ensuite stocker dans un message de type "unsigned char" pour être envoyé au LCD. Tout fonctionnait jusqu'à maintenant mais le problème désormais, est d'afficher des caractères spéciaux tel que Ä,ä ou encore ö, Ö. Ces dernier étant codés sur 2 octets, mon programme ne fonctionne plus correctement, les caractères ne sont pas affichés comme ils le devraient. Après plusieurs recherches sur Internet, j'ai vu qu'il fallait que j'utilise par exemple le type "wchar_t" mais seulement voila, je ne peux pas changer le type d'entrée qui est "string" et ne peux pas avoir recours aux fonctions (fonctions non reconnues dans mon application par le compilateur) tels que "swprintf" ou encore "mbstowcs". A noter que je travaille avec un répertoire de librairie restreint du fait du caractère embarqué de l'application. Donc si quelqu'un a une idée, merci.

Code de la fonction dans le cas ou cela fonctionne avec des caractères non spéciaux :
void LCD::writeLCDMessage(std::string sParameter){
        size_t size = sParameter.size() + 1;
        char * buffer = new char[ size ];                         
strncpy(buffer, sParameter.c_str(), size);
int sizeDisplay=0;
sizeDisplay = strlen(buffer);
unsigned char pDisplayMessage[sizeDisplay];
for(int i=0; i<sizeDisplay; i++){
pDisplayMessage[i]=buffer[i];                         
}
write(lcd,pDisplayMessage,sizeof(pDisplayMessage));      
delete [] buffer;                                         
}

4 réponses

zaraki21 Messages postés 31 Date d'inscription lundi 2 juin 2008 Statut Membre Dernière intervention 22 avril 2011
27 avril 2010 à 09:16
En fait, c'est bon j'ai trouvé un code sur le net pour transformer une "string" en "wchar_t" :
template <typename InputIterator,typename OutputIterator>
OutputIterator utf8_to_wchar_t(InputIterator  begin,InputIterator  end,OutputIterator result){
for (; begin != end; ++begin, ++result){
int count      = 0; // the number of bytes in the UTF-8 sequence
unsigned c     = (unsigned char)*begin;
unsigned i     = 0x80;
    
if (c == 0xEF){
c = (unsigned char)* ++ ++ ++begin;
}
// Resynchronize after errors
    while ((c & 0xC0) == 0x80){
    	c = (unsigned char)*++begin;
    }
// Now we count the number of bytes in the sequence...
for (; c & i; i >>= 1){
++count;
}
// ...and strip the high-code-bits from the character value
c &= i - 1;
// Now we build the resulting wchar_t by appending all the character bits together
for (; count > 1; --count){
c <<= 6;
    c |=  (*++begin) & 0x3F;
}
// And we store the result in the output container
*result = c;
}
// The usual generic stuff
return result;
}


Après j'ai utilisé cette méthode en l'adaptant à mes besoins pour ainsi récupérer la "string" passée en paramètre dans un tableau "vector" de "wchar_t". Ensuite il a été facile de passer en "unsigned char" par la suite.
3
cptpingu Messages postés 3837 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 28 mars 2023 123
21 avril 2010 à 17:20
Librairie => bibliothèque (librairie est une grossière erreur de traduction du mot "library").

Tout d'abord, un petit problème qui n'a certes rien à voir, mais qui va te pourrir la vie: attention à la copie des arguments !
Ceci serait vraiment mieux:
void LCD::writeLCDMessage(const std::string& sParameter)

Tu gagne énormément en perf juste en faisant cela, sans incidence sur ton code. C'est encore plus flagrant en système embarqué !


Pour répondre à ton problème, tu peux utiliser: std::wstring et wchar_t. Normalement tu trouveras tout les fonctions nécessaires dans <cstdlib>. Si tu ne peux changer le std::string tu es très très mal. Il te faudra convertir ton std::string en std::wstring, et ce sera l'horreur.

Autre question: Tu ne peux pas faire: write(lcd, sParameter.c_str(), sParameter.size()); ?

_____________________________________________
Historique de mes créations, et quelques articles:[ http://0217021.free.fr/portfolio
http://0217021.free.fr/portfolio]
0
zaraki21 Messages postés 31 Date d'inscription lundi 2 juin 2008 Statut Membre Dernière intervention 22 avril 2011
21 avril 2010 à 19:39
Ok, merci pour les astuces et conseils de programmation. Tout d'abord au niveau du "write" avec lcd, non je dois faire comme j'ai fais avant car sinon il y a des problèmes d'affichages sur le LCD. Sinon à part ça je crois pas pouvoir changer string en wstring car en fait si tu veux le message est saisi bien un formulaire donc je sais pas. Enfin, je vais essayer d'utiliser <cstdlib> et voir ce que ça donne.
0
zaraki21 Messages postés 31 Date d'inscription lundi 2 juin 2008 Statut Membre Dernière intervention 22 avril 2011
22 avril 2010 à 18:06
En fait, je rencontre des problèmes pour l'utilisation de wstring ; en effet même en incluant <cstdlib>, le compilateur me met comme erreur "wstring in namespace std does not name a type" et je n'ai pas trouvé de solution à ce problème. J'ai aussi trouvé une fonction qui pourrait me permettre de faire ce que je veux c'est swprintf mais toujours pareil j'ai une erreur de compilation quand j'essaye de l'utiliser "swprintf was not declared in this scope" donc je suis un peu dans l'impasse. De plus, j'ai essayé sur un autre ordinateur d'utiliser ces deux éléments et cela fonctionne donc à mon avis il doit y avoir un problème au niveau du compilateur utilisé, je pense notamment à uclibc, tu en penses quoi ?
0
Rejoignez-nous