You must have missed the part where I explained that it is less efficient than deathmetal's original code, which itself is not too bad where efficiency is concerned. If the aim is to be efficient while retaining some measure of buffer flow avoidance and reusability, I would go for something like this instead:
Code:
#include <assert.h>
#include <stdio.h>
#include <string.h>
char *join_by_char(char *dest, size_t dest_maxlen, const char *left, char glue, const char *right, size_t left_len, size_t right_len)
{
assert(left_len + right_len < dest_maxlen);
memcpy(dest, left, left_len);
dest[left_len] = glue;
memcpy(dest + left_len + 1, right, right_len);
dest[left_len + right_len + 1] = '\0';
return dest;
}
int main(void)
{
char names[][100] = {"john", "abbey", "mouse", "micky", "minney"};
char result[200];
for (size_t i = 0; i < sizeof(names) / sizeof(names[0]) - 1; ++i)
{
size_t len1 = strlen(names[i]);
size_t len2 = strlen(names[i + 1]);
printf("name is %s\n", join_by_char(result, sizeof(result) - 1, names[i], '*', names[i + 1], len1, len2));
printf("name is %s\n", join_by_char(result, sizeof(result) - 1, names[i + 1], '*', names[i], len2, len1));
}
return 0;
}
But it lacks the kind of flexibility as with my earlier example where dest_maxlen can be used to limit the destination string rather than merely function as an assertion check. It's possible to re-insert the limit functionality, but then it'll basically be replacing the strncat calls in my earlier example with memcpy + the input string lengths, hence avoiding the extra length checking, null character search, and null character appending. Plausible, but ultimately demonstrating the use of strncat may be better for general use with null terminated strings.
Of course, if you have an even more efficient solution, you should go ahead and let deathmetal know about it. After all, what I posted above does not result in fewer function calls.