Как напечатать строку с внедренными нулями, чтобы вместо "\ 0" подставлялось "(null)"

У меня есть строка, которую я написал, используя memcpy (), которая (при расширении) выглядит следующим образом:

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

Я хотел бы напечатать каждый символ в строке, и если символ нулевой, распечатать "(null)" в качестве замены для \0.

Если я использую такую ​​функцию, как put () или printf (), она просто завершится с первым нулем и выведет

AAAA

Итак, как я могу заставить его распечатать фактическое слово "(null)", не интерпретируя его как конец строки?

4 ответа

Решение

Вы должны сделать это самостоятельно. Если хотите, то это так. В C строки заканчиваются нулем. Итак, если вы используете форматированную функцию вывода, такую ​​как printf или же puts и попросить его напечатать строку (через спецификатор формата %s) это остановит печать str как только он достигнет первого нуля. Здесь нет null слово на C. Если вы точно знаете, сколько символов у вас в 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, так и на лязг.

Обратите внимание, что стандарт не требует этого:

s Если модификатор длины l отсутствует, аргумент должен быть указателем на начальный элемент массива символьного типа.280) Символы из массива записываются до (но не включая) завершающего нулевого символа. Если указана точность, записывается не более того количества байтов. Если точность не указана или превышает размер массива, массив должен содержать нулевой символ.

Полагаться на такое поведение может привести к неожиданностям!

Один из ключевых краеугольных камней языка C - строки, оканчивающиеся на '\0'. Каждый живет по этому правилу. поэтому я предлагаю вам не думать о вашей строке как о строке, а как о массиве символов.

Если вы пересекаете массив и проверяете "\ 0", вы можете вывести "(null)" вместо символа. Вот пример. Пожалуйста, обратите внимание, ваш char * str был создан либо как массив символов или в стеке, используя 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");

Вместо того, чтобы печатать строку с %s вам придется придумать for цикл, который проверяет условие, является ли данный символ в вашем массиве символов \0 а затем распечатать NULL

Из C++ Ссылка на put () (выделено мое):

Записывает строку C, указанную str, в stdout и добавляет символ новой строки ('\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]);
  }
}    
Другие вопросы по тегам