memccpy

From cppreference.com
< c‎ | string‎ | byte
Defined in header <string.h>
void *memccpy( void * restrict dest, const void * restrict src, int c, size_t count );
(since C23)

Copies bytes from the object pointed to by src to the object pointed to by dest, stopping after any of the next two conditions are satisfied:

  • count bytes are copied
  • the byte (unsigned char)c is found (and copied).

The src and dest objects are interpreted as arrays of unsigned char.

The behavior is undefined if any condition is met:

  • access occurs beyond the end of the dest array;
  • the objects overlap (which is a violation of the restrict contract)
  • either dest or src is an invalid or null pointer

Parameters

dest - pointer to the object to copy to
src - pointer to the object to copy from
c - terminating byte, converted to unsigned char at first
count - number of bytes to copy

Return value

If the byte (unsigned char)c was found memccpy returns a pointer to the next byte in dest after (unsigned char)c, otherwise returns null pointer.

Notes

The function is identical to the POSIX memccpy.

memccpy(dest, src, 0, count) behaves similar to strncpy(dest, src, count), except that the former returns a pointer to the end of the buffer written, and does not zero-pad the destination array. Thus, memccpy is useful for efficiently concatenating multiple strings.

char bigString[1000];
char* end = bigString + sizeof bigString;
 
char* p = memccpy(bigString, "John, ", 0, sizeof bigString);
if (p) p = memccpy(p - 1, "Paul, ", 0, end - p);
if (p) p = memccpy(p - 1, "George, ", 0, end - p);
if (p) p = memccpy(p - 1, "Joel ", 0, end - p);
 
puts(bigString); // John, Paul, George, Joel

Example

#include <ctype.h>
#include <stdio.h>
#include <string.h>
 
int main(void)
{
    const char src[] = "Stars: Altair, Sun, Vega.";
    const char terminal[] = {':', ' ', ',', '.', '!'};
    char dest[sizeof src];
    const char alt = '@';
 
    for (size_t i = 0; i != sizeof terminal; ++i) {
 
        void *to = memccpy(dest, src, terminal[i], sizeof dest);
 
        printf("Terminal '%c' (%s):\t\"", terminal[i], to ? "found" : "absent");
 
        // if `terminal` character was not found - print the whole `dest`
        to = to ? to : dest + sizeof dest;
 
        for (char *from = dest; from != to; ++from)
            putchar(isprint(*from) ? *from : alt);
 
        puts("\"");
    }
 
 
    puts("\n" "Separate star names from distances (ly):");
    const char *star_distance[] = {
        "Arcturus : 37", "Vega : 25", "Capella : 43", "Rigel : 860", "Procyon : 11"
    };
    char names_only[64];
    char *first = names_only;
    char *last = names_only + sizeof names_only;
 
    for (size_t t = 0; t != (sizeof star_distance)/(sizeof star_distance[0]); ++t) {
        if (first) {
            first = memccpy(first, star_distance[t], ' ', last - first);
        } else break;
    }
    if (first) {
        *first = '\0';
        puts(names_only);
    } else {
        puts("Buffer is too small.");
    }
}

Output:

Terminal ':' (found):   "Stars:"
Terminal ' ' (found):   "Stars: "
Terminal ',' (found):   "Stars: Altair,"
Terminal '.' (found):   "Stars: Altair, Sun, Vega."
Terminal '!' (absent):  "Stars: Altair, Sun, Vega.@"
 
Separate star names from distances (ly):
Arcturus Vega Capella Rigel Procyon

See also

copies one buffer to another
(function)
copies a certain amount of wide characters between two non-overlapping arrays
(function)
moves one buffer to another
(function)
copies one string to another
(function)
concatenates two strings
(function)