Unix Programming - sprintf container

This is Interesting: Free IT Magazines  
Home > Archive > Unix Programming > August 2004 > sprintf container





You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

Author sprintf container
vertigo

2004-08-27, 6:21 pm

Hello
I want to write function which will return me string
formatted by sprintf:

char* sprintf_container(const char *format,...){
str=malloc('what size' ??);
sprintf(str,format,???);
return str;
}

But how should i pass other parameters to sprintf ?

Thanx
Michal

Måns Rullgård

2004-08-27, 6:21 pm

vertigo <none@microsoft.com> writes:

> Hello
> I want to write function which will return me string
> formatted by sprintf:
>
> char* sprintf_container(const char *format,...){
> str=malloc('what size' ??);
> sprintf(str,format,???);
> return str;
> }
>
> But how should i pass other parameters to sprintf ?


man vsprintf

--
Måns Rullgård
mru@mru.ath.cx
Pascal Bourguignon

2004-08-27, 6:21 pm

vertigo <none@microsoft.com> writes:

> Hello
> I want to write function which will return me string
> formatted by sprintf:
>
> char* sprintf_container(const char *format,...){
> str=malloc('what size' ??);
> sprintf(str,format,???);
> return str;
> }
>
> But how should i pass other parameters to sprintf ?


You won't be using sprintf.

You should really, as always, read the manual page for sprintf: man sprintf

Where you'll notice vsnprintf.
Then you'll refer to the stdarg man page: man stdarg


--
__Pascal Bourguignon__ http://www.informatimago.com/

Our enemies are innovative and resourceful, and so are we. They never
stop thinking about new ways to harm our country and our people, and
neither do we.
Jens.Toerring@physik.fu-berlin.de

2004-08-27, 6:21 pm

vertigo <none@microsoft.com> wrote:
> I want to write function which will return me string
> formatted by sprintf:


> char* sprintf_container(const char *format,...){
> str=malloc('what size' ??);
> sprintf(str,format,???);
> return str;
> }


Here's what I use for that:

#define SPRINTF_CONTAINER_TRY_LENGTH 128

char *sprintf_container( const char *fmt, ... )
{
char *c = NULL, *new_c;
size_t len = SPRINTF_CONTAINER_TRY_LENGTH;
va_list ap;
int wr;


while ( 1 )
{
if ( ( new_c = realloc( c, len ) ) == NULL )
{
free( c );
return NULL;
}
c = new_c;

va_start( ap, fmt );
wr = vsnprintf( c, len, fmt, ap );
va_end( ap );

if ( wr < 0 ) /* indicates not enough space with older glibc */
{
len *= 2;
continue;
}

if ( ( size_t ) wr + 1 > len ) /* new glibc returns the number of */
{ /* chars needed, not counting the */
len = wr + 1; /* trailing '\0' */
continue;
}

break;
}

/* Trim the string to the number of required characters */

if ( ( size_t ) wr + 1 < len )
{
if ( ( new_c = realloc( c, ( size_t ) wr + 1 ) ) == NULL )
return c;
else
c = new_c;
}

return c;
}

Regards, Jens
--
\ Jens Thoms Toerring ___ Jens.Toerring@physik.fu-berlin.de
\__________________________ http://www.toerring.de
sean larsson

2004-08-27, 6:21 pm

On Fri, 27 Aug 2004 11:48:53 +0200
vertigo <none@microsoft.com> wrote:

> Hello
> I want to write function which will return me string
> formatted by sprintf:
>
> char* sprintf_container(const char *format,...){
> str=malloc('what size' ??);
> sprintf(str,format,???);
> return str;
> }
>
> But how should i pass other parameters to sprintf ?
>
> Thanx
> Michal
>


or you could use asprintf(). not standard C, but it is portable on linux and
bsd.

--
-sean
Lev Walkin

2004-08-27, 6:21 pm

