How to print a string with embedded nulls so that

2020-04-12 10:07发布

I have a string I composed using memcpy() that (when expanded) looks like this:

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

I would like to print every character in the string, and if the character is null, print out "(null)" as a substitute for '\0'.

If I use a function like puts() or printf() it will just end at the first null and print out

AAAA

So how can I get it to print out the actual word "(null)" without it interpreting it as the end of the string?

标签: c printf puts
4条回答
不美不萌又怎样
2楼-- · 2020-04-12 10:18

Instead of printing the string with %s , you will have to come up with a for loop that checks a condition whther a given char in your char array is a \0 and then print the NULL

查看更多
再贱就再见
3楼-- · 2020-04-12 10:29

From C++ Reference on puts() (emphasis mine):

Writes the C string pointed by str to stdout and appends a newline character ('\n'). The function begins copying from the address specified (str) until it reaches the terminating null character ('\0'). This final null-character is not copied to stdout.

To process data such as you have, you'll need to know the length. From there, you can simply loop across the characters:

/* 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]);
  }
}    
查看更多
smile是对你的礼貌
4楼-- · 2020-04-12 10:30

You have to do that mapping yourself. If you want to, that is. In C, strings are null-terminated. So, if you use a formatted output function such as printf or puts and ask it to print a string (via the format specifier %s) it'd stop printing str as soon as it hits the first null. There is no null word in C. If you know exactly how many characters you have in str you might as well loop over them and print the characters out individually, substituting the 0 by your chosen mnemonic.

The draft says 7.21.6.1/8:

p The argument shall be a pointer to void. The value of the pointer is converted to a sequence of printing characters, in an implementation-defined manner.

However, the following:

$ cat null.c
#include <stdio.h>
int main() {
 printf("%p\n", (void *)0);
}

produces:

00000000

on both gcc 4.6 and clang 3.2.

However, on digging deeper:

$ cat null.c
#include <stdio.h>
int main() {
 printf("%s\n", (void *)0);
}

does indeed produce the desired output:

(null)

on both gcc and clang.

Note that the standard does not mandate this:

s If no l length modifier is present, the argument shall be a pointer to the initial element of an array of character type.280) Characters from the array are written up to (but not including) the terminating null character. If the precision is specified, no more than that many bytes are written. If the precision is not specified or is greater than the size of the array, the array shall contain a null character.

Relying on this behavior may lead to surprises!

查看更多
贼婆χ
5楼-- · 2020-04-12 10:30

One of the key cornerstones of C is strings are terminated by '\0'. Everyone lives by that rule. so I suggest you not think of your string as a string but as an array of characters.

If you traverse the array and test for '\0', you can print "(null)" out in place of the character. Here is an example. Please note, your char * str was created either as a char array or on the stack using malloc. This code needs to know the actual buffer size.

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");
查看更多
登录 后发表回答