Meilleur auteur de réponses
Visual C++ Problème avec la fonction strrchr en mode unicode

Question
-
Bonjour,
Projet : Visual Studio 2017 Community
Mode débogage : Release / win 32
Jeu de caractères : UNICODE
Fonction utilisée : strrchr
Problème : Cette fonction ne retourne pas la position d'un caractère.Ci-joint mon code avec les explications en commentaire :
//But c'est de récupérer le chemin "c:\Projets" à partir //de l'arborescence suivante "c:\Projets\ArchiveDoc.exe" //-- //on récupère le dossier par défaut de l'application char lpFilename[_MAX_PATH]; DWORD len = _MAX_PATH; lpFilename[0] = 0; GetModuleFileName(NULL, (LPWSTR)lpFilename, len); //lpFilename contient "c:\Projets\ArchiveDoc.exe" if (strlen(lpFilename) != 0) { int ch = 92; //la caractère '\' char *pdest; pdest = strrchr(lpFilename, ch); //recherche de la première occurrence de '\' en partant de la fin int Pos = (int)(pdest - lpFilename + 1); CString sfilname; sfilname.Empty(); sfilname.Format(L"Le numero est %d ", Pos); AfxMessageBox(sfilname); // !!!PROBLEME !!! // Pos retourne -18756256 au lieu de Pos=11 sfilname.Empty(); sfilname += lpFilename; CString FilePath = sfilname.Left(Pos - 1); // Conséquence de Pos <0, FilePath est vide au lieu d'être "C:\projets" CString FileName = sfilname.Right(sfilname.GetLength() - Pos); m_cRootFolder = FilePath; sFileParametre = FilePath; sFileParametre += "\\"; sFileParametre += "Arcodop.xml"; AfxMessageBox(sFileParametre); // résultat sFileParametre ="\Arcodop.xml" au lieu d'être "c\projets\Arcodop.xml" }
Question : le problème est-il lié à l'utilisation du jeu de caractère Unicode?
Si Oui, devrais-je revenir au jeu de caractère multioctet MBCS ?
Merci d'avance pour toute aide- Modifié cheickna1966 dimanche 4 mars 2018 11:55 correction
Réponses
-
Tu mélanges Ansi et Unicode
En Unicode, on n'utilise pas de char mais WCHAR et on utilise les fonctions Unicode (strrchr=>wcsrchr)Une des méthodes pour splitter un path :
WCHAR sModule[MAX_PATH]; WCHAR sDrive[MAX_PATH], sDir[MAX_PATH]= L""; GetModuleFileName(NULL, sModule, MAX_PATH); _wsplitpath(sModule, sDrive, sDir, NULL, NULL);
- Modifié Castorix31 dimanche 4 mars 2018 17:06
- Marqué comme réponse Nina ZaekovaMicrosoft contingent staff, Moderator lundi 16 avril 2018 12:04
-
Mais MS recommande d'utiliser plutôt Unicode dans ses docs comme :
où il y a notamment :
"New applications should always call the Unicode versions. Many world languages require Unicode. If you use ANSI strings, it will be impossible to localize your application. The ANSI versions are also less efficient, because the operating system must convert the ANSI strings to Unicode at run time."
- Marqué comme réponse Nina ZaekovaMicrosoft contingent staff, Moderator lundi 16 avril 2018 12:04
-
@cheickna1966, @Castorix31, il faut être rigoureux.
Soit c'est tout ANSI
Soit c'est tout UNICODE
Soit c'est tout TCHAR.
"GetModuleFileName", c'est du TCHAR.
C'est "GetModuleFileNameA" pour de l'ANSI
C'est "GetModuleFileNameW" pour de l'UNICODE.
Paul Bacelar, Ex - MVP VC++
- Marqué comme réponse Nina ZaekovaMicrosoft contingent staff, Moderator lundi 16 avril 2018 12:05
Toutes les réponses
-
Tu mélanges Ansi et Unicode
En Unicode, on n'utilise pas de char mais WCHAR et on utilise les fonctions Unicode (strrchr=>wcsrchr)Une des méthodes pour splitter un path :
WCHAR sModule[MAX_PATH]; WCHAR sDrive[MAX_PATH], sDir[MAX_PATH]= L""; GetModuleFileName(NULL, sModule, MAX_PATH); _wsplitpath(sModule, sDrive, sDir, NULL, NULL);
- Modifié Castorix31 dimanche 4 mars 2018 17:06
- Marqué comme réponse Nina ZaekovaMicrosoft contingent staff, Moderator lundi 16 avril 2018 12:04
-
Merci Castorix31,
je me doutais qu'il s'agissait d'un problème de ce genre. J'ai voulu pour une fois me lancer dans un codage 100% Unicode mais je crois que j'ai utilisé 80% des fonctions AINSI.
En mode Debug tout fonctionnait pourtant mais dès que j'ai basculé en release pour générer la version finale de mon appli, j'ai eu 355 erreurs et il a fallu que je mette des L"" partout, caster les variables en LPCTSTR, etc....Une demi journée de travail. Maintenant je comprends mieux et je pense que je vais retourner à mon bon vieux ainsi.
Encore merci
-
Mais MS recommande d'utiliser plutôt Unicode dans ses docs comme :
où il y a notamment :
"New applications should always call the Unicode versions. Many world languages require Unicode. If you use ANSI strings, it will be impossible to localize your application. The ANSI versions are also less efficient, because the operating system must convert the ANSI strings to Unicode at run time."
- Marqué comme réponse Nina ZaekovaMicrosoft contingent staff, Moderator lundi 16 avril 2018 12:04
-
@cheickna1966, @Castorix31, il faut être rigoureux.
Soit c'est tout ANSI
Soit c'est tout UNICODE
Soit c'est tout TCHAR.
"GetModuleFileName", c'est du TCHAR.
C'est "GetModuleFileNameA" pour de l'ANSI
C'est "GetModuleFileNameW" pour de l'UNICODE.
Paul Bacelar, Ex - MVP VC++
- Marqué comme réponse Nina ZaekovaMicrosoft contingent staff, Moderator lundi 16 avril 2018 12:05
-
Bonjour @Castorix31 & @Paul Bacelar,
Merci beaucoup pour vos remarques.
Avec vos remarques et les préconisations de MS mentionnées ci-dessus pas Castorix31 je vais me résoudre à tenter de faire du tout UNICODE pour être cohérent. Il faudrait donc que je revois toutes les fonctions de traitrement de string car j'ai du char*, TCHAR, WCHAR, LPCTSTR, LPSTR et même du CString partout....
Du boulot en perspective donc heureusement qu'il s'agit d'un projet personnel...
-
-
Bonsoir Paul Bacelar,
C'est ce que j'ai tenté d'expliquer au départ. Après plus de 10 ans en développement en France on a toujours codé dans ma société en Ansi avec une utilisation à outrance des MFC d'où le CString.
Cela fait maintenant plus de 12 ans que je ne code plus et lorsqu'on s'y remet qui plus est vouloir faire de l'Unicode, on est forcement tenté d'utiliser ce qu'on connaît mieux. Je trouve qu'avec le CString la manipulation des chaines (concatenation, position d'un caractère dans la chaine, extraction d'une partie, etc) est beaucoup plus simple. C'est donc la raison pour laquelle j'ai mélangé ansi et Unicode, tchar, etc.
-
>Après plus de 10 ans en développement en France on a toujours codé dans ma société en Ansi
Étrange, en France on est plutôt "aware" des problèmes de l'usage de l'ASCII grâce à nos chers accents qui passent mal sur pas mal de programme US.
>avec une utilisation à outrance des MFC d'où le CString.
Il faut pas tomber dans ce vieil excès où on utilisait des MFC dans des applications console pour avoir la classe CString.
On n'est plus dans les années 80, début 90 où la STL du C++ n'existait pas.
std::string est bien plus portable ET bien plus puissante maintenant que la classe CString, qui n'est plus qu'une spécialisation de la std::string qui ne fait qu'assurer la rétrocompatibilité.
Utiliser CString dans des classes MFC d'IHM si cela vous permet d'utiliser les Designer Graphique mais dès que vous n'êtes plus dans un module nécessitant les MFC (donc hors des formulaires) vous devriez vous en débarrasser.
>on est forcement tenté d'utiliser ce qu'on connaît mieux.
Progresser ou périr.
>Je trouve qu'avec le CString la manipulation des chaines (concatenation, position d'un caractère dans la chaine, extraction d'une partie, etc) est beaucoup plus simple.
Vous n'avez pas vraiment regarder la documentation de std::string, je pense.
>C'est donc la raison pour laquelle j'ai mélangé ansi et Unicode, tchar, etc.
Évitez les mélanges autant que possible, et s'il y a mélange, soyez très rigoureux.
Pour validez votre rigueur, compilez systématiquement en UNICODE ET en ASCII (les usines de build sont nos amies).
Si vous vous amusez pas à caster comme un bourrin, le compilateur vous aidera à détecter les erreurs de mélange.
Paul Bacelar, Ex - MVP VC++
-
Bonjour,
Je reconnais qu'il n' ya que du vrai dans ce que vous dites et pour cause c'est l'expérience qui fait la différence. Quand j'ai quitté le monde VB pour VC++ au debaut des années 2000 vous étiez MVP et vous avez résolu des dizaines de problèmes auxquels j'ai été confrontés. J'ai quitté le monde développeur et près de 15 ans après vous donnez les mêmes conseils avisés en temps que Ex MVP.
Il ya quelque chose de très vrai dans ce que vous avez écrit ci-dessus : "Vous n'avez pas vraiment regarder la documentation de std::string" c'est exact. Donc entre progresser et périr, je vais choisir progresser et me plonger dans la doc du std::string.. Ce sera d'ailleurs un bon challenge pour moi de faire un programme complet sans CString.
Encore merci et à bientôt pour d'autres échanges.