C++ 向字节向量添加字符串或字符数组
我目前正在开发一个类来创建和读取通过网络发送的数据包,到目前为止,我使用的是16位和8位整数(无符号但仍然有效) 现在的问题是,我已经尝试了许多方法来复制它,但不知何故,缓冲区被弄坏了,出现了故障,或者结果是错误的 如果有人能给我举个有效的例子,我将不胜感激 我当前的代码可以在下面看到 谢谢,Xeross 主要的C++ 向字节向量添加字符串或字符数组,c++,sockets,C++,Sockets,我目前正在开发一个类来创建和读取通过网络发送的数据包,到目前为止,我使用的是16位和8位整数(无符号但仍然有效) 现在的问题是,我已经尝试了许多方法来复制它,但不知何故,缓冲区被弄坏了,出现了故障,或者结果是错误的 如果有人能给我举个有效的例子,我将不胜感激 我当前的代码可以在下面看到 谢谢,Xeross 主要的 #包括 #包括 #包括“Packet.h” 使用名称空间std; int main(int argc,字符**argv) { cout由于您正在使用std::vector作为缓冲区,您
#包括
#包括
#包括“Packet.h”
使用名称空间std;
int main(int argc,字符**argv)
{
cout由于您正在使用std::vector作为缓冲区,您也可以让它跟踪写入位置本身,避免手动调整其大小。您还可以通过使用函数模板避免写入add函数的多个重载:
template <class T>
Packet& add(T value) {
std::copy((uint8_t*) &value, ((uint8_t*) &value) + sizeof(T), std::back_inserter(_buffer));
return *this;
}
或者明确地说:
o.write<int>(5);
o.write(5);
要从缓冲区读取,您需要跟踪读取位置:
template <class T>
T read() {
T result;
uint8_t *p = &_buffer[_rpos];
std::copy(p, p + sizeof(T), (uint8_t*) &result);
_rpos += sizeof(T);
return result;
}
模板
T read(){
T结果;
uint8_t*p=&u缓冲区[_RPO];
标准:复制(p,p+sizeof(T),(uint8_T*)和结果);
_rpos+=sizeof(T);
返回结果;
}
您需要显式地传递一个类型参数来读取
int i = o.read<int>();
inti=o.read();
警告:我经常使用这种模式,但由于我是在头脑中输入这种模式,代码中可能会有一些错误
编辑:我刚刚注意到,您希望能够将字符串或其他非POD类型添加到缓冲区。您可以通过模板专门化来实现这一点:
template <>
Packet& add(std::string s) {
add(string.length());
for (size_t i = 0; i < string.length(); ++i)
add(string[i]);
return *this;
}
模板
数据包和添加(标准::字符串s){
添加(string.length());
对于(大小i=0;i
这告诉编译器:如果使用字符串类型调用add,请使用此函数而不是泛型add()函数
要读取字符串,请执行以下操作:
template <>
std::string read<>() {
size_t len = read<size_t>();
std::string s;
while (len--)
s += read<char>();
return s;
}
模板
std::string read(){
尺寸长度=读取();
std::字符串s;
而(len--)
s+=read();
返回s;
}
由于您正在使用std::vector作为缓冲区,您也可以让它跟踪写入位置本身,避免手动调整其大小。您还可以通过使用函数模板避免写入add函数的多个重载:
template <class T>
Packet& add(T value) {
std::copy((uint8_t*) &value, ((uint8_t*) &value) + sizeof(T), std::back_inserter(_buffer));
return *this;
}
或者明确地说:
o.write<int>(5);
o.write(5);
要从缓冲区读取,您需要跟踪读取位置:
template <class T>
T read() {
T result;
uint8_t *p = &_buffer[_rpos];
std::copy(p, p + sizeof(T), (uint8_t*) &result);
_rpos += sizeof(T);
return result;
}
模板
T read(){
T结果;
uint8_t*p=&u缓冲区[_RPO];
标准:复制(p,p+sizeof(T),(uint8_T*)和结果);
_rpos+=sizeof(T);
返回结果;
}
您需要显式地传递一个类型参数来读取
int i = o.read<int>();
inti=o.read();
警告:我经常使用这种模式,但由于我是在头脑中输入这种模式,代码中可能会有一些错误
编辑:我刚刚注意到,您希望能够将字符串或其他非POD类型添加到缓冲区。您可以通过模板专门化来实现这一点:
template <>
Packet& add(std::string s) {
add(string.length());
for (size_t i = 0; i < string.length(); ++i)
add(string[i]);
return *this;
}
模板
数据包和添加(标准::字符串s){
添加(string.length());
对于(大小i=0;i
这告诉编译器:如果使用字符串类型调用add,请使用此函数而不是泛型add()函数
要读取字符串,请执行以下操作:
template <>
std::string read<>() {
size_t len = read<size_t>();
std::string s;
while (len--)
s += read<char>();
return s;
}
模板
std::string read(){
尺寸长度=读取();
std::字符串s;
而(len--)
s+=read();
返回s;
}
您可以使用std::string
作为内部缓冲区,并在添加新元素时使用
因此,添加字符串或常量char*将非常简单
添加/写入uint8可以通过将其强制转换为char、将uint16-写入长度为sizeof(uint16_t)的char*来完成
阅读uint16:
uint16_t read_int16()
{
return ( *(uint16_t*)(m_strBuffer.c_str() + m_nOffset) );
}
您可以使用std::string
作为内部缓冲区,并在添加新元素时使用
因此,添加字符串或常量char*将非常简单
添加/写入uint8可以通过将其强制转换为char、将uint16-写入长度为sizeof(uint16_t)的char*来完成
阅读uint16:
uint16_t read_int16()
{
return ( *(uint16_t*)(m_strBuffer.c_str() + m_nOffset) );
}
当您只添加了四个字节时,您似乎试图从缓冲区中打印出十个字节,因此您正在运行向量的末尾。这可能会导致seg故障
此外,printf正在尝试将字符打印为带有%x的无符号整数。您需要使用静态\u转换(packet.\u buffer[i])
作为参数
风格上:
Packet-Packet=Packet();
可能导致构造两个对象。只需使用Packet-Packet;
通常尽量避免使用受保护的属性(受保护的方法很好),因为它们会减少类的封装。当您只添加了四个字节时,您似乎试图从缓冲区中打印出十个字节,因此您正在运行向量的末尾。这可能会导致seg错误
此外,printf正在尝试将字符打印为带有%x的无符号整数。您需要使用静态\u转换(packet.\u buffer[i])
作为参数
风格上:
Packet-Packet=Packet();
可能导致构造两个对象。只需使用Packet-Packet;
通常尽量避免使用受保护的属性(受保护的方法也可以)因为它们减少了类的封装。您的问题表明追加字符串或字符数组有问题,但我看不到尝试这样做的代码。不要混合使用printf和cout。只使用cout。stdio.h和类似的也不推荐使用。例如,对于每个C头,只需在其前面键入C,然后删除.hJust to m注意:您也可以为add()使用模板方法,并使用sizeof而不是硬编码的类型长度。为了避免代码重复,这是一个强大的启动标志。太棒了。@xeross:它可以用于您的代码设计的任何类型;)换句话说,如果您只想添加基本整数,请保持这种方式,只需替换1和2即可