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 :

Mini-string en C (Windows)


Sujet :

C

  1. #1
    Membre averti
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Juin 2012
    Messages
    257
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2012
    Messages : 257
    Points : 321
    Points
    321
    Par défaut Mini-string en C (Windows)
    Bonjour,

    J'envisage de réaliser un ensemble de structures et de fonctions pour gérer les chaînes de caractères un peu dans l'idée des objets C++
    Je pense que cela pourrait me faire gagner au global sur le codage de certains projets. Je programme pour l'instant en C et exclusivement pour Windows (et je suis débutant).
    Les fonctions de l'API Windows ont un type LPCTSTR, l’investissement serait vraiment intéressant si je pouvais créer des fonctions qui retournent ce type, par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    LPCTSTR message=myStrcat(str1,str2);
    C'est faisable ou juste impossible ?

    Merci pour votre réponse et des idées ou des liens sur ce sujet.

  2. #2
    Membre éclairé
    Inscrit en
    Décembre 2010
    Messages
    290
    Détails du profil
    Informations forums :
    Inscription : Décembre 2010
    Messages : 290
    Points : 719
    Points
    719
    Par défaut
    Sous l'api Windows, LPCTSTR désigne un "pointeur vers une chaine de caractères constante où chaque caractère est de type TCHAR".
    En effet, rien ne t'empêche de définir une fonction myStrCat () qui alloue un buffer de TCHARs, y stocke la concaténation des deux chaines passées en paramètre, et retourne un pointeur vers ce buffer. Il faudra juste préciser dans la documentation de myStrCat() que l'appelant ne doit pas oublier de libérer le buffer en question en appelant une fonction désignée.
    Qu'est-ce qui te bloque ?

  3. #3
    Membre averti
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Juin 2012
    Messages
    257
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2012
    Messages : 257
    Points : 321
    Points
    321
    Par défaut
    Merci de me répondre, il n'y a rien qui me bloque vraiment :
    J'essaie d'en apprendre le plus possible avant de me lancer dans des dev. plus conséquents.
    Comme LPCTSTR désigne un pointeur vers une chaine de caractères constante, je craignais que l'on ne puisse pas faire une affectation comme pour une variable.
    Est_ce que :
    a un sens ?
    C'est la taille du pointeur ou de la chaîne ?
    Les allocations sont certainement le cœur du sujet et je suis encore peu expérimenté avec les allocations dynamiques.

  4. #4
    Membre éclairé
    Inscrit en
    Décembre 2010
    Messages
    290
    Détails du profil
    Informations forums :
    Inscription : Décembre 2010
    Messages : 290
    Points : 719
    Points
    719
    Par défaut
    Citation Envoyé par nanosoft Voir le message
    Comme LPCTSTR désigne un pointeur vers une chaine de caractères constante, je craignais que l'on ne puisse pas faire une affectation comme pour une variable.
    En fait, ce typedef est défini dans l'api windows un peu comme ça :
    typedef const TCHAR* LPCTSTR;
    Quand un qualifier "const" apparait AVANT l'étoile (*), cela signifie que les données POINTEES sont constantes, pas le pointeur lui même.
    On a le droit de modifier le pointeur (le faire pointer vers autre chose), mais on a pas le droit de modifier la chaîne pointée par ce pointeur.

    Tu as le droit d'allouer un buffer, y copier des données, et retourner un pointeur CONST vers ce buffer : cela signifie à l'appelant "je te donne accès en lecture seule à une chaîne de caractères".

    Citation Envoyé par nanosoft Voir le message
    Est_ce que :
    a un sens ?
    C'est la taille du pointeur ou de la chaîne ?
    C'est la taille du pointeur (4 sous Windows 32 bits).
    Pour obtenir la taille de la chaine, il faut la parcourir jusqu'à obtenir un 0, c'est le principe des chaînes en C.

  5. #5
    Membre éclairé
    Inscrit en
    Décembre 2010
    Messages
    290
    Détails du profil
    Informations forums :
    Inscription : Décembre 2010
    Messages : 290
    Points : 719
    Points
    719
    Par défaut
    Les fonctions de l'API Windows ont un type LPCTSTR ...
    Je viens juste de relire ton message original, et je pense qu'il y a une petite confusion :
    Une fonction Win32 dans ce genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    BOOL WINAPI CopyFile(LPCTSTR lpExistingFileName, LPCTSTR lpNewFileName, BOOL bFailIfExists);
    prend deux paramètres de type "pointeur vers une chaînes de caractères constante". Mais cela signifie surtout "Moi, fonction CopyFile(), je te promets juré craché que je ne vais pas modifier les chaînes de caractères que tu me passes en paramètre, je vais juste les lire pour savoir quel fichier je dois copier".
    Cela ne veut pas dire que toi, appelant de cette fonction, tu doives manipuler des pointeurs vers des constantes. Tu PEUX le faire, mais tu n'y es pas obligé. Tu peux très bien lui passer un pointeur vers une chaine modifiable, c'est juste que le prototype de CopyFile() te promets qu'il ne va pas la modifier.

  6. #6
    Membre averti
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Juin 2012
    Messages
    257
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2012
    Messages : 257
    Points : 321
    Points
    321
    Par défaut
    OK,
    Si j'ai ce code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    LPCTSTR message1;
    // ...
    message1="OK";
    c'est le compilateur qui alloue la taille ?
    est-ce que ensuite dans le programme, je peux avoir une fonction :
    ?

  7. #7
    Membre éclairé
    Inscrit en
    Décembre 2010
    Messages
    290
    Détails du profil
    Informations forums :
    Inscription : Décembre 2010
    Messages : 290
    Points : 719
    Points
    719
    Par défaut
    Citation Envoyé par nanosoft Voir le message
    OK,
    Si j'ai ce code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    LPCTSTR message1;
    // ...
    message1="OK";
    c'est le compilateur qui alloue la taille ?
    Oui, enfin précisément les trois caractères qui composent le "OK" (y a aussi un 0 à la fin) sont stockés dans la partie data de l'executable, donc on parle pas vraiment d'allocation (je simplifie un peu, mais l'idée est là).

    Citation Envoyé par nanosoft Voir le message
    est-ce que ensuite dans le programme, je peux avoir une fonction :
    ?
    Oui bien sûr, tu fais alors pointer ton pointeur vers une autre chaîne de caractères.

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Bonjour,
    Pour travailler facilement avec des TCHAR (ou _TCHAR), tu dois utiliser les fonctions de <tchar.h> (ou d'autres fonctions données par Windows).

    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
    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <string.h>
    #include <tchar.h>
     
     
    int _tmain(int argc, _TCHAR const * argv[])
    {
    	LPCTSTR message1 = _T("ok");
    	_TCHAR buf[10] = _T("Test ");
     
    	_tcscat(buf, message1);
    	_tprintf(_T("Résultat: %s\n"), buf);
    	return 0;
    }
    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.

  9. #9
    Membre averti
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Juin 2012
    Messages
    257
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2012
    Messages : 257
    Points : 321
    Points
    321
    Par défaut
    Merci pour ces infos Medinoc,

    Quel est le type ou la structure correspondant à TCHAR ?

    Avec le petit exemple ci-dessous je sais passer d'une chaine vers LPCTSTR.
    Mais je n'ai pas encore réussi pour passer de LPCTSTR vers une chaîne, c'est forcement plus compliqué puisqu'il faut gérer la longueur de la chaîne.
    Je suis preneur d'un petit exemple sur le principe.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    LPCTSTR saisie="OK";
    char chaine[]=" Salut ";
     
    _tprintf(_T("saisie : %s \n "),saisie); // => OK
     
    saisie = chaine;
     
    _tprintf(_T("saisie : %s \n "),saisie); // => Salut

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    TCHAR
    Les conversions sont une plaie, surtout en C. Tu te retrouves à bosser avec des #ifdef partout, ou autres joyeusetés...

    En C++ on gagne un peu de répit avec des classes dédiées à la conversion et des surcharges de 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.

  11. #11
    Membre averti
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Juin 2012
    Messages
    257
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2012
    Messages : 257
    Points : 321
    Points
    321
    Par défaut
    A la place des #ifdef, est-il possible de s'en sortir avec la taille ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    int taille=sizeof(TCHAR);
    printf("taille = %i \n",taille); // => 1
    Si taille = 1, cela veut-il dire que TCHAR est un char ?

    Si taille = 2 ou 4 ou autre ?
    Comment faire ? y a t-il des "endians" à considérer ?

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    J'ignore si l'endianness change d'une version de Windows à une autre (quelle est l'endianness d'un ARM?), mais sous x86, c'est du little-endian; aussi, sous Windows un wchar_t fait deux octets.

    Pas contre, je ne dois pas l'intérêt de bosser avec des if plutôt que des #ifdef et des macros.

    Dans tous les cas, on peut au minimum faire des fonctions de conversion:
    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
    /*TestConvertStr.h*/
    #pragma once
    #include <wchar.h>
     
    wchar_t * AllocA2W(char const *sczA);
    char * AllocW2A(wchar_t const *sczW);
    char * AllocA2A(char const *sczA);
    wchar_t * AllocW2W(wchar_t const *sczW);
    void FreeA(char *szA);
    void FreeW(wchar_t *szW);
     
    char * AbortIfNullA(char *szA);
    wchar_t * AbortIfNullW(wchar_t *szW);
     
    #ifdef _UNICODE
    	#define AllocA2T AllocA2W
    	#define AllocW2T AllocW2W
    	#define AllocT2T AllocW2W
    	#define AllocT2A AllocW2A
    	#define AllocT2W AllocW2W
    	#define FreeT FreeW
    	#define AbortIfNullT AbortIfNullW
    #else
    	#define AllocA2T AllocA2A
    	#define AllocW2T AllocW2A
    	#define AllocT2T AllocA2A
    	#define AllocT2A AllocA2A
    	#define AllocT2W AllocA2W
    	#define FreeT FreeA
    	#define AbortIfNullT AbortIfNullA
    #endif
    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
    /*TestConvertStr.c*/
    #define _CRT_SECURE_NO_WARNINGS
    #include <stdlib.h>
    #include <string.h>
    #include <wchar.h>
    #include <stdio.h>
     
    #include "TestConvertStr.h"
     
    wchar_t * AllocA2W(char const *sczA)
    {
    	size_t const cchLenA = strlen(sczA);
    	size_t const cchLenW = mbstowcs(NULL, sczA, cchLenA+1);
    	wchar_t * szW = calloc(cchLenW+1, sizeof *szW);
    	if(szW!=NULL)
    		mbstowcs(szW, sczA, cchLenA+1);
    	return szW;
    }
    char * AllocW2A(wchar_t const *sczW)
    {
    	size_t const cchLenW = wcslen(sczW);
    	size_t const cchLenA = wcstombs(NULL, sczW, cchLenW+1);
    	char * szA = calloc(cchLenA+1, sizeof *szA);
    	if(szA!=NULL)
    		wcstombs(szA, sczW, cchLenW+1);
    	return szA;
    }
     
    char * AllocA2A(char const *sczA)
    {
    	size_t const cchLenA = strlen(sczA);
    	char * szA = calloc(cchLenA+1, sizeof *szA);
    	if(szA!=NULL)
    		strcpy(szA, sczA);
    	return szA;
    }
    wchar_t * AllocW2W(wchar_t const *sczW)
    {
    	size_t const cchLenW = wcslen(sczW);
    	wchar_t * szW = calloc(cchLenW+1, sizeof *szW);
    	if(szW!=NULL)
    		wcscpy(szW, sczW);
    	return szW;
    }
     
    void FreeA(char *szA)
    {
    	free(szA);
    }
    void FreeW(wchar_t *szW)
    {
    	free(szW);
    }
     
    char * AbortIfNullA(char *szA)
    {
    	if(szA==NULL)
    	{
    		fputs("Echec d'allocation en conversion de chaine!\n", stderr);
    		abort();
    	}
    	return szA;
    }
    wchar_t * AbortIfNullW(wchar_t *szW)
    {
    	if(szW==NULL)
    	{
    		fputs("Echec d'allocation en conversion de chaine!\n", stderr);
    		abort();
    	}
    	return szW;
    }
    Ainsi, tu peux utiliser directement AllocT2A(s) ou AbortIfNullA(AllocT2A(s))...
    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.

  13. #13
    Membre averti
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Juin 2012
    Messages
    257
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2012
    Messages : 257
    Points : 321
    Points
    321
    Par défaut
    Merci pour ces fonctions de conversion.
    D'après ton message je comprend qu'elles sont pour Windows sous X86 ?

    Plus je me documente sur ce sujet et plus je me pose des questions, je vais résumer mes acquis :

    - LPCTSTR est un pointeur sur un tableau de TCHAR
    - un TCHAR est soit un char soit un wchar_t

    Je cherche à faire des conversions entre TCHAR et char donc dans un cas (qui semble être celui de ma configuration actuelle) il n'y a rien à faire.
    Je devrais pouvoir écrire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    LPCTSTR saisie="OK";
    char *chaine="KO";
    // et
    saisie = chaine;
    // ou
    chaine = saisie;
    Or, avec la ligne 6 j'ai un warning ?

    Je pensais que wchar_t était nécessaire pour les accents et je viens de m'apercevoir que je peux mettre des accents dans une chaine de char ?
    Un char est-il toujours un octet ?

    Éventuellement aussi :
    - qu'est ce que : #pragma once ?
    - #define _CRT_SECURE_NO_WARNINGS ?
    - qu'est ce qui conditionne _UNICODE ?

    En tout cas merci d'avance pour ce petit cours en ligne

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Bonjour,
    alors, tes réponses en vrac:

    • C'est pour Windows, indépendamment de l'architecture, normalement.
    • LPCTSTR, c'est un pointeur const de tableau de TCHAR (la version non-const, c'est LPTSTR).
    • Attention, une chaine littérale de TCHAR doit être entourée d'une des macros suivantes: _TEXT(), _T (définies dans <tchar.h>, dépendant de _UNICODE) ou TEXT() (définie in incluant <windows.h>, dépendant de UNICODE).
    • Si les macros UNICODE et _UNICODE ne sont pas définies (il faut définir soit les deux, soit aucune, sinon bonjour le bordel), TCHAR = char et c'est parfaitement interchangeable. Mais limité aux caractères de la page de codes courante (en France, les caractères latins avec la plupart des accents).
    • Ton warning en ligne 6 est à cause de const vs. non-const.
    • wchar_t c'est pour Unicode UCS-2 (anciennes versions de Windows), UTF-16 (Windows) et UCS-4/UTF-32 (*n*x). Mais char n'est le plus souvent pas limité à l'ASCII pur (ou à EBCDIC), il s'agit généralement d'un ASCII étendu:
      • Sous *n*x dans le monde "occidental", c'est généralement l'encodage ISO 8859-1 (Latin-1) ou ISO 8859-15 (Latin-9), quand ce n'est pas carrément de l'UTF-8
      • Sous Windows, ça dépend du type de programme: pour les applications fenêtrées c'est généralement la page de codes 1252 (alias "Windows-1252"); pour les applications console (et DOS) c'est CP437 aux USA, CP850 (alias "IBM-850") en France.

      Dans tous les cas, tu ne pourras pas saisir de caractères cyrilliques, arabes, japonais etc. dans un programme non-Unicode sans changer ta config de Windows.
    • Un char, c'est toujours au moins 8 bits en C (mais ça peut être plus sur certaines plate-formes) et sizeof(char) est toujours égal à 1. C'est tout ce qui est garanti en C, mais quand on bosse en C sous Windows on considère que c'est toujours exactement 8 bits.
    • #pragma once est un pragma reconnu par la plupart des compilos, qui remplace les #ifndef/#define/#endif pour empêcher qu'un header soit inclus plusieurs fois.
    • Ce #define sert à dire au compilo de Visual Studio de ne pas m'emmerder à se plaindre que les fonctions standard de <string.h> sont "unsafe". Pour le code de ces fonctions, la portabilité (notamment avec l'autre compilo, MinGW) est plus importante à mes yeux.
    • Sous un Visual Studio récent, il y a une option du projet qui définit automatiquement UNICODE et _UNICODE si on l'active; sinon, on les rajoute généralement en ligne de commande de compilation (pour MinGW: -DUNICODE -D_UNICODE)
    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.

  15. #15
    Membre averti
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Juin 2012
    Messages
    257
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2012
    Messages : 257
    Points : 321
    Points
    321
    Par défaut
    Super

    Encore 2 questions (pour l'instant !):

    - Est ce que le code ci-dessous est correct, en particulier maFonction (ou est-ce que l'on retourne ici un pointeur sur une variable locale) ?

    - Qu'est ce qui fait concrètement sous Windows qu'un TCHAR pourrait être différent d'un char, est-ce uniquement lié à ma configuration de compilation (ou faut-il craindre des problèmes de portabilité) ?

    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
    LPCTSTR saisie=TEXT("OK");
    const char *chaine="Chaîne hé hé !";
    printf("chaine : %s \n",chaine);          // => Chaîne hé hé !
    int i=0;
    while (chaine[i])
    {
        printf("car. : %c \n",chaine[i]);i++;
    }
    int taille=sizeof(chaine[3]);
    printf("taille char = %i \n",taille);   // => 1
     
    _tprintf(_T("saisie : %s \n "),saisie); // => OK
     
    saisie = chaine;
     
    _tprintf(_T("saisie : %s \n "),saisie); // => Chaîne hé hé !
     
    saisie=TEXT("OK");
    chaine = saisie;
    printf("chaine %s \n",chaine);          // => OK
     
    taille=sizeof(TCHAR);
    printf("taille TCHAR = %i \n",taille);  // => 1
     
    LPCTSTR maFonction()
    {
        LPCTSTR local=TEXT("retour");
        return local;
    }
    chaine=maFonction();
    printf("chaine %s \n",chaine);          // => retour

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Les lignes 14, 19 et 30, et tout ce qui en dépend, ne marcheront que si UNICODE et _UNICODE ne sont pas définis.
    Par contre, maFonction est OK, parce que "retour" (ou L"retour" si UNICODE est défini) est une chaîne littérale.

    Addition: Si tu utilises des printf() (et surtout des _tprintf()), ces informations peuvent être utiles: Size and Distance Specification
    Ce qu'il faut retenir:
    • _tprintf(_T("%s"), str); affichera systématiquement des TCHARs.
    • Le format %hs marche avec les trois versions pour afficher systématiquement des char.
    • Le format %ws marche avec les trois versions pour afficher systématiquement des wchar_t.
    • Il n'existe pas de format qui affiche systématiquement des TCHAR sur les trois versions; pour afficher des TCHAR, tu dois absolument utiliser _tprintf().
    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.

  17. #17
    Membre averti
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Juin 2012
    Messages
    257
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2012
    Messages : 257
    Points : 321
    Points
    321
    Par défaut
    Bonjour,

    J'ai réalisé des fonctions qui me retournent un LPCTSTR, voici un exemple :

    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
     
    LPCTSTR int2str(int nb)             // conversion int positif vers une chaîne
    {
        //printf("%i \n",nb);           // nb entier à convertir
        char *temp = NULL;
        int dec = 1,car = 1;            // nombres de digits
     
        if (nb>9)                       // nombre de chiffres ?
        {
            int nbd = nb;
            while((nbd/10)>=1)
            {
                dec++;
                nbd=nbd/10;
            }
        }
     
        temp = malloc((1+dec)*sizeof(char));
        car = sprintf(temp,"%d",nb);
        //printf("car : %i \n",car);    // nombre de caractères
        //printf("%i \n",dec);          // nombre de chiffres
        LPCTSTR chiffre = temp;
        //free(temp);
        return chiffre;                 // chaîne du nombre
    }
    En première approche je voulais libérer temp avec la ligne 23, mais évidement il ne faut pas puisque il ne s'agit que d'une même et unique adresse.

    Bref, d'après mes tests cela semble OK et je voudrais savoir si cette fonction est 100% sure : pas de souci de portabilité (autre machine 32/64 , version de Windows ...).

    Merci pour votre avis et vos conseils

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Ce n'est pas un vrai LPCTSTR, c'est un char* (LPSTR) casté en LPCTSTR.
    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
    #include <windows.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <tchar.h>
     
    LPTSTR int2str(int nb)             // conversion int positif vers une chaîne
    {
        //printf("%i \n",nb);           // nb entier à convertir
        int dec = _sctprintf(_T("%d"), nb);            // nombres de digits
        TCHAR *buf = malloc((1+dec)*sizeof(TCHAR));
        int car = _stprintf(temp, _T("%d"), nb);
        //printf("car : %i \n",car);    // nombre de caractères
        //printf("%i \n",dec);          // nombre de chiffres
        return buf;                 // chaîne du nombre
    }
    Et ne pas oublier le free() après usage.
    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
    Membre averti
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Juin 2012
    Messages
    257
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2012
    Messages : 257
    Points : 321
    Points
    321
    Par défaut
    OK, merci pour la correction avec tchar.h

    Mais :
    Ce n'est pas un vrai LPCTSTR, c'est un char* (LPSTR) casté en LPCTSTR.
    Quel est l'inconvénient ou le risque ?
    si je caste quand même avec LPCTSTR int2str(int nb)
    (c'est le type attendu des fonctions API Windows que je veux utiliser)

    et pour libérer , c'est comme cela ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    // ...
    // ...
    message=int2str(2013);
    // ...
    free(message);

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Citation Envoyé par nanosoft Voir le message
    Quel est l'inconvénient ou le risque ?
    si je caste quand même avec LPCTSTR int2str(int nb)
    (c'est le type attendu des fonctions API Windows que je veux utiliser)
    Très simple: D'une part dès que tu compileras en Unicode ça foirera, d'autre part tu ne pourras pas faire le free() sur le pointeur retourné sans faire un autre cast d'abord.

    et pour libérer , c'est comme cela ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    // ...
    // ...
    message=int2str(2013);
    // ...
    free(message);
    Oui, parfaitement.
    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.

Discussions similaires

  1. problème fin de string sous windows 98
    Par LAPLACE dans le forum Windows
    Réponses: 1
    Dernier message: 07/03/2006, 11h09
  2. Réponses: 4
    Dernier message: 30/01/2006, 19h50

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