Précédent   Forum du club des développeurs et IT Pro > C et C++ > C
C Forum d'entraide technique sur le langage C. Avant de poster -> F.A.Q. C, Avant de poster.
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse
 
Outils de la discussion
Publicité
'
Vieux 08/01/2013, 21h47   #1
nanosoft
Nouveau Membre du Club
 
Homme
Ingénieur développement matériel électronique
Inscription : juin 2012
Messages : 57
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 : 57
Points : 36
Points : 36
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.
nanosoft est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/01/2013, 11h28   #2
phi1981
Membre éclairé
 
Inscription : décembre 2010
Messages : 174
Détails du profil
Informations forums :
Inscription : décembre 2010
Messages : 174
Points : 358
Points : 358
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 ?
phi1981 est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 09/01/2013, 22h13   #3
nanosoft
Nouveau Membre du Club
 
Homme
Ingénieur développement matériel électronique
Inscription : juin 2012
Messages : 57
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 : 57
Points : 36
Points : 36
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.
nanosoft est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 10/01/2013, 08h45   #4
phi1981
Membre éclairé
 
Inscription : décembre 2010
Messages : 174
Détails du profil
Informations forums :
Inscription : décembre 2010
Messages : 174
Points : 358
Points : 358
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.
phi1981 est déconnecté   Envoyer un message privé Réponse avec citation 20
Vieux 10/01/2013, 09h02   #5
phi1981
Membre éclairé
 
Inscription : décembre 2010
Messages : 174
Détails du profil
Informations forums :
Inscription : décembre 2010
Messages : 174
Points : 358
Points : 358
Citation:
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.
phi1981 est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 10/01/2013, 22h14   #6
nanosoft
Nouveau Membre du Club
 
Homme
Ingénieur développement matériel électronique
Inscription : juin 2012
Messages : 57
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 : 57
Points : 36
Points : 36
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 :
?
nanosoft est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 11/01/2013, 08h18   #7
phi1981
Membre éclairé
 
Inscription : décembre 2010
Messages : 174
Détails du profil
Informations forums :
Inscription : décembre 2010
Messages : 174
Points : 358
Points : 358
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.
phi1981 est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 18/01/2013, 14h56   #8
Médinoc
Expert Confirmé Sénior
 
Avatar de Médinoc
 
Homme
Développeur informatique
Inscription : septembre 2005
Messages : 22 380
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 29
Localisation : France

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

Informations forums :
Inscription : septembre 2005
Messages : 22 380
Points : 32 015
Points : 32 015
Envoyer un message via MSN à Médinoc
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.
Médinoc est actuellement connecté   Envoyer un message privé Réponse avec citation 20
Vieux 03/02/2013, 21h53   #9
nanosoft
Nouveau Membre du Club
 
Homme
Ingénieur développement matériel électronique
Inscription : juin 2012
Messages : 57
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 : 57
Points : 36
Points : 36
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
nanosoft est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 04/02/2013, 06h26   #10
Médinoc
Expert Confirmé Sénior
 
Avatar de Médinoc
 
Homme
Développeur informatique
Inscription : septembre 2005
Messages : 22 380
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 29
Localisation : France

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

Informations forums :
Inscription : septembre 2005
Messages : 22 380
Points : 32 015
Points : 32 015
Envoyer un message via MSN à Médinoc
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.
Médinoc est actuellement connecté   Envoyer un message privé Réponse avec citation 01
Vieux 04/02/2013, 21h29   #11
nanosoft
Nouveau Membre du Club
 
Homme
Ingénieur développement matériel électronique
Inscription : juin 2012
Messages : 57
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 : 57
Points : 36
Points : 36
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 ?
nanosoft est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 05/02/2013, 11h10   #12
Médinoc
Expert Confirmé Sénior
 
Avatar de Médinoc
 
Homme
Développeur informatique
Inscription : septembre 2005
Messages : 22 380
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 29
Localisation : France

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

Informations forums :
Inscription : septembre 2005
Messages : 22 380
Points : 32 015
Points : 32 015
Envoyer un message via MSN à Médinoc
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.
Médinoc est actuellement connecté   Envoyer un message privé Réponse avec citation 10
Vieux 05/02/2013, 22h17   #13
nanosoft
Nouveau Membre du Club
 
Homme
Ingénieur développement matériel électronique
Inscription : juin 2012
Messages : 57
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 : 57
Points : 36
Points : 36
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
nanosoft est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 05/02/2013, 23h35   #14
Médinoc
Expert Confirmé Sénior
 
Avatar de Médinoc
 
Homme
Développeur informatique
Inscription : septembre 2005
Messages : 22 380
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 29
Localisation : France

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

Informations forums :
Inscription : septembre 2005
Messages : 22 380
Points : 32 015
Points : 32 015
Envoyer un message via MSN à Médinoc
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.
Médinoc est actuellement connecté   Envoyer un message privé Réponse avec citation 30
Vieux 06/02/2013, 21h45   #15
nanosoft
Nouveau Membre du Club
 
Homme
Ingénieur développement matériel électronique
Inscription : juin 2012
Messages : 57
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 : 57
Points : 36
Points : 36
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
nanosoft est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 06/02/2013, 22h41   #16
Médinoc
Expert Confirmé Sénior
 
Avatar de Médinoc
 
Homme
Développeur informatique
Inscription : septembre 2005
Messages : 22 380
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 29
Localisation : France

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

Informations forums :
Inscription : septembre 2005
Messages : 22 380
Points : 32 015
Points : 32 015
Envoyer un message via MSN à Médinoc
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.
Médinoc est actuellement connecté   Envoyer un message privé Réponse avec citation 10
Vieux 06/04/2013, 16h21   #17
nanosoft
Nouveau Membre du Club
 
Homme
Ingénieur développement matériel électronique
Inscription : juin 2012
Messages : 57
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 : 57
Points : 36
Points : 36
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
nanosoft est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 06/04/2013, 17h25   #18
Médinoc
Expert Confirmé Sénior
 
Avatar de Médinoc
 
Homme
Développeur informatique
Inscription : septembre 2005
Messages : 22 380
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 29
Localisation : France

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

Informations forums :
Inscription : septembre 2005
Messages : 22 380
Points : 32 015
Points : 32 015
Envoyer un message via MSN à Médinoc
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.
Médinoc est actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 06/04/2013, 18h02   #19
nanosoft
Nouveau Membre du Club
 
Homme
Ingénieur développement matériel électronique
Inscription : juin 2012
Messages : 57
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 : 57
Points : 36
Points : 36
OK, merci pour la correction avec tchar.h

Mais :
Citation:
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);
nanosoft est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 06/04/2013, 19h23   #20
Médinoc
Expert Confirmé Sénior
 
Avatar de Médinoc
 
Homme
Développeur informatique
Inscription : septembre 2005
Messages : 22 380
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 29
Localisation : France

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

Informations forums :
Inscription : septembre 2005
Messages : 22 380
Points : 32 015
Points : 32 015
Envoyer un message via MSN à Médinoc
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.

Citation:
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.
Médinoc est actuellement connecté   Envoyer un message privé Réponse avec citation 10
Réponse
Outils de la discussion

Navigation rapide


Fuseau horaire GMT +2. Il est actuellement 14h43.


 
 
 
 
Partenaires

Hébergement Web