2009-10-11 165 views
0

我想要一个固定长度的字符串,就像在Python中存在的struct.pack,但是在C++中。我想到了itoa (i,buffer,2),但问题可能是它的长度取决于平台。有没有办法让它独立于平台?python struct.pack相当于C++

回答

3

如果您正在寻找一个类似于Python的结构包的完整解决方案,那么您可以查看Google's Protocol Buffers Library。使用它将为您处理很多问题(例如,端到端,语言可移植性,跨版本兼容性)。

+0

+1对于链接 – 2009-10-12 10:29:46

1

您需要通过typedef定义精确宽度的整数类型;你以平台特定的方式做到这一点。如果您使用C99,则在<stdint.h>中预定义int16_t。然后,您可以转换为这种类型,并输入变量的内存中表示:

int16_t val = (int16_t) orig_val; 
void *buf = &val; 

注意,您仍然需要处理字节排列顺序。

如果您没有C99,则可以使用编译时或运行时大小测试。对于编译时测试,考虑使用autoconf,它已经计算了各种基本类型的大小,以便您可以在编译时选择一个好的类型。在运行时,只需进行一系列sizeof测试。请注意,这对于运行时来说是不合适的,因为测试总是会以相同的结果出来。作为autoconf的替代方法,您还可以使用编译器/系统标识宏进行编译时测试。

0

C++的办法是使用stringstream

stringstream ss; 
int number=/*your number here*/; 
ss<<number; 

,并让你使用ss.str().c_str()缓冲区。

+0

-1这不给定一个固定长度的字符串 – 2009-10-12 11:43:58

1

这里的一个开始:

typedef std::vector<uint8_t> byte_buffer; 

template <std::size_t N> 
void append_fixed_width(byte_buffer& buf, uintmax_t val) { 
    int shift = ((N - 1) * 8); 
    while (shift >= 0) { 
     uintmax_t mask = (0xff << shift); 
     buf.push_back(uint8_t((val & mask) >> shift)); 
     shift -= 8; 
    } 
} 

template <typename IntType> 
void append_bytes(byte_buffer& buf, IntType val) { 
    append_fixed_width<sizeof(IntType)>(buf, uintmax_t(val)); 
} 

int main() { // usage example 
    byte_buffer bytes; 
    append_bytes(bytes, 1); // appends sizeof(int) bytes 
    append_bytes(bytes, 1ul); // appends sizeof(unsigned long) bytes 
    append_bytes(bytes, 'a'); // appends sizeof(int) bytes :p 
    append_bytes(bytes, char('a')); // appends 1 byte 
    return 0; 
} 

Append_bytes将任何整数类型附加到一个字节缓冲器使用std::vector<uint8_t>表示。数值以big endian字节顺序打包。如果您需要更改此设置,请调整append_fixed_width以不同的顺序遍历值。

这些函数构建一个原始字节缓冲区,所以无论解码谁负责知道里面有什么。 IIRC,这是struct.pack所做的;换句话说,struct.unpack的调用者需要提供相同的格式字符串。你可以写的append_fixed_width变种收拾TLV代替:

template <typename TagType, typename ValueType> 
void append_tlv(byte_buffer& buf, TagType t, ValueType val) { 
    append_fixed_width<sizeof(TagType)>(buf, uintmax_t(t)); 
    append_fixed_width<sizeof(std::size_t)>(buf, uintmax_t(sizeof(ValueType))); 
    append_fixed_width<sizeof(ValueType)>(buf, uintmax_t(val)); 
} 

我将采取认真的看Jeremy's suggestion虽然。我希望在编写我现在所有的二进制包装代码时它已经存在。