printf with%s包含空字符

aus*_*tin 11 c string printf

我需要连接一些字符串,我需要包含NULL字节.我不想将'\ 0'视为终止字节.我想保存我宝贵的NULL字节!

在代码示例中,如果

    char *a = "\0hey\0\0";
Run Code Online (Sandbox Code Playgroud)

我需要以输出"\ 0hey\0\0"的格式printf.

-AUstin

sje*_*397 12

怎么样:

int i;
for(i = 0; i < 4; i++)
    printf("%c", a[i]);
Run Code Online (Sandbox Code Playgroud)

如果您希望%s在格式字符串中指定"printf-like"函数时使用此函数,则可以在自己的函数中包含上述代码.但正如@Neil所提到的,你将很难找到寻找空字节来确定字符串长度的替代方法.为此,我猜你可以使用某种逃避角色.

  • 为什么需要大量代码?这对于循环来说是微不足道的?很难看到替代品. (2认同)
  • 我建议使用putchar()而不是printf().字符不需要格式化,因此putchar()效率更高. (2认同)

Mat*_*y K 7

这里的问题是字符串的长度a不容易确定.例如,你的代码..

char *a = "\0hey\0\0";
Run Code Online (Sandbox Code Playgroud)

..为字符串分配七个字节,最后一个是NULL终止符.使用函数strlen会返回0.

如果您知道字符串的精确长度,那么您可以编写或迭代字节:

#ifdef ESCAPE_NULLS
    int i;
    for (i = 0; i <= 6; i++)
        if (a[i] == 0)
            printf("\\0");
        else
            printf("%c", a[i]);
#else
    write(1, a, 6);
#endif
Run Code Online (Sandbox Code Playgroud)

但你必须知道6.

另一种方法是不使用以NULL结尾的字符串,而是为您的字节实现替代存储机制; 例如,长度编码的数组.

#include <stdio.h>

typedef struct {
    int length;
    char *bytes;
} bytearr;

void my_printf(bytearr *arr)
{
    #ifdef ESCAPE_NULLS
        int i;
        for (i = 0; i <= arr->length; i++)
            if (arr->bytes[i] == 0)
                printf("\\0");
            else
                printf("%c", arr->bytes[i]);
    #else
        write(1, arr->bytes, arr->length);
    #endif
}

void main(void)
{
    bytearr foo = {
        6, "\0hey\0\0"
    };
    my_printf(&foo);
}
Run Code Online (Sandbox Code Playgroud)

没有优雅,但希望你能得到这个想法.

编辑:2011-05-31

重读这个问题我刚注意到"连接"这个词.如果要将NULL字符忠实地从内存中的一个位置复制到另一个位置(不是反斜杠转义),并且您事先知道每个数组中的总字节数,那么您可以简单地使用memcpy.

#include <string.h>
char *a = "\0hey\0\0";   /*  6 */
char *b = "word\0up yo"; /* 10 */
char *c = "\0\0\0\0";    /*  4 */
void main(void)
{
    char z[20];
    char *zp = z;
    zp = memcpy(zp, a, 6);
    zp = memcpy(zp, b, 10);
    zp = memcpy(zp, c, 4);
    /* now z contains all 20 bytes, including 8 NULLs */
}
Run Code Online (Sandbox Code Playgroud)

  • 不要将 POSIX `write()` 与 stdio `printf` 混合使用。使用`fwrite`。并且不要对单个字节使用 `printf("%c"`,使用 `putchar`!或者更好的是,搜索下一个 `0` 并使用一个函数调用对所有非零字节使用 `fwrite`。或者复制并转义到本地缓冲区并对其进行写入。顺便说一句,`memcpy` 不是 `strcat`:`memcpy` 返回其第一个未修改的参数,而不是它写入的 *end*。所以你的更新反复覆盖`z` 的开始。但是,如果你使用正确的目标指针,memcpy 是适合这项工作的工具。 (2认同)