3 ms·
Eh... // This code is licensed under CC0. // A copy of the license can be obtained at https://creativecommons.org/publicdomain/zero/1.0/ // May you forev
by anon4 11y ago
Eh...
// This code is licensed under CC0.
// A copy of the license can be obtained at https://creativecommons.org/publicdomain/zero/1.0/
// May you forever catenate in peace.
#define strcatm(...) strcat_multi(__VA_ARGS__, NULL);
char* strcat_multi(char *dest, ...) {
va_list srcs;
char *dest_end;
const char *src;
size_t src_sz;
va_start(srcs, dest);
for (dest_end = dest; *dest_end; dest_end++);
for (src = va_arg(srcs, const char *); src; src = va_arg(srcs, const char *)) {
src_sz = strlen(src);
memmove(dest_end, src, src_sz);
dest_end += src_sz;
*dest_end = '\0';
}
va_end(srcs);
return dest_end;
}
There. Now go and catenate, children.
- anon4 11y agoAs a bonus, this works with e.g. char buf[256]; buf[0] = 'x'; buf[1] = '\0'; strcatm(buf, buf, buf, buf); producing a string of 16 'x's
- huhtenberg 11y agostrcatm(..., NULL); and it's 8 x/s, not 16. Also fix , to ; in the second for loop.
- anon4 11y agostrcatm is the convenience macro that adds a last NULL arg. And it's 16, because it doubles each time. Already fixed.
- huhtenberg 11y agostrcatm - aye, missed that, but I must insist on 8.
- anon4 11y agoRight, 8. I miscounted it as 4 loops :)
- Kristine1975 11y agoI'll concatenate the hell out of the buffer and whatever comes after it.
- deleted 11y ago[deleted]
- efaref 11y ago// This code is licensed under CC0. // A copy of the license can be obtained at https://creativecommons.org/publicdomain/zero/1.0/ // May you forever catenate in peace. #define strncatm(dest, sz, ...) strncat_multi((dest), (sz), __VA_ARGS__, NULL); char* strncat_multi(char *dest, size_t dest_sz, ...) { va_list srcs; char *dest_end; const char *src; size_t src_sz; size_t dest_off; size_t copy_sz; va_start(srcs, dest_sz); for (dest_end = dest, dest_off = 0; *dest_end && dest_off < dest_sz; dest_end++, dest_sz++); for (src = va_arg(srcs, const char *); src && dest_off < dest_sz; src = va_arg(srcs, const char *)) { src_sz = strlen(src); copy_sz = src_sz < (dest_sz - dest_off) ? src_sz : (dest_sz - dest_off); memmove(dest_end, src, copy_sz); dest_end += copy_sz; dest_off += copy_sz; if (dest_off < dest_sz) { *dest_end = '\0'; } } va_end(srcs); return dest_end; }
- anon4 11y agoGood, but I'd do one modification -- always write a null byte at the end. Otherwise you end up with a non-null-terminated string and that's bad. So, copy_sz = src_sz < (dest_sz - dest_off) ? src_sz : (dest_sz - dest_off - 1); ... *dest_end = '\0';
- unwind 11y agoBut remember to rename the function, since all function names starting with "str" are reserved in C. To keep with the spirit of the article, calling strlen() just to allow convenient use of memmove() seems a bit counter-intuitive, I'd roll the two together into a copying loop instead.
- anon4 11y agoAnd then you do infinite copying if you're catenating a string with itself.