One other issue not yet considered is "How do I handle words with an odd number of characters?". It's easy to split 1234
into 12
and 34
, but how do you split 123
? You must decide how to test for odd/even and decide which half gets the extra character (generally the first half, but it's up to you). You should also consider splitting strings of any size (and validate against processing a NULL pointer or empty-string passed to your function).
To handle checking odd/even length, all you need to do is check the 1st-bit of length on little-endian systems, or for complete portability just use modulo 2
. If the 1st-bit (on little-endian) or the result of len % 2
is 0
it's even, otherwise the length is odd. (if odd, just add +1
character to the first half).
If your compiler supports Variable Length Array C99 extensions, the problem becomes simply a matter of declaring the two VLAs and letting the compiler handle the work, e.g.
void split_vla (char *s)
{
if (!s || !*s) { /* validate parameter not NULL or empty-string */
fprintf (stderr, "error: s NULL or empty-string.\n");
return;
}
size_t l = strlen (s),
n = (l % 2 == 0) ? l / 2 : l / 2 + 1;
char s1[n + 1], s2[n + 1]; /* declare VLAs */
memcpy (s1, s, n); /* memcpy chars to each half */
memcpy (s2, s + n, l - n);
s1[n] = 0; /* affirmatively nul-terminate */
s2[l - n] = 0;
printf ("s : %s\ns1 : %s\ns2 : %s\n", s, s1, s2);
}
If it doesn't, you can always dynamically allocate storage for each of the halfs (and if you choose calloc
over malloc
, then your storage is initialized to all zeros (providing a nul-byte at the end of each half), e.g.
void split_dyn (char *s)
{
if (!s || !*s) { /* validate parameter not NULL or empty-string */
fprintf (stderr, "error: s NULL or empty-string.\n");
return;
}
size_t l = strlen (s),
n = (l % 2 == 0) ? l / 2 : l / 2 + 1;
char *s1, *s2;
/* allocate storage for s1 & s2 and validate allocation */
if (!(s1 = calloc (n + 1, 1)) || !(s2 = calloc (n + 1, 1))) {
fprintf (stderr, "error: virtual memory exhausted.\n");
exit (EXIT_FAILURE);
}
memcpy (s1, s, n); /* memcpy chars to each half */
memcpy (s2, s + n, l - n);
printf ("s : %s\ns1 : %s\ns2 : %s\n", s, s1, s2);
free (s1); /* don't forget to free the memory you allocate */
free (s2);
}
Either way is fine depending on what your compiler supports. You are free to use malloc
and affirmatively nul-terminate as was done in the VLA example. Also be aware that alloca
gives similar functionality to what you get with VLAs, but provides a bit more flexibility in the scope for your arrays (not relevant here since the VLAs are declared with function scope but be aware of the additional method). Give both examples a try and let me know if you have further questions.
Example Use/Output
$ ./bin/str_split_half 123456789
s : 123456789
s1 : 12345
s2 : 6789
$ ./bin/str_split_half 1234567890
s : 1234567890
s1 : 12345
s2 : 67890
$ ./bin/str_split_half 1
s : 1
s1 : 1
s2 :