输出一个带有空值的缓冲区
printf a buffer with nulls
是否有一些花哨的printf语法在打印字符串时忽略null ?
示例用例:打印一个包含一堆以空结束的字符串的网络数据包。
我用来说明这个问题的测试代码:
#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);
}
printf
假定字符串为c样式(即以空字符结尾)。您需要执行以下操作之一:
write
方法(c++风格)
2)使用write
命令(来自unistd.h
, C样式)
3)遍历每个字符并输出
当我调试数据包时,通常我会使用%02hhx
格式打印出每个字符,以确保我看到确切的代码(没有任何关于将空字符打印到屏幕上的怪癖)
没有办法告诉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
但更好的是
你可以使用std::ostream
的write
,因为你毕竟在使用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);
没有想到什么,那么为什么不使用fwrite()呢?如果您知道缓冲区内容的格式,则此操作可以正常工作。
fwrite(buffer, size, 1, stdout);
如果需要进一步格式化输出,可以在调用fwrite()之前和之后使用printf()。
我没有引用典型的c++ iostreams,因为我得到的印象是你更喜欢标准C中的东西。
首先,您的memcpy
操作各复制6个字节,因为"hello"
和"world"
都是char[6]
,结果是h|e|l|l|o| |w|o|r|l|d|
。这就是为什么不使用memcpy
复制字符串,而是使用巧妙命名的strcpy
。
下一个,"你将如何打印网络数据包"?我有一个实用函数hexdump
,它以16行为单位打印任意内存,也许你会发现它很有用:
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, "==> ");
您想忽略空值,还是以某种可见的形式打印它们?
假设是后者,并借用@Seth的代码:
void printbuf(const char* buffer, int len) {
for (int i = 0; i < len; ++i)
if (buffer[i] == ' ') {
cout << "\0";
}
else
cout << buffer[i];
}
}
}
如果您使用的是C而不是c++,请替换cout << ...
- 使用 const char* 键映射 C++ 检索空值
- 返回空值的字符串值
- boost::any 如何检查空值/未定义的值
- C++ - 无法从基类继承 |提供空值
- C++空值和此指针
- 使用 cin 或 getline() 输入空值
- 可变参数列表是否以空值终止?
- 如何将整数重新初始化/设置为空值
- 检查构造函数的空值
- 无法从Linux,C ++执行"my_script" python脚本"main(filename)"功能;pModule = PyImport_Import(pName);返回空值
- 使用Nlohmann JSON将JSON数据保存在文件中时获取空值
- 在命名空间中定义变量,但在测试中获取空值
- 将 char* 推送到矢量时出现问题,但在每次迭代后,它会将指向相同值缓冲区的指针添加到矢量中
- 安全操作以清除C++中的空输入缓冲区
- 将 CURL 转换为字符串时为空值
- QCharts - 在 QLineSeries 中创建一个中断(空值)
- 动态强制转换返回空值
- SDL 表面返回空值
- ptrA = ptrB 是否等同于 ptrA = &*ptrB?,空值是否共享一个地址空间?
- C++-缓冲区组合添加额外的空值