variable number of strings passed to function - how?

Doug Gwyn gwyn at smoke.BRL.MIL
Sun Oct 23 05:03:17 AEST 1988


In article <434 at tutor.UUCP> pete at tutor.UUCP (Peter Schmitt) writes:
>I want to write a function that accepts a variable number of string
>arguments.  What is a possible way to do this?

There are two portable ways to do this as stated, using variable-
argument facilities (you could also pass as a fixed argument a
variable-sized data structure containing the strings).  Either a
count of the number of strings is passed as the first argument,
or a null pointer (end marker) is passed after the last string.

The two standard variable-argument facilities are associated with
the headers <varargs.h> (most current implementations) and
<stdarg.h> (ANSI C conforming implementations).  I generally code
for both, using #if __STDC__ as necessary to control compilation
of the correct variation of the code.  You should refer to your
reference manual for details of these facilities, but here is an
example extracted from the BRL/VLD MUVES project source code:


#include <stdio.h>
#include <string.h>

#if __STDC__
#include <stdarg.h>
#else
#include <varargs.h>
#endif

#include <Er.h>			/* error-logging package interface */
#include <Mm.h>			/* memory-management package iface */

/*
	IoOpenFile() opens the file named by the concatenation of its
	variable character-string arguments for reading; it returns NULL
	if memory could not be allocated to build the pathname or if the
	file could not be opened (in which case ErIndex is set to
	`errnum').  The final argument must be (char *)NULL.
*/

#if __STDC__
FILE *
IoOpenFile( long errnum, ... )
	{
#else
/*VARARGS*/
FILE *
IoOpenFile( va_alist )
	va_dcl
	{
	long	errnum;
#endif
	va_list		ap;
	register FILE	*fp;		/* opened file stream pointer */
	register char	*p;		/* -> filename segment */
	register char	*cp;		/* -> end of partial filename */
	register int	name_len;	/* string allocation length */
	char		*fname;		/* full path name of file */

	/* allocate space for filename */

#if __STDC__
	va_start( ap, errnum );
#else
	va_start( ap );
	errnum = va_arg( ap, long );
#endif

	for ( name_len = 1; (p = va_arg( ap, char * )) != NULL; )
		name_len += strlen( p );

	va_end( ap );

	if ( (fname = cp = MmVAllo( name_len, char )) == NULL )
		return (FILE *)NULL;	/* ErIndex already set */

	/* construct concatenated filename */

#if __STDC__
	va_start( ap, errnum );
#else
	va_start( ap );
	(void)va_arg( ap, long );	/* skip errnum */
#endif

	while ( (p = va_arg( ap, char * )) != NULL )
		while ( (*cp = *p++) != '\0' )
			++cp;

	va_end( ap );

	/* try to open the file */

	if ( (fp = fopen( fname, "r" )) == NULL )
		ErSet( errnum );

	/* deallocate filename space */

	MmVFree( name_len, char, fname );
	return fp;			/* (may be NULL) */
	}



More information about the Comp.lang.c mailing list