Re: String concatenation function, request for comments.
- From: Michael Mair <Michael.Mair@xxxxxxxxxxxxxxx>
- Date: Sun, 05 Jun 2005 16:20:14 +0200
michael.casey@xxxxxxxxx wrote:
The purpose of this post is to obtain the communities opinion of the usefulness, efficiency, and most importantly the correctness of this small piece of code. I thank everyone in advance for your time in considering this post, and for your comments.
I wrote this function to simplify the task of combining strings using mixed sources. I often see the use of sprintf() which results in several lines of code, and more processing than really for the task. The function is pretty straight forward, it accepts a variable list of arguments beginning with the mandatory integer containing the total number of arguments.
The function allocates a static buffer; I thought the use of malloc() to be unnecessary, as the responsibility of freeing the memory would be left to the client. This design choice also minimizes the amount of required arguments. If the resultant buffer is needed beyond the second call to the function, it can be copied to another buffer at the clients digression.
If the strings specified for concatenation exceed the buffer available, the overall string will simply be truncated. I decided on this behaviour because I do not believe the output to be essential to a programs operation, so this error can in most cases go silent, but still be apparent to the programmer once the result is examined.
If the defined buffer amount is insufficient or is unnecessarily large for a particular application, it is left to the client to redefine the buffer amount; I feel that 512 bytes is sufficient for my use.
I find this function most useful when frequently forming messages for use over a socket, which will not otherwise be reused.
Note: Try to be a little bit more short and concise when describing what your code does or is intended to do -- then people will see what you want and not miss an important detail. Your above description could be shortened to your wanting to have sort of a strncat() with arbitrarily many arguments where the destination buffer is an internal static buffer. At least an introduction of this kind might be helpful.
Me's reply (<1117978823.695019.91800@xxxxxxxxxxxxxxxxxxxxxxxxxxxx>) raised most of the important points, so I will more or less try to make you aware of other stuff I saw.
Example use of the function:
char *tmp; tmp = vast("Welcome to ", HOST, ", you are logged in as ", name, ".");
Apart from the forgotten number argument and the better design using a terminating (char *)0 (the cast is necessary for non-fixed arguments of variadic functions). You could get into trouble when using const-qualified strings and the like; on the other hand, using const char* arguments would leave you with typecasts for everything.
Your design makes the function non-reentrant. A "snvast(char *buf, size_t buflen, char *firststring, ...)" would cure this problem, apart from being able to return a sensible error state. vast() could still be used as convenient wrapper to snvast() for most uses. Sensible return types for snvast could be int (similar semantics as snprinf()) or size_t (return strlen(buf)+1 on success and 0 on failure).
send(sockfd, tmp, strlen(tmp), 0);
The function is defined as follows:
/*------------------------------------------------------------------*\ |- vast(): Variable Argument String; concatenate arbitrary strings. -| \*------------------------------------------------------------------*/
#define VAST_BUF 512
char *vast(int num, ...) {
static char buf[VAST_BUF];
int t = 0, o = 0;
char *v;
va_list ap;
if(num > 1) { va_start(ap, num);
/* Loop it while its hot. */
while(num--) { v = va_arg(ap, char *);
/* Copy string to cumulative buffer until NUL is reached */ /* so long as the total does not exceed (MAX_BUF - 1). */
while((buf[o] = *v++) && !(t >= VAST_BUF - 1)) { /* Condition is met, increment offset and total. */ t++, o++; } }
va_end(ap); }
buf[o] = NUL;
return(buf);
Minor nit: return is not a function. return buf; is entirely sufficient.
}
I agree with most of the points Me raised, so I didn't comment on the same things.
Cheers Michael -- E-Mail: Mine is an /at/ gmx /dot/ de address. .
- Follow-Ups:
- Re: String concatenation function, request for comments.
- From: Chris Torek
- Re: String concatenation function, request for comments.
- References:
- String concatenation function, request for comments.
- From: michael.casey@xxxxxxxxx
- String concatenation function, request for comments.
- Prev by Date: Re: String concatenation function, request for comments.
- Next by Date: Re: String concatenation function, request for comments.
- Previous by thread: Re: String concatenation function, request for comments.
- Next by thread: Re: String concatenation function, request for comments.
- Index(es):
Relevant Pages
|
Loading