none
Visual C++ Problème avec la fonction strrchr en mode unicode RRS feed

  • 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
    dimanche 4 mars 2018 11:55

Réponses

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);

    dimanche 4 mars 2018 17:02
  • 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

    dimanche 4 mars 2018 19:35
  • Mais MS recommande d'utiliser plutôt Unicode dans ses docs comme :

    Working with Strings

    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."

    dimanche 4 mars 2018 23:19
  • @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++

    lundi 5 mars 2018 16:17
    Modérateur
  • 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...

    lundi 5 mars 2018 17:08
  • Pourquoi des CString à la place des std::string du standard ?

    Paul Bacelar, Ex - MVP VC++

    lundi 5 mars 2018 17:11
    Modérateur
  • 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.

    lundi 5 mars 2018 23:55
  • >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++

    mardi 6 mars 2018 13:40
    Modérateur
  • 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.

    mardi 6 mars 2018 14:42