printf буфер с нулями - PullRequest
       12

printf буфер с нулями

2 голосов
/ 25 августа 2011

Есть ли какой-нибудь причудливый синтаксис printf, чтобы игнорировать нули при печати строки?

Пример использования: печать сетевого пакета, который содержит несколько строк с нулевым символом в конце.

Мой тестовый код для иллюстрации проблемы:

#include <cstdio>
#include <cstring>

void main()
{
    char buffer[32];
    const char h[] = "hello";
    const char w[] = "world";
    const int size = sizeof(w) + sizeof(h);

    memcpy(buffer, h, sizeof(h));
    memcpy(buffer + sizeof(h), w, sizeof(w));

    //try printing stuff with printf
    printf("prints only 'hello' [%s]\n",buffer);
    printf("this prints '<bunch of spaces> hello' [%*s]\n",size,buffer);
    printf("and this prints 'hello' [%.*s]\n",size,buffer);

    //hack fixup code
    for(int i = 0; i < size; ++i)
    {
        if(buffer[i] == 0)
            buffer[i] = ' ';
    }
    printf("this prints 'hello world ' [%.*s]\n",size,buffer);
}

Ответы [ 5 ]

5 голосов
/ 25 августа 2011

printf предполагает, что строки выполнены в стиле c (т. Е. Заканчиваются нулевыми символами).Вам необходимо выполнить одно из следующих действий:

1) использовать метод ostream write (стиль C ++)

2) использовать команду write (из unistd.h, Cstyle)

3) итерация по каждому символу и печать.

Когда я отлаживаю пакеты, часто я печатаю каждый символ в формате %02hhx, чтобы убедиться, что вижу точный код(без каких-либо ухищрений по поводу вывода на экран нулевых символов)

1 голос
/ 25 августа 2011

Во-первых, ваши memcpy операции копируют по шесть байтов каждая, поскольку "hello" и "world" равны char[6], а результат равен h|e|l|l|o|\0|w|o|r|l|d|\0. Вот почему вы не копируете строки с memcpy, а с умным именем strcpy.

Далее, "как бы вы печатали сетевые пакеты"? У меня есть служебная функция hexdump, которая печатает произвольную память в шестнадцати строках, может быть, вы найдете ее полезной:

void asciiprint(FILE * out, unsigned char c)
{
  if (c < 32 || c > 126) fprintf(out, ".");
  else fprintf(out, "%c", c);
}

void hexdump(FILE * out, const unsigned char * buf, size_t length, const char * delim)
{
  for (size_t k = 0; 16*k < length; k++)
  {
    fprintf(out, "%s", delim);

    for (int i = 0; i < 16 && 16*k + i < length; ++i)
      fprintf(out, "0x%02X ", buf[16*k + i]);

    if (16*(k+1) > length)
      for (size_t i = 0; i < 16*(k+1)-length; ++i)
        fprintf(out, "     ");

    fprintf(out, "    ");

    for (size_t i = 0; i < 16 && 16*k + i < length; ++i)
      asciiprint(out, buf[16*k + i]);

    fprintf(out, "\n");
  }
}

Использование: hexdump(stdout, (const unsigned char*)buffer, 32, "==> ");

1 голос
/ 25 августа 2011

Ничего не приходит на ум, так почему бы не использовать вместо него fwrite (). Это работает, если вы знаете формат содержимого вашего буфера.

fwrite(buffer, size, 1, stdout);

Если вам требуется дополнительный форматированный вывод, вы можете использовать printf () до и после вызова fwrite ().

Я не отвечаю ссылками на типичные iostreams C ++, потому что у меня сложилось впечатление, что вы предпочитаете что-то в стандартном C.

1 голос
/ 25 августа 2011

Нет способа определить printf длину строки, которую вы хотите напечатать. Вам нужно будет печатать каждый символ отдельно:

void printbuf(const char* buffer, int len) {
    for (int i = 0; i < len; ++i)
        printf("%c", buffer[i]);
}

char buf[] = {'a', 'b', 'c', 0, 'a', 'b', 'c'};
printbuf(buf, 7);

// prints
// abc abc

Вы можете обернуть буфер в string и распечатать его (если вы не возражаете против дублирования), поскольку NULL s не разделяют string s:

char buf[] = {'a', 'b', 'c', 0, 'a', 'b', 'c'};

string strwithnulls(buf, buf + 7); // or as John pointed out, string strwithnulls(buf, 7);
cout << strwithnulls;

// prints
// abc abc

Но еще лучше

вы можете использовать write из std::ostream, потому что вы все-таки используете C ++:

char buf[] = {'a', 'b', 'c', 0, 'a', 'b', 'c'};
cout.write(buf, 7); // best yet

Если вы на самом деле используете C (почему вы пометили его C ++?), Вы можете сделать это:

char buf[] = {'a', 'b', 'c', 0, 'a', 'b', 'c'};
fwrite(buf, 1, 7, stdout);
0 голосов
/ 25 августа 2011

Хотите игнорировать нули или распечатать их в какой-либо видимой форме?

Предполагая последнее и заимствуя @ код Сета:

void printbuf(const char* buffer, int len) {
    for (int i = 0; i < len; ++i)
        if (buffer[i] == '\0') {
             cout << "\\0";
        }
        else
            cout << buffer[i];
        }
    }
}

Замените cout << ..., если вы используете C, а не C ++.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...