在 C 中替换字符串前缀的正确方法

Proper way to replace string prefix in C

我的目标是在不收到任何编译器警告或触发未定义行为的情况下替换字符串中的前 n (3) 个字符:

const char *replacment = "abc";
char buffer[128] = "xxx-remainder";

我正在使用 gcc (GCC) 9.2.0 和标准库:

  1. 使用 sprintf 似乎是在 replacement 中插入 NUL 字符,即使我认为我告诉它不要这样做:

    sprintf(buffer, "%.3s", replacement);
    printf("%s\n", buffer);   /// prints "abc", not "abc-remainder"
    
  2. 使用 strncpy 会引发警告:

    strncpy(buffer, replacement, 3);
    

    这会触发以下警告:

    test.c: In function 'main':
    main.c:8:5: warning: 'strncpy' output truncated before terminating nul copying 3 bytes from a string of the same length [-Wstringop-truncation]
     8 |         strncpy(buffer, replacement, 3);
       |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~
    

    在这种情况下输出看起来很好。

  3. 当然,我可以使用 for 循环手动复制字符,但我正在努力避免这种情况。

如何修复这里显示的任何一种方法,或者哪个替代函数调用可以让我替换前 3 个字符而不向字符串插入 NUL 或收到警告?

memcpy(buffer, replacement, strlen(replacement));

就是您要找的。

另一种(非常混淆)方式:

char c = buffer[strlen(replacement)];
buffer[snprintf(buffer, sizeof buffer, "%s", replacement)] = c;

只需使用 memcpy。

memcpy( buffer, replacement, 3 );

这是一个演示程序。

#include <stdio.h>
#include <string.h>

int main(void) 
{
    const char *replacment = "abc";
    char buffer[128] = "xxx-remainder";
    
    printf( "%s\n", ( char * )memcpy( buffer, replacment, strlen( replacment ) ) );
    
    return 0;
}

程序输出为

abc-remainder

将字符数设为变量使 strncpy 方法在没有警告的情况下工作:

const char *replacment = "abc";
char buffer[128] = "xxx-remainder";

const int n = 3;
strncpy(buffer, replacement, n);

const 限定符是可选的。

显然,该警告是 9.0 版中的错误:https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87028,随后已修复。大概在 9.2 和 10.2 之间。