2
char data_[4096];
...
socket_.async_read_some(boost::asio::buffer(data_, 4096),
    boost::bind(&client::handle_read_header, this,
    boost::asio::placeholders::error,
    boost::asio::placeholders::bytes_transferred));

当函数handle_read_header被触发时,文本data_中包含许多\0符号。通过哪种方式更容易查看完整的(剥离或转义\0的)字符串std::cout?(默认情况下 \0 使字符串结束并且不显示其他)

4

4 回答 4

6

Seth 好心地指出了您的要求,以使其“更易于查看”。为了那个原因:

for (size_t i = 0; i < num_bytes; ++i)
    if (buffer[i] == '\\')
        std::cout << "\\\\";
    else if (isprint(buffer[i]))
        std::cout << buffer[i];
    else
        std::cout << '\\' << std::fill(0) << std::setw(3) << buffer[i];

以上使用 3 位反斜杠转义八进制表示法来表示不可打印字符。您可以很容易地更改表示。

(对于简单的二进制写入,您可以调用std::cout.write(buffer, num_bytes)执行二进制块写入,而不是std::cout << buffer依赖于字符数组/指针的 ASCIIZ 约定。然后您可以将结果通过管道传输到lesscat -vt或者您的操作系统提供的任何有助于查看二进制数据的内容,包括NUL。)

于 2012-05-01T16:06:28.763 回答
4
std::transform( data_, data_+size, std::ostream_iterator<char>(std::cout)
              , [](char c) { c == 0 ? '*':c; });

当然,您可以选择除“*”之外的任何内容。如果您不能使用当前的 C++ 工具,那么只需创建一个执行上述 lambda 功能的函数。

于 2012-05-01T16:07:19.513 回答
1

以下是去除字符的三个选项(如您所问),具体取决于您是否需要保持data_完整,或者您是否只是想要一种快速简便的方法来输出字符。此外,最后一个选项显示了一种将不同(单个)字符替换为空字符的简单方法。如果您支持 C++11,所有这些都可以实现为 lambda,从而使代码更加简洁。

#include <string>
#include <iostream>
#include <algorithm>
#include <iterator>
using namespace std;


int main()
{
   char c[] = "Ch\0ad\0's Answ\0\0\0er.";
   std::string data(c, c+19);

   std::string c1;

   struct is_null
   {
      bool operator()(const char c) const
      {
         return c == '\0';
      }
   };

   // if you need to keep data_ intact (copy)
   std::remove_copy_if(
      data.begin(),
      data.end(),
      std::back_inserter(c1),
      is_null());

   std::cout << c1 << "\n";

   // if you don't need to keep data intact, remove inline
   std::string::iterator nend = std::remove_if(
      data.begin(),
      data.end(),
      is_null());

   data.erase(nend, data.end());

   std::cout << data << "\n";

   // simplest approach, just stream out each byte and skip the null characters
   for(int x = 0; x < 19; ++x)
   {
      if(c[x] != '\0')
         cout << c[x];
   }

   cout << "\n";

   // If you want to decorate the null characters instead
   std::string data2(c, c+19);

   std::replace_if(
      data2.begin(),
      data2.end(),
      is_null(),
      '#'); // <--- this is the character that will replace the nulls

   cout << data2 << "\n";
}
于 2012-05-01T16:15:35.967 回答
0

cout.write您可以通过使用并指定要写入的字符串多长时间(应该在读取处理程序中知道)在终端上输出数据“原始”(不替换 \0 )。

否则,您可以在单独的缓冲区中创建数据的转义副本,如下所示:

char data_[4096];
char escaped[sizeof(data_)*2];
size_t dataLength=...;
char *readPtr=data_, *writePtr=escaped;
for( ; readPtr<data_+dataLength; readPtr++, writePtr++)
{
    switch(*readPtr)
    {
        case 0:
            *writePtr='\\';
            *++writePtr='0';
            break;
        case '\\':
            *writePtr='\\';
            *++writePtr='\\';
            break;
        default:
            *writePtr=*readPtr;
    }
}

或在写作时“即时”替换它(但它可能更慢)。

于 2012-05-01T16:06:38.810 回答