Jens.Toerring@physik.fu-berlin.de wrote:
> vertigo <none@microsoft.com> wrote:
>
>
>
>
>
> Here's what I use for that:
>
> #define SPRINTF_CONTAINER_TRY_LENGTH 128
>
> char *sprintf_container( const char *fmt, ... )
> {
> char *c = NULL, *new_c;
> size_t len = SPRINTF_CONTAINER_TRY_LENGTH;
> va_list ap;
> int wr;
>
>
> while ( 1 )
> {
> if ( ( new_c = realloc( c, len ) ) == NULL )
> {
> free( c );


if realloc() fails, your program will crash on most free() implementations.



--
Lev Walkin
vlm@lionet.info
Jens.Toerring@physik.fu-berlin.de

2004-08-27, 6:21 pm

Lev Walkin <vlm@lionet.info> wrote:
> Jens.Toerring@physik.fu-berlin.de wrote:
[vbcol=seagreen]
> if realloc() fails, your program will crash on most free() implementations.


In that case 'c' should be either a value returned from a previous call
of alloc(), in which case I don't see a problem, or NULL, and then it
should be a no-op (as far as I can see from the C89 standard). Or am I
overlooking something?
Regards, Jens
--
\ Jens Thoms Toerring ___ Jens.Toerring@physik.fu-berlin.de
\__________________________ http://www.toerring.de
William Ahern

2004-08-27, 6:21 pm

Lev Walkin <vlm@lionet.info> wrote:
> Jens.Toerring@physik.fu-berlin.de wrote:
>
> if realloc() fails, your program will crash on most free() implementations.


Care to elaborate? I'm quite surprised to hear that.

Lev Walkin

2004-08-27, 6:21 pm

Jens.Toerring@physik.fu-berlin.de wrote:
> Lev Walkin <vlm@lionet.info> wrote:
>
>
>
>
>
> In that case 'c' should be either a value returned from a previous call
> of alloc(), in which case I don't see a problem, or NULL, and then it
> should be a no-op (as far as I can see from the C89 standard). Or am I
> overlooking something?


you're overlooking the real world.

however, I've just checked, and indeed it seem to have improved on newer
systems. however, I remember this being a common inconvenience on the older
ones, so it's better not to rely on it.


--
Lev Walkin
vlm@lionet.info
Lev Walkin

2004-08-27, 6:21 pm

William Ahern wrote:
> Lev Walkin <vlm@lionet.info> wrote:
>
>
>
> Care to elaborate? I'm quite surprised to hear that.


The code checks for old behavior of vsnprintf(), which may return -1 instead
of the "estimated" numer of characters. But the code does not go further and
check if the c is non-0 before free()'ing. See my other follow-up on the C89
quote.


--
Lev Walkin
vlm@lionet.info
Jens.Toerring@physik.fu-berlin.de

2004-08-27, 6:21 pm

Lev Walkin <vlm@lionet.info> wrote:
> William Ahern wrote:
[vbcol=seagreen]
> The code checks for old behavior of vsnprintf(), which may return -1 instead
> of the "estimated" numer of characters. But the code does not go further and
> check if the c is non-0 before free()'ing. See my other follow-up on the C89
> quote.


Luckily, I don't remember having to deal with a C version that didn't
work correctly with free() on NULL (but fortunately one tends to forget
about such annoyances and normally, i.e. in the code I really use, I
avoid it anyway because I usually would take it to be an indication
that something went wrong when free() is called with a NULL pointer).
But vsnprintf() is a different case because it's in C99 only, so one
can't reasonably expect that all implementations got it already right
(if they have it at all), so additional checks are (still) in order.
Perhaps I sshould have made it more clear that the code I posted only
works with a system that conforms to C89 and has a vsnprintf() imple-
mentation that either is C99 conformant or returns a negative value
when the the length of the buffer is insufficient.

Regards, Jens
--
\ Jens Thoms Toerring ___ Jens.Toerring@physik.fu-berlin.de
\__________________________ http://www.toerring.de
Bjorn Reese

2004-08-28, 7:48 am

On Fri, 27 Aug 2004 20:32:08 +0000, sean larsson wrote:

> or you could use asprintf(). not standard C, but it is portable on linux and
> bsd.


Here is a version aof asprintf() that will work on all platforms:

http://ctrio.sourceforge.net/

--
mail1dotstofanetdotdk

James Antill

2004-08-28, 3:18 pm

On Fri, 27 Aug 2004 12:13:11 +0000, Jens.Toerring wrote:

> vertigo <none@microsoft.com> wrote:
>

Personally I'd recommend looking at:

http://www.and.org/vstr/printf_comparison.html

....and just using something that does the above for you, creating your own
is non-trivial.
[vbcol=seagreen]
> Here's what I use for that:
>
> #define SPRINTF_CONTAINER_TRY_LENGTH 128
>
> char *sprintf_container( const char *fmt, ... )
> {
> char *c = NULL, *new_c;
> size_t len = SPRINTF_CONTAINER_TRY_LENGTH;
> va_list ap;
> int wr;
>
>
> while ( 1 )
> {
> if ( ( new_c = realloc( c, len ) ) == NULL )
> {
> free( c );
> return NULL;
> }
> c = new_c;
>
> va_start( ap, fmt );
> wr = vsnprintf( c, len, fmt, ap );
> va_end( ap );
>
> if ( wr < 0 ) /* indicates not enough space with older glibc */


This is not the only case that glibc will return -1, see:

http://www.and.org/vstr/security.html#snprintf-ex1

> if ( ( size_t ) wr + 1 < len )
> {
> if ( ( new_c = realloc( c, ( size_t ) wr + 1 ) ) == NULL )
> return c;
> else
> c = new_c;
> }


Do you really want to return the old "c" on allocation failure?

>
> return c;
> }


--
James Antill -- james@and.org
Need an efficient and powerful string library for C?
http://www.and.org/vstr/

Jens.Toerring@physik.fu-berlin.de

2004-08-28, 3:18 pm

James Antill <james-netnews@and.org> wrote:
> On Fri, 27 Aug 2004 12:13:11 +0000, Jens.Toerring wrote:
[vbcol=seagreen]
> This is not the only case that glibc will return -1, see:


> http://www.and.org/vstr/security.html#snprintf-ex1


Thanks, good to know!

[vbcol=seagreen]
> Do you really want to return the old "c" on allocation failure?


If realloc() returns NULL the old pointer should still be valid and
what it's pointing to unchanged, so I would guess that returning
too much memory (and the call of realloc() here is only there to
cut back on the buffer size) with the expected string is preferable
to returning NULL, indicating complete failure. Actually, in my real
code error handling it is done differently, so I had change that part
a bit.
Regards, Jens
--
\ Jens Thoms Toerring ___ Jens.Toerring@physik.fu-berlin.de
\__________________________ http://www.toerring.de
Sponsored Links






Free braindumps | Software forum | Database administration forum

Copyright 2003 - 2008 webservertalk.com