2010-11-05 4 views
5

Je dois allouer un tampon suffisant pour la fonction de formatage vswprintf(). En faisant la même chose avec la chaîne ANSI, j'utilise:Comment déterminer la taille du tampon pour vswprintf sous Linux gcc

vsnprintf(NULL, NULL, pszFormat, args); 

qui me renvoie la taille d'un tampon. Mais il semble que la version Unicode de cette fonction n'a pas cette fonctionnalité. Lorsque j'exécute:

vswprintf(NULL, NULL, pszFormat, args); 

La valeur du résultat est toujours -1.

Seule la solution que j'ai trouvée utilise un grand tampon statique pour le calcul de la taille requise. Mais je n'aime pas cette solution:

static const int nBuffSize = 1024; 
static XCHAR evalBuff[nBuffSize]; 
int nSize = vswprintf(evalBuff, nBuffSize, pszFormat, args); 
if (nSize != -1) 
{ 
return nSize; 
} 
else 
{ 
throw XXX; 
} 

Est-il possible comment mesurer la taille requise de la mémoire tampon pour les chaînes unicode?

Cordialement Ludek

Répondre

4

Ouverture d'un fichier fictif/dev/null (ou NUL sous Windows) et l'impression à ce fichier pour récupérer la taille fonctionne très bien (il est plus rapide que l'impression d'une chaîne):

#if defined (_MSC_VER)
    printf_dummy_file = fopen ("/ dev/null", "wb");
#else
    printf_dummy_file = fopen ("NUL", "wb");
#endif

...

n = vfprintf (printf_dummy_file, format, args); La partie "fopen" doit être effectuée une seule fois (vous pouvez utiliser une variable statique ou le constructeur d'une variable globale si vous utilisez C++).

+1

'vfwprintf' plutôt que' vfprintf', mais +1 de toute façon. Et n'oubliez pas d'utiliser une copie de la liste va_list. –

+0

Merci pour ce conseil. Seul inconvénient de cette solution est 5 fois plus lent que la fonction originale vswprintf.Donc, je vais utiliser cette fonction pour les systèmes * nix, mais la fonction d'origine pour le système Win. Merci –

1

Un poids lourd de peu, mais si personne ne vient avec quelque chose de mieux que vous pourrait exponentiellement croître un tampon jusqu'à ce qu'il soit assez grand:

std::vector<wchar_t> vec(512); 
int nSize; 
do { 
    vec.resize(vec.size()*2); 
    va_list args2; 
    va_copy args2, args; 
    nSize = vswprintf(&vec[0], vec.size(), format, args2); 
    va_end args2 
} while(nSize < 0); 
// now I have the length, and the formatted string to copy if required. 

Puisque vous êtes sur Posix, vous d pense qu'une erreur serait définie pour un espace tampon insuffisant, et que cet errno devrait être vérifié dans la condition while, de sorte que d'autres erreurs ne provoquent pas de boucle gourmande en ressources. Mais il n'y a pas d'errno défini à http://opengroup.org/onlinepubs/007908775/xsh/fwprintf.html, donc je suppose que vous devrez tester quelle erreur vous obtenez réellement sur votre implémentation (le cas échéant). Une autre option consiste à se débarrasser des chaînes de format et à écrire à . Mais ce n'est pas très utile si votre chaîne de format doit être configurée après la compilation.

+0

Merci pour ce conseil, mais cela prend beaucoup plus de temps que la solution proposée par John Rusta, alors je me décide pour son chemin. Merci –

-1

Cela obtenir la taille du tampon:

vswprintf (nullptr, -1, pszFormat, args);

+0

Cela ne fonctionne que sur Windows, sur Linux, il renvoie -1 – Programmdude

+0

@Programmdude: Il reviendra -1 pour vous tous, qui a eu un 'using namespace std;' quelque part dans votre code (ou 'en utilisant std :: vswprintf'). Pour tous les autres, il retournera la taille de tampon requise (ou une erreur de compilation). – IInspectable

+0

@IInspectable votre commentaire est faux, C++ délègue à la spécification C pour 'vswprintf' sans spécifier de changements de comportement; et la spécification C indique que 'vswprintf' rend le comportement indéfini pour passer un pointeur nul en tant que premier argument –

Questions connexes