使用\ 0字符显示字符串中的完整字符串

时间:2012-05-01 16:01:57

标签: c++ std

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 个答案:

答案 0 :(得分: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)的内容。)

答案 1 :(得分:4)

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

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

答案 2 :(得分:1)

根据您是否需要保持data_完好无损,或者您只是想要一种快速简便的方法来流出字符,这里有三个删除字符的选项(如您所知)。此外,最后一个选项显示了一种简单的方法来替换空字符的不同(单个)字符。如果你有C ++ 11支持,所有这些都可以作为lambdas实现,使代码更简洁。

#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";
}

答案 3 :(得分:0)

您可以使用cout.write在终端上输出数据“raw”(不替换\ 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;
    }
}

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