"Eric Bart" wrote in message news:bp08o3$oqt$ | //-------------------------------------------------------------------------- - | string BKsys::StrPrintf(const char *chFormat, ...) | { | va_list args; | va_start(args, chFormat); | | // calcul de la taille du buffer | char * buff; | int iBufSize = vsnprintf(buff, 0, chFormat, args); | | buff = new char[iBufSize +2]; | vsnprintf(buff, iBufSize +1, chFormat, args); | | va_end(args); | string sS = buff; | delete [] buff; | return sS; | } ... | Ca vous plait ?
Très bien, à quelques détails près: - buff n'est pas initialise avant le 1er appel a vsnprintf. Bcp de compils en feront un 'warning'. - je serais tente d'utiliser un buffer local lors du premier appel, pour eviter l'alloc et le second appel lorsque c'est possible. - si le constructeur de sS lance une exception (eh oui, c'est possible) il y aura un memory leak. - si new[] ou le ctr lancent une exception, va_end ne sera pas appelé (pas bien)
Alternative: utiliser std::vector<char> plutot que new[]. Mais try-catch resterait necessaire pour appeler va_end(args), sauf tech speciales...
Amicalement, Ivan -- http://ivan.vecerina.com
"Eric Bart" <eric.bart@wanadoo-tralala.fr> wrote in message
news:bp08o3$oqt$1@news-reader5.wanadoo.fr...
|
//--------------------------------------------------------------------------
-
| string BKsys::StrPrintf(const char *chFormat, ...)
| {
| va_list args;
| va_start(args, chFormat);
|
| // calcul de la taille du buffer
| char * buff;
| int iBufSize = vsnprintf(buff, 0, chFormat, args);
|
| buff = new char[iBufSize +2];
| vsnprintf(buff, iBufSize +1, chFormat, args);
|
| va_end(args);
| string sS = buff;
| delete [] buff;
| return sS;
| }
...
| Ca vous plait ?
Très bien, à quelques détails près:
- buff n'est pas initialise avant le 1er appel a vsnprintf.
Bcp de compils en feront un 'warning'.
- je serais tente d'utiliser un buffer local lors du
premier appel, pour eviter l'alloc et le second
appel lorsque c'est possible.
- si le constructeur de sS lance une exception (eh oui,
c'est possible) il y aura un memory leak.
- si new[] ou le ctr lancent une exception, va_end
ne sera pas appelé (pas bien)
"Eric Bart" wrote in message news:bp08o3$oqt$ | //-------------------------------------------------------------------------- - | string BKsys::StrPrintf(const char *chFormat, ...) | { | va_list args; | va_start(args, chFormat); | | // calcul de la taille du buffer | char * buff; | int iBufSize = vsnprintf(buff, 0, chFormat, args); | | buff = new char[iBufSize +2]; | vsnprintf(buff, iBufSize +1, chFormat, args); | | va_end(args); | string sS = buff; | delete [] buff; | return sS; | } ... | Ca vous plait ?
Très bien, à quelques détails près: - buff n'est pas initialise avant le 1er appel a vsnprintf. Bcp de compils en feront un 'warning'. - je serais tente d'utiliser un buffer local lors du premier appel, pour eviter l'alloc et le second appel lorsque c'est possible. - si le constructeur de sS lance une exception (eh oui, c'est possible) il y aura un memory leak. - si new[] ou le ctr lancent une exception, va_end ne sera pas appelé (pas bien)
Alternative: utiliser std::vector<char> plutot que new[].
Ce n'est AMHA pas une "alternative", mais la solution canonique. C'est "new char[]" ou le buffer local qui sont les alternatives.
-- ;-)
Ivan Vecerina
"Fabien LE LEZ" wrote in message news:
On Thu, 13 Nov 2003 19:54:25 +0100, "Ivan Vecerina" wrote:
- si new[] ou le ctr lancent une exception, va_end ne sera pas appelé (pas bien)
Plutôt que de s'emmerder avec des try/catch à ne plus finir, mets tout le bazar dans une classe : ...
Alternative: utiliser std::vector<char> plutot que new[]. Ce n'est AMHA pas une "alternative", mais la solution canonique. C'est
"new char[]" ou le buffer local qui sont les alternatives.
Ouaip. J'étais parti sur vector, puis me suis dit (a tort) que ce serait trop long d'utiliser RAII pour le va_end, et que quitte à utiliser un catch()... Donc, pour clore l'exercice:
std::string strptrintf(const char *chFormat, ...) { struct va_Owner { va_list args; va_Owner(const char *chFormat) { va_start(args, chFormat); } ~va_Owner() { va_end (args); } //NB: copy-ctr, op= privés etc à ajouter si pas slmt pour ici }; va_Owner va(chFormat);
char localBuf[256]; int const len = vsnprintf( localBuf, sizeof(localBuf) , chFormat, va.args ); if( len<sizeof(localBuf) ) return localBuf;
Ceci dit, oui: - à réserver aux enracinés à printf. - vsnprintf n'existe pas en standard C++ (n'est que ds C99) - boost::format pour tout nouveau code: http://www.boost.org/libs/format/doc/format.html
[Note en passant : si jamais ce thread est un troll et que je suis tombé dedans, toutes mes excuses...] Si c'en était un, je suis aussi tombé dedans... n'en avait pas l'air.
Merci, Ivan -- http://ivan.vecerina.com
"Fabien LE LEZ" <gramster@gramster.com> wrote in message
news:cn38rvcocsioa2bm4i6m2fjriakral2b9u@4ax.com...
On Thu, 13 Nov 2003 19:54:25 +0100, "Ivan Vecerina"
<please_use_web_form@ivan.vecerina.com> wrote:
- si new[] ou le ctr lancent une exception, va_end
ne sera pas appelé (pas bien)
Plutôt que de s'emmerder avec des try/catch à ne plus finir, mets tout
le bazar dans une classe :
...
Alternative: utiliser std::vector<char> plutot
que new[].
Ce n'est AMHA pas une "alternative", mais la solution canonique. C'est
"new char[]" ou le buffer local qui sont les alternatives.
Ouaip. J'étais parti sur vector, puis me suis dit (a tort) que
ce serait trop long d'utiliser RAII pour le va_end, et que quitte
à utiliser un catch()...
Donc, pour clore l'exercice:
std::string strptrintf(const char *chFormat, ...)
{
struct va_Owner
{
va_list args;
va_Owner(const char *chFormat) { va_start(args, chFormat); }
~va_Owner() { va_end (args); }
//NB: copy-ctr, op= privés etc à ajouter si pas slmt pour ici
};
va_Owner va(chFormat);
char localBuf[256];
int const len = vsnprintf( localBuf, sizeof(localBuf)
, chFormat, va.args );
if( len<sizeof(localBuf) )
return localBuf;
Ceci dit, oui:
- à réserver aux enracinés à printf.
- vsnprintf n'existe pas en standard C++ (n'est que ds C99)
- boost::format pour tout nouveau code:
http://www.boost.org/libs/format/doc/format.html
[Note en passant : si jamais ce thread est un troll et que je suis
tombé dedans, toutes mes excuses...]
Si c'en était un, je suis aussi tombé dedans... n'en avait pas l'air.
On Thu, 13 Nov 2003 19:54:25 +0100, "Ivan Vecerina" wrote:
- si new[] ou le ctr lancent une exception, va_end ne sera pas appelé (pas bien)
Plutôt que de s'emmerder avec des try/catch à ne plus finir, mets tout le bazar dans une classe : ...
Alternative: utiliser std::vector<char> plutot que new[]. Ce n'est AMHA pas une "alternative", mais la solution canonique. C'est
"new char[]" ou le buffer local qui sont les alternatives.
Ouaip. J'étais parti sur vector, puis me suis dit (a tort) que ce serait trop long d'utiliser RAII pour le va_end, et que quitte à utiliser un catch()... Donc, pour clore l'exercice:
std::string strptrintf(const char *chFormat, ...) { struct va_Owner { va_list args; va_Owner(const char *chFormat) { va_start(args, chFormat); } ~va_Owner() { va_end (args); } //NB: copy-ctr, op= privés etc à ajouter si pas slmt pour ici }; va_Owner va(chFormat);
char localBuf[256]; int const len = vsnprintf( localBuf, sizeof(localBuf) , chFormat, va.args ); if( len<sizeof(localBuf) ) return localBuf;
Ceci dit, oui: - à réserver aux enracinés à printf. - vsnprintf n'existe pas en standard C++ (n'est que ds C99) - boost::format pour tout nouveau code: http://www.boost.org/libs/format/doc/format.html
[Note en passant : si jamais ce thread est un troll et que je suis tombé dedans, toutes mes excuses...] Si c'en était un, je suis aussi tombé dedans... n'en avait pas l'air.
Merci, Ivan -- http://ivan.vecerina.com
kanze
"Ivan Vecerina" wrote in message news:<bp0k0v$iab$...
Très bien, à quelques détails près: - buff n'est pas initialise avant le 1er appel a vsnprintf. Bcp de compils en feront un 'warning'.
En effet, il aurait pû en passer (char*)NULL. (Si on tient à faire du C, autant le faire correctement.)
- je serais tente d'utiliser un buffer local lors du premier appel, pour eviter l'alloc et le second appel lorsque c'est possible. - si le constructeur de sS lance une exception (eh oui, c'est possible) il y aura un memory leak.
J'ai une classe Buffer qui gère les deux. Elle commence avec un char[] membre, puis passe à malloc/realloc quand ça ne suffit pas.
- si new[] ou le ctr lancent une exception, va_end ne sera pas appelé (pas bien)
Encore une raison d'éviter les vararg's en C++.
En fait, la solution est assez simple. Voir GB_Format à ma site, par exemple. (Et l'« assez simple » est un peu ironique. Bien que la plupart de la complexité est due au fait de vouloir supporter d'une part l'extension X/Open des paramètres positionnels, et de l'autre, à vouloir supporter absolument toutes les options de printf, y compris celles qui n'ont pas d'équivalent dans les options de formattage des ostream.)
-- James Kanze GABI Software mailto: Conseils en informatique orientée objet/ http://www.gabi-soft.fr Beratung in objektorientierter Datenverarbeitung 11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16
"Ivan Vecerina" <please_use_web_form@ivan.vecerina.com> wrote in message
news:<bp0k0v$iab$1@newshispeed.ch>...
"Eric Bart" <eric.bart@wanadoo-tralala.fr> wrote in message
news:bp08o3$oqt$1@news-reader5.wanadoo.fr...
Très bien, à quelques détails près:
- buff n'est pas initialise avant le 1er appel a vsnprintf.
Bcp de compils en feront un 'warning'.
En effet, il aurait pû en passer (char*)NULL. (Si on tient à faire du C,
autant le faire correctement.)
- je serais tente d'utiliser un buffer local lors du
premier appel, pour eviter l'alloc et le second
appel lorsque c'est possible.
- si le constructeur de sS lance une exception (eh oui,
c'est possible) il y aura un memory leak.
J'ai une classe Buffer qui gère les deux. Elle commence avec un char[]
membre, puis passe à malloc/realloc quand ça ne suffit pas.
- si new[] ou le ctr lancent une exception, va_end
ne sera pas appelé (pas bien)
Encore une raison d'éviter les vararg's en C++.
En fait, la solution est assez simple. Voir GB_Format à ma site, par
exemple. (Et l'« assez simple » est un peu ironique. Bien que la plupart
de la complexité est due au fait de vouloir supporter d'une part
l'extension X/Open des paramètres positionnels, et de l'autre, à vouloir
supporter absolument toutes les options de printf, y compris celles qui
n'ont pas d'équivalent dans les options de formattage des ostream.)
--
James Kanze GABI Software mailto:kanze@gabi-soft.fr
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16
Très bien, à quelques détails près: - buff n'est pas initialise avant le 1er appel a vsnprintf. Bcp de compils en feront un 'warning'.
En effet, il aurait pû en passer (char*)NULL. (Si on tient à faire du C, autant le faire correctement.)
- je serais tente d'utiliser un buffer local lors du premier appel, pour eviter l'alloc et le second appel lorsque c'est possible. - si le constructeur de sS lance une exception (eh oui, c'est possible) il y aura un memory leak.
J'ai une classe Buffer qui gère les deux. Elle commence avec un char[] membre, puis passe à malloc/realloc quand ça ne suffit pas.
- si new[] ou le ctr lancent une exception, va_end ne sera pas appelé (pas bien)
Encore une raison d'éviter les vararg's en C++.
En fait, la solution est assez simple. Voir GB_Format à ma site, par exemple. (Et l'« assez simple » est un peu ironique. Bien que la plupart de la complexité est due au fait de vouloir supporter d'une part l'extension X/Open des paramètres positionnels, et de l'autre, à vouloir supporter absolument toutes les options de printf, y compris celles qui n'ont pas d'équivalent dans les options de formattage des ostream.)
-- James Kanze GABI Software mailto: Conseils en informatique orientée objet/ http://www.gabi-soft.fr Beratung in objektorientierter Datenverarbeitung 11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16
Eric Bart
Merci pour la leçon ! Je vois que je suis loin d'être 100% C++
Ces flux y m'embêtent. Cette classe string me parait mal équippée en standard, surtout après avoir connu la classe AnsiString de Borland.
Si la technologie objet me parait incontournable, je me demande naivement si le C++ est sa meilleure implémentation ...
Donc, pour clore l'exercice:
std::string strptrintf(const char *chFormat, ...) { struct va_Owner { va_list args; va_Owner(const char *chFormat) { va_start(args, chFormat); } ~va_Owner() { va_end (args); } //NB: copy-ctr, op= privés etc à ajouter si pas slmt pour ici }; va_Owner va(chFormat);
char localBuf[256]; int const len = vsnprintf( localBuf, sizeof(localBuf) , chFormat, va.args ); if( len<sizeof(localBuf) ) return localBuf;
Ceci dit, oui: - à réserver aux enracinés à printf. - vsnprintf n'existe pas en standard C++ (n'est que ds C99) - boost::format pour tout nouveau code: http://www.boost.org/libs/format/doc/format.html
[Note en passant : si jamais ce thread est un troll et que je suis tombé dedans, toutes mes excuses...] Si c'en était un, je suis aussi tombé dedans... n'en avait pas l'air.
Merci, Ivan -- http://ivan.vecerina.com
Merci pour la leçon ! Je vois que je suis loin d'être 100% C++
Ces flux y m'embêtent. Cette classe string me parait mal équippée
en standard, surtout après avoir connu la classe AnsiString de Borland.
Si la technologie objet me parait incontournable, je me demande naivement
si le C++ est sa meilleure implémentation ...
Donc, pour clore l'exercice:
std::string strptrintf(const char *chFormat, ...)
{
struct va_Owner
{
va_list args;
va_Owner(const char *chFormat) { va_start(args, chFormat); }
~va_Owner() { va_end (args); }
//NB: copy-ctr, op= privés etc à ajouter si pas slmt pour ici
};
va_Owner va(chFormat);
char localBuf[256];
int const len = vsnprintf( localBuf, sizeof(localBuf)
, chFormat, va.args );
if( len<sizeof(localBuf) )
return localBuf;
Ceci dit, oui:
- à réserver aux enracinés à printf.
- vsnprintf n'existe pas en standard C++ (n'est que ds C99)
- boost::format pour tout nouveau code:
http://www.boost.org/libs/format/doc/format.html
[Note en passant : si jamais ce thread est un troll et que je suis
tombé dedans, toutes mes excuses...]
Si c'en était un, je suis aussi tombé dedans... n'en avait pas l'air.
Ceci dit, oui: - à réserver aux enracinés à printf. - vsnprintf n'existe pas en standard C++ (n'est que ds C99) - boost::format pour tout nouveau code: http://www.boost.org/libs/format/doc/format.html
[Note en passant : si jamais ce thread est un troll et que je suis tombé dedans, toutes mes excuses...] Si c'en était un, je suis aussi tombé dedans... n'en avait pas l'air.
Merci, Ivan -- http://ivan.vecerina.com
Christophe Lephay
Eric Bart wrote:
Merci pour la leçon ! Je vois que je suis loin d'être 100% C++
Ces flux y m'embêtent. Cette classe string me parait mal équippée en standard, surtout après avoir connu la classe AnsiString de Borland.
Si la technologie objet me parait incontournable, je me demande naivement si le C++ est sa meilleure implémentation ...
La question est légitime. Attention seulement à ne pas confondre POO et librairie (les qualités et défauts de std::string n'ont pas grand chose à voir avec le modèle objet du C++)...
Chris
Eric Bart wrote:
Merci pour la leçon ! Je vois que je suis loin d'être 100% C++
Ces flux y m'embêtent. Cette classe string me parait mal équippée
en standard, surtout après avoir connu la classe AnsiString de
Borland.
Si la technologie objet me parait incontournable, je me demande
naivement si le C++ est sa meilleure implémentation ...
La question est légitime. Attention seulement à ne pas confondre POO et
librairie (les qualités et défauts de std::string n'ont pas grand chose à
voir avec le modèle objet du C++)...
Merci pour la leçon ! Je vois que je suis loin d'être 100% C++
Ces flux y m'embêtent. Cette classe string me parait mal équippée en standard, surtout après avoir connu la classe AnsiString de Borland.
Si la technologie objet me parait incontournable, je me demande naivement si le C++ est sa meilleure implémentation ...
La question est légitime. Attention seulement à ne pas confondre POO et librairie (les qualités et défauts de std::string n'ont pas grand chose à voir avec le modèle objet du C++)...
Chris
Fabien LE LEZ
On Fri, 14 Nov 2003 21:09:57 +0100, "Eric Bart" wrote:
Cette classe string me parait mal équippée en standard
Tu peux toujours prendre une autre classe de chaînes, en essayant tout de même de garder la portabilité. Il me semble que boost en propose.
-- ;-)
On Fri, 14 Nov 2003 21:09:57 +0100, "Eric Bart"
<eric.bart@wanadoo-tralala.fr> wrote:
Cette classe string me parait mal équippée
en standard
Tu peux toujours prendre une autre classe de chaînes, en essayant tout
de même de garder la portabilité. Il me semble que boost en propose.
On Fri, 14 Nov 2003 21:09:57 +0100, "Eric Bart" wrote:
Cette classe string me parait mal équippée en standard
Tu peux toujours prendre une autre classe de chaînes, en essayant tout de même de garder la portabilité. Il me semble que boost en propose.
-- ;-)
James Kanze
Fabien LE LEZ writes:
|> On Fri, 14 Nov 2003 21:09:57 +0100, "Eric Bart" |> wrote:
|> >Cette classe string me parait mal équippée |> >en standard
|> Tu peux toujours prendre une autre classe de chaînes, en essayant |> tout de même de garder la portabilité. Il me semble que boost |> en propose.
Il faudrait aussi comprendre ce qu'il entend par « mal équipée ». Je ne crois pas qu'il soit interdit d'écrire des fonctions libres qui fait ce qu'on veut.
-- James Kanze mailto: Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 11 rue de Rambouillet, 78460 Chevreuse, France +33 1 41 89 80 93
Fabien LE LEZ <gramster@gramster.com> writes:
|> On Fri, 14 Nov 2003 21:09:57 +0100, "Eric Bart"
|> <eric.bart@wanadoo-tralala.fr> wrote:
|> >Cette classe string me parait mal équippée
|> >en standard
|> Tu peux toujours prendre une autre classe de chaînes, en essayant
|> tout de même de garder la portabilité. Il me semble que boost
|> en propose.
Il faudrait aussi comprendre ce qu'il entend par « mal
équipée ». Je ne crois pas qu'il soit interdit d'écrire des
fonctions libres qui fait ce qu'on veut.
--
James Kanze mailto:kanze@gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France +33 1 41 89 80 93
|> On Fri, 14 Nov 2003 21:09:57 +0100, "Eric Bart" |> wrote:
|> >Cette classe string me parait mal équippée |> >en standard
|> Tu peux toujours prendre une autre classe de chaînes, en essayant |> tout de même de garder la portabilité. Il me semble que boost |> en propose.
Il faudrait aussi comprendre ce qu'il entend par « mal équipée ». Je ne crois pas qu'il soit interdit d'écrire des fonctions libres qui fait ce qu'on veut.
-- James Kanze mailto: Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 11 rue de Rambouillet, 78460 Chevreuse, France +33 1 41 89 80 93
Eric Bart
Il faudrait aussi comprendre ce qu'il entend par « mal équipée ». Je ne crois pas qu'il soit interdit d'écrire des fonctions libres qui fait ce qu'on veut.
Est-ce qu'il est possible de modifier la classe string sans changer les sources systèmes ? Si pour rajouter une fonction à la classe string je suis obligé d'éditer les sources standards, alors je ne pourrai pas par exemple, distribuer mes sources. Il faudra que je prévienne de modifier la classe string. Pas très pratique.
Je peux bien sûr rajouter les sources de boost à mon projet. M'enfin tout dépend de la confiance que j'accorde à boost. Est-ce que boost se compile sur tout ? durera t-il ? Est-ce qu'une librairie standard ne remplacera boost d'ici peu, rendant mon programme illisible dans quelques années.
Il faudrait aussi comprendre ce qu'il entend par « mal
équipée ». Je ne crois pas qu'il soit interdit d'écrire des
fonctions libres qui fait ce qu'on veut.
Est-ce qu'il est possible de modifier la classe string sans changer
les sources systèmes ? Si pour rajouter une fonction à la classe string
je suis obligé d'éditer les sources standards, alors je ne pourrai pas
par exemple, distribuer mes sources. Il faudra que je prévienne de
modifier la classe string. Pas très pratique.
Je peux bien sûr rajouter les sources de boost à mon projet. M'enfin
tout dépend de la confiance que j'accorde à boost. Est-ce que boost
se compile sur tout ? durera t-il ? Est-ce qu'une librairie standard
ne remplacera boost d'ici peu, rendant mon programme illisible dans
quelques années.
Il faudrait aussi comprendre ce qu'il entend par « mal équipée ». Je ne crois pas qu'il soit interdit d'écrire des fonctions libres qui fait ce qu'on veut.
Est-ce qu'il est possible de modifier la classe string sans changer les sources systèmes ? Si pour rajouter une fonction à la classe string je suis obligé d'éditer les sources standards, alors je ne pourrai pas par exemple, distribuer mes sources. Il faudra que je prévienne de modifier la classe string. Pas très pratique.
Je peux bien sûr rajouter les sources de boost à mon projet. M'enfin tout dépend de la confiance que j'accorde à boost. Est-ce que boost se compile sur tout ? durera t-il ? Est-ce qu'une librairie standard ne remplacera boost d'ici peu, rendant mon programme illisible dans quelques années.