char *strcat(), *strcpy(), *fgets();

Lloyd Zusman ljz at fxgrp.UUCP
Sun Jun 26 14:55:17 AEST 1988


In article <8160 at brl-smoke.ARPA> gwyn at brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes:
  In article <11580010 at hpisod2.HP.COM> decot at hpisod2.HP.COM (Dave Decot) writes:
  >> ...  Here is a real example from source code
  >> ...
  >> 	(void)strcat(strcat(strcat(strcat(strcat(strcpy(fn, [...]
  
  >This is much more efficiently (and readably!) rendered as:
  >     (void) sprintf(fn, "%s%s/%s/%s", TargetDir, target, approx, CCMAP);
  
  What you say is true (indeed, the reason the code was open in a layer was
  because I was straightening this out), but sometimes sprintf() is inadvisable
  ...

Here are a couple of routines that can be used in place of the
messy string of strcat's and also in place of sprintf:

1)  char *strset(result, s1, s2, ..., NULL)

    (where all arguments are "char *").  This concatenates 's1', 's2', ...
    together, putting the result plus a trailing '\0' into 'result',
    which must be large enough to hold everything.

    Variations of this routine appear in many places.

2)  This one is rarer:

    char *stralloc(s1, s2, ..., NULL)

    (again, where all arguments are "char *").  This allocates a string
    large enough to hold 's1', 's2', ... plus a trailing '\0', and then
    concatenates everything into this allocated string, whose address is
    returned to the caller.  Allocation is done via malloc(), and the
    return value is NULL if this failed.

I used the 'varargs' convention to implement this, but I believe that
'stdargs' would also work (using 'stdargs' is left as an exercise to
the reader).

Please forgive me if I accidentally introduced a bug or two into these
routines ... I had to copy them by hand into this article due to
problems at my site, and I may have mistyped something or other.

------------------------- routines follow ----------------------------
#include <varargs.h>

extern char *malloc();

#define NULL	((char *)0)

/*
 * strset(result, string1, string2, ..., NULL)
 *
 *	Concatenate string1, string2, ... together into the result,
 *	which must be big enough to hold all of them plus a trailing
 *	'\0'.  Returns the address of the result.
 *
 *	Example:
 *
 *		char result[100];
 *
 *		(void)strset(result, "This", " ", "is a ", "test", NULL);
 *
 *			result now contains "This is a test".
 */
char *
strset(va_alist)
va_dcl
{
    va_list ap;		/* argument list pointer */
    char *result;	/* pointer to result string */
    char *sp;		/* used as a temporary string pointer */
    char *cp;		/* used as a temporary string pointer */

    va_start(ap);
    
    sp = va_arg(ap, char *);	/* get first argument ... do nothing if NULL */
    if (sp == NULL) {
	return (sp);
    }

    result = sp;	/* save pointer to beginning of result string */

    /*
     * Loop through all the arguments, concatenating each one to the
     * result string.
     */
    for (cp = va_arg(ap, char *); cp != NULL; cp = va_arg(ap, char*)) {
	while (*cp != '\0') {
	    *sp++ = *cp++;
	}
    }
    *sp = '\0';		/* we need a trailing '\0' */

    va_end(ap);

    return (result);
}

/*
 * stralloc(string1, string2, ..., NULL)
 *
 *	Allocate a string big enough to hold the concatenation of
 *	string1, string2, ... plus a '\0', and then concatenate the
 *	strings into it, returning its address to the caller.
 *
 *	Example:
 *
 *		char *result;
 *
 *		result = stralloc("This", " ", "is a ", "test", NULL);
 *
 *			result now contains "This is a test" unless
 *  	    	    	malloc() failed, in which case it contains
 *  	    	    	NULL.  If the call succeeded, the result
 *			can be freed via "free(result)".
 */
char *
stralloc(va_alist)
va_dcl
{
    va_list ap;		/* argument list pointer */
    char *result;	/* result string pointer */
    char *cp;		/* temporary string pointer */
    char *sp;		/* temporary string pointer */
    int size = 1;	/* string size: leave room for trailing '\0' */

    /*
     * First pass: count characters in list of strings.
     */
    va_start(ap);
    for (cp = va_arg(ap, char *); cp != NULL; cp = va_arg(ap, char*)) {
	while (*cp++ != '\0') {
	    ++size;
	}
    }

    /*
     * Allocate the string.
     */
    result = malloc(size);
    if (result == NULL) {
	return (result);
    }
    sp = result;

    /*
     * Second pass: copy the arguments.
     */
    va_start(ap);
    for (cp = va_arg(ap, char *); cp != NULL; cp = va_arg(ap, char*)) {
	while (*cp) {
	    *sp++ = *cp++;
	}
    }
    *sp = '\0';

    va_end(ap);

    return (result);
}
--
  Lloyd Zusman                          UUCP:   ...!ames!fxgrp!ljz
  Master Byte Software              Internet:   ljz%fx.com at ames.arc.nasa.gov
  Los Gatos, California               or try:   fxgrp!ljz at ames.arc.nasa.gov
  "We take things well in hand."



More information about the Comp.std.c mailing list