Guessing buffer size needed for sprintf beforehand

Chris Torek chris at mimsy.UUCP
Wed May 4 01:30:52 AEST 1988


In article <136 at insyte.uucp> jad at insyte.uucp (Jill Diewald) writes:
>... sprintf ... requires my knowing how big a buffer to supply.
>The IO module of our program needs to sprintf into its internal
>output buffer - which is dynamically allocated. ... The IO routine
>does not know how many characters there are to print until sprintf 
>returns that number, by then it it too late!

Welcome to the `we hate sprintf' club :-) .  Alas, there is no portable
way to do this.  There *is* one reasonably portable solution, but it
may be slow.  If you have a `function oriented stdio', there is a
convenient and fast solution, but it is not portable.

>One solution is to fprintf into a file opened to be /dev/null.
>This requires two calls to the c print fuctions, one to get the
>size and the second to actually print.

By the time you reach a routine that takes a `va_list' argument,
it is too late to scan the argument list twice: there is no way
to `back up' the va_list parameter.  So, while this would get
you a suitable count, it would then be too late to use that count.

>Is there another approach?

Here is one:

static FILE *sfile;		/* dynamic sprintf string file */

/*
 * open a temp file in "w+" mode, or perhaps even
 * in "w+b" mode; abort if it cannot be opened.
 */
void
dynopen()
{
	/* you supply the details */
}

/*
 * dynamically create a string holding the result from a printf.
 */
char *
dynsprintf(fmt, ap)
	char *fmt;
	va_list ap;
{
	static FILE *sfile;
	int count, c;
	char *ret, *cp;

	if (sfile == NULL)
		dynopen();

	/* write the arguments to the temp file, and count characters */
	rewind(sfile);
	count = vfprintf(sfile, fmt, ap);
	if (count == EOF) ... handle error

	/* make room */
	ret = malloc((unsigned)count + 1);
	if (ret == NULL) ... do something

	/* read back the result */
	rewind(sfile);
	cp = ret;
	while (--count >= 0) {
		if ((c = getc(sfile)) == EOF) ... ??? why?
		*cp++ = c;
	}
	*cp = 0;
	return (ret);
}

void
dynclose()
{

	if (sfile != NULL) {
		(void) fclose(sfile);
		... remove temp file
	}
}
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris at mimsy.umd.edu	Path:	uunet!mimsy!chris



More information about the Comp.unix.questions mailing list