2

我有一个使用 memcpy() 组成的字符串(扩展时)如下所示:

char* str = "AAAA\x00\x00\x00...\x11\x11\x11\x11\x00\x00...";

我想打印字符串中的每个字符,如果该字符为空,则打印出来"(null)"以替代“\0”。

如果我使用 puts() 或 printf() 之类的函数,它只会在第一个 null 处结束并打印出来

AAAA

那么我怎样才能让它打印出实际的单词“(null)”而不将它解释为字符串的结尾呢?

4

4 回答 4

4

您必须自己进行映射。如果你愿意,那就是。在 C 中,字符串以空值结尾。因此,如果您使用诸如printfor之类的格式化输出函数puts并要求它打印一个字符串(通过格式说明符),它会在遇到第一个空值时立即%s停止打印。strC中没有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) 数组中的字符被写入(但不包括)终止空字符。如果指定了精度,则写入的字节数不会超过这个数。如果未指定精度或大于数组的大小,则数组应包含空字符。

依靠这种行为可能会导致意外!

于 2012-05-30T03:44:09.337 回答
0

而不是用 打印字符串%s,您必须想出一个for循环来检查 char 数组中的给定字符是否为 a 的条件\0,然后打印NULL

于 2012-05-30T03:45:02.560 回答
0

来自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]);
  }
}    
于 2012-05-30T03:57:40.490 回答
0

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");
于 2012-05-30T10:51:44.243 回答