显示带有 0 个字符的字符串的完整字符串

show full string from string with chars

本文关键字:字符串 字符 显示      更新时间:2023-10-16
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_ 在文本中包含许多符号。借助哪种方式更容易通过std::cout查看完整(带有剥离或转义)字符串?(默认情况下 \0 使字符串结束,不显示其他)

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) 来执行二进制块写入,而不是依赖于字符数组/指针的 ASCIIZ 约定的std::cout << buffer。 然后,您可以将结果传送到 lesscat -vt 或操作系统提供的任何有助于查看二进制数据(包括 NULL)的内容。

std::transform( data_, data_+size, std::ostream_iterator<char>(std::cout)
              , [](char c) { c == 0 ? '*':c; });

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

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

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

int main()
{
   char c[] = "Chad's Answer.";
   std::string data(c, c+19);
   std::string c1;
   struct is_null
   {
      bool operator()(const char c) const
      {
         return c == '';
      }
   };
   // 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] != '')
         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";
}

您可以使用 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;
    }
}

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