Publicité
+ Répondre à la discussion
Page 1 sur 2 12 DernièreDernière
Affichage des résultats 1 à 20 sur 30
  1. #1
    Membre du Club
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    juin 2012
    Messages
    89
    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 : 89
    Points : 64
    Points
    64

    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 :
    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 expérimenté
    Inscrit en
    décembre 2010
    Messages
    250
    Détails du profil
    Informations forums :
    Inscription : décembre 2010
    Messages : 250
    Points : 549
    Points
    549

    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 du Club
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    juin 2012
    Messages
    89
    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 : 89
    Points : 64
    Points
    64

    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 expérimenté
    Inscrit en
    décembre 2010
    Messages
    250
    Détails du profil
    Informations forums :
    Inscription : décembre 2010
    Messages : 250
    Points : 549
    Points
    549

    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 expérimenté
    Inscrit en
    décembre 2010
    Messages
    250
    Détails du profil
    Informations forums :
    Inscription : décembre 2010
    Messages : 250
    Points : 549
    Points
    549

    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 :
    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 du Club
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    juin 2012
    Messages
    89
    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 : 89
    Points : 64
    Points
    64

    Par défaut

    OK,
    Si j'ai ce code :
    Code :
    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 expérimenté
    Inscrit en
    décembre 2010
    Messages
    250
    Détails du profil
    Informations forums :
    Inscription : décembre 2010
    Messages : 250
    Points : 549
    Points
    549

    Par défaut

    Citation Envoyé par nanosoft Voir le message
    OK,
    Si j'ai ce code :
    Code :
    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 Confirmé Sénior Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    septembre 2005
    Messages
    23 817
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France

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

    Informations forums :
    Inscription : septembre 2005
    Messages : 23 817
    Points : 31 660
    Points
    31 660

    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 :
    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 du Club
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    juin 2012
    Messages
    89
    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 : 89
    Points : 64
    Points
    64

    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 :
    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 Confirmé Sénior Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    septembre 2005
    Messages
    23 817
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France

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

    Informations forums :
    Inscription : septembre 2005
    Messages : 23 817
    Points : 31 660
    Points
    31 660

    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 du Club
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    juin 2012
    Messages
    89
    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 : 89
    Points : 64
    Points
    64

    Par défaut

    A la place des #ifdef, est-il possible de s'en sortir avec la taille ?
    Code :
    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 Confirmé Sénior Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    septembre 2005
    Messages
    23 817
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France

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

    Informations forums :
    Inscription : septembre 2005
    Messages : 23 817
    Points : 31 660
    Points
    31 660

    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 :
    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 :
    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 du Club
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    juin 2012
    Messages
    89
    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 : 89
    Points : 64
    Points
    64

    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 :
    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 Confirmé Sénior Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    septembre 2005
    Messages
    23 817
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France

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

    Informations forums :
    Inscription : septembre 2005
    Messages : 23 817
    Points : 31 660
    Points
    31 660

    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 CP435 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 du Club
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    juin 2012
    Messages
    89
    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 : 89
    Points : 64
    Points
    64

    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 :
    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 Confirmé Sénior Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    septembre 2005
    Messages
    23 817
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France

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

    Informations forums :
    Inscription : septembre 2005
    Messages : 23 817
    Points : 31 660
    Points
    31 660

    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 du Club
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    juin 2012
    Messages
    89
    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 : 89
    Points : 64
    Points
    64

    Par défaut

    Bonjour,

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

    Code :
    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 Confirmé Sénior Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    septembre 2005
    Messages
    23 817
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France

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

    Informations forums :
    Inscription : septembre 2005
    Messages : 23 817
    Points : 31 660
    Points
    31 660

    Par défaut

    Ce n'est pas un vrai LPCTSTR, c'est un char* (LPSTR) casté en LPCTSTR.
    Code C :
    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 du Club
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    juin 2012
    Messages
    89
    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 : 89
    Points : 64
    Points
    64

    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 :
    1
    2
    3
    4
    5
    // ...
    // ...
    message=int2str(2013);
    // ...
    free(message);

  20. #20
    Expert Confirmé Sénior Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    septembre 2005
    Messages
    23 817
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France

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

    Informations forums :
    Inscription : septembre 2005
    Messages : 23 817
    Points : 31 660
    Points
    31 660

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

Liens sociaux

Règles de messages

  • Vous ne pouvez pas créer de nouvelles discussions
  • Vous ne pouvez pas envoyer des réponses
  • Vous ne pouvez pas envoyer des pièces jointes
  • Vous ne pouvez pas modifier vos messages
  •