memccpy

来自cppreference.com
< c‎ | string‎ | byte
定义于头文件 <string.h>
void *memccpy(void * restrict dest, const void * restrict src, int c, size_t count);
(C23 起)

src 所指向的对象复制字符到 dest 所指向的对象,在满足接下来的任何两个条件之一后停止:

  • 复制了 count 个字符
  • 找到(并复制)了字符 (unsigned char)c

转译 srcdest 对象为 unsigned char 的数组。

若符合任何以下条件则行为未定义:

  • 出现越过 dest 数组结尾的访问
  • 对象重叠(这违反 restrict 契约)
  • destsrc 为非法或空指针值

参数

dest - 指向要复制的对象的指针
src - 指向复制来源对象的指针
c - 终止字符,首先转换成 unsigned char
count - 要复制的字符数

返回值

若找到字符 (unsigned char)cmemccpy 返回 dest(unsigned char)c 后一字符的指针,否则返回空指针。

注解

函数等同于 POSIX memccpy

memccpy(dest, src, 0, count) 表现类似 strncpy(dest, src, count) ,除了前者返回指向被写入缓冲区的末尾的指针,并且不会以零填充目标数组。从而 memccpy 对高效连接多个字符串有用。

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

示例

#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");
 
        // 若找不到 `terminal` 字符 - 打印整个 `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.");
    }
}

输出:

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

参阅

将一个缓冲区复制到另一个
(函数)
在两个不重叠的数组间复制一定数量的宽字符
(函数)
将一个缓冲区移动到另一个
(函数)
复制一个字符串给另一个
(函数)
连接两个字符串
(函数)