I’m much less experienced in C than I am in higher-level languages. At Cisco, we use C, and I sometimes run into something that would be easy to do in Java or Python, but very difficult to do in C. Now is one of those times.
I have a dynamically-allocated array of unsigned integers which I need to convert to a comma-separated string for logging. While the integers are not likely to be very large, they could conceptually be anywhere from 0 to 4,294,967,295 In Python, that’s one short line.
my_str = ','.join(my_list)
How elegantly can people do this in C? I came up with a way, but it’s gross. If anyone knows a nice way to do it, please enlighten me.
In contrast to other answers, does not mandate C99.
The real problem here is not knowing the length of the string you're going to need. Getting a number is as easy as sprintf("%u", *num)
using num
to walk your array of int
s, but how much space are you going to need? To avoid overrunning a buffer, you have to keep track of a lot of integers.
size_t join_integers(const unsigned int *num, size_t num_len, char *buf, size_t buf_len) {
size_t i;
unsigned int written = 0;
for(i = 0; i < num_len; i++) {
written += snprintf(buf + written, buf_len - written, (i != 0 ? ", %u" : "%u"),
*(num + i));
if(written == buf_len)
break;
}
return written;
}
Notice, that I keep track of how much of the buffer I have used and use snprintf
so I don't overrun the end. snprintf
will tack on a \0
, but since I'm using buf + written
I will start at the \0
of the previous snprintf
.
In use:
int main() {
size_t foo;
char buf[512];
unsigned int numbers[] = { 10, 20, 30, 40, 1024 };
foo = join_integers(numbers, 5, buf, 512);
printf("returned %u\n", foo);
printf("numbers: %s\n", buf);
}
Outputs:
returned 20
numbers: 10, 20, 30, 40, 1024
Forcing the limiting to kick in, instead of overrunning:
char buf[15];
foo = join_integers(numbers, 5, buf, 14);
buf[14] = '\0';
Outputs, expectedly:
returned 14
numbers: 10, 20, 30, 4
You can actually use a library like Glib, which contains functions like
gchar* g_strjoin (const gchar *separator, ...);
Joins a number of strings together to form one long string, with the optional separator inserted between each of them. The returned string should be freed with g_free().
(you still need to use g_snprintf()
, possibly with g_printf_string_upper_bound()
to ensure space)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With