我有一个使用 memcpy() 组成的字符串(扩展时)如下所示:
char* str = "AAAA\x00\x00\x00...\x11\x11\x11\x11\x00\x00...";
我想打印字符串中的每个字符,如果该字符为空,则打印出来"(null)"
以替代“\0”。
如果我使用 puts() 或 printf() 之类的函数,它只会在第一个 null 处结束并打印出来
AAAA
那么我怎样才能让它打印出实际的单词“(null)”而不将它解释为字符串的结尾呢?
您必须自己进行映射。如果你愿意,那就是。在 C 中,字符串以空值结尾。因此,如果您使用诸如printf
or之类的格式化输出函数puts
并要求它打印一个字符串(通过格式说明符),它会在遇到第一个空值时立即%s
停止打印。str
C中没有null
单词。如果你确切地知道你有多少个字符,str
你不妨遍历它们并单独打印出这些字符,0
用你选择的助记符代替。
草案说 7.21.6.1/8:
p参数应该是一个指向 void 的指针。指针的值以实现定义的方式转换为打印字符序列。
但是,以下内容:
$ cat null.c
#include <stdio.h>
int main() {
printf("%p\n", (void *)0);
}
产生:
00000000
在 gcc 4.6 和 clang 3.2 上。
然而,深入挖掘:
$ cat null.c
#include <stdio.h>
int main() {
printf("%s\n", (void *)0);
}
确实产生了所需的输出:
(null)
在 gcc 和 clang 上。
请注意,该标准不强制要求:
s如果不存在 l 长度修饰符,则参数应是指向字符类型数组的初始元素的指针。280) 数组中的字符被写入(但不包括)终止空字符。如果指定了精度,则写入的字节数不会超过这个数。如果未指定精度或大于数组的大小,则数组应包含空字符。
依靠这种行为可能会导致意外!
而不是用 打印字符串%s
,您必须想出一个for
循环来检查 char 数组中的给定字符是否为 a 的条件\0
,然后打印NULL
来自puts() 上的 C++ 参考(强调我的):
将 str 指向的 C 字符串写入标准输出并附加换行符 ('\n')。该函数从指定的地址 (str) 开始复制,直到到达终止空字符 ('\0')。这个最终的空字符不会复制到标准输出。
要处理您拥有的数据,您需要知道长度。从那里,您可以简单地遍历字符:
/* ugly example */
char* str = "AAAA\x00\x00\x00...\x11\x11\x11\x11\x00\x00...";
int len = ...; /* get the len somehow or know ahead of time */
for(int i = 0; i < len; ++i) {
if('\0' == str[i]) {
printf(" (null) ");
} else {
printf(" %c ", str[i]);
}
}
C 的关键基石之一是字符串以 '\0' 结尾。每个人都按照这个规则生活。所以我建议您不要将字符串视为字符串,而是将其视为字符数组。
如果您遍历数组并测试“\0”,则可以打印“(null)”来代替字符。这是一个例子。请注意,您char * str
是使用 char 数组或在堆栈上创建的malloc
。此代码需要知道实际的缓冲区大小。
char* str = "AAAA\x00\x00\x00...\x11\x11\x11\x11\x00\x00...";
int iStrSz = <str's actual buffer size>
int idx;
for(idx=0; idx<iStrSz; idx++)
{
if('\0' == *(str + idx)
{
sprintf("%s", "(null)");
}
else
{
putchar(*(str + idx));
}
}
printf("%s", "\n");