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使字符串结束,不显示其他字符串)
答案 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约定。然后你可以管道结果进入less
,cat -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;
}
}
或在写作时“动态”替换它(但它可能更慢)。