Xref: utzoo comp.unix.questions:6847 comp.unix.wizards:8219 Path: utzoo!mnetor!uunet!lll-winken!lll-tis!ames!umd5!mimsy!chris From: chris@mimsy.UUCP (Chris Torek) Newsgroups: comp.unix.questions,comp.unix.wizards Subject: Re: Guessing buffer size needed for sprintf beforehand Message-ID: <11331@mimsy.UUCP> Date: 3 May 88 15:30:52 GMT References: <136@insyte.uucp> Organization: U of Maryland, Dept. of Computer Science, Coll. Pk., MD 20742 Lines: 83 Keywords: sprintf In article <136@insyte.uucp> jad@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@mimsy.umd.edu Path: uunet!mimsy!chris