7

我正在尝试对向量的数据进行二进制序列化。在下面的这个示例中,我序列化为一个字符串,然后反序列化回一个向量,但没有得到与我开始时相同的数据。为什么会这样?

vector<size_t> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);

string s((char*)(&v[0]), 3 * sizeof(size_t));

vector<size_t> w(3);
strncpy((char*)(&w[0]), s.c_str(), 3 * sizeof(size_t));

for (size_t i = 0; i < w.size(); ++i) {
    cout << w[i] << endl;
}

我希望得到输出

1  
2
3

而是得到输出

1
0
0

(在gcc-4.5.1上)

4

4 回答 4

4

错误在于对 的调用strncpy。从链接页面:

如果src的长度小于n, strncpy() 用空字节填充 dest 的剩余部分。

因此,在0找到序列化数据中的第一个字节后, 's 数据数组的其余部分将w用 s 填充0

要解决此问题,请使用for循环,或std::copy

std::copy( &s[0], 
           &s[0] + v.size() * sizeof(size_t), 
           reinterpret_cast<char *>(w.data()) );

IMO,不是std::string用作缓冲区,而是使用char数组来保存序列化数据。

ideone的例子

于 2012-07-05T23:13:30.493 回答
2

strncpy是一大堆失败。它将在您的输入中提前终止,因为它size_t有一些零字节,它解释为 NULL 终止符,将它们保留为默认构造的 0。如果您在 BE 机器上运行此测试,则全部为 0。使用std::copy.

于 2012-07-05T23:13:49.220 回答
-1

最安全的方法是循环遍历向量并将值单独存储到大小为 3*sizeof(size_t) 的 char 数组中。这样你就不会依赖向量类实现的内部结构。

于 2012-07-05T23:33:57.643 回答
-1

要将这个向量序列化为一个字符串,首先要将这个向量的每个元素从一个 int 转换为一个包含该数字的相同 ascii 表示的字符串,这个操作可以称为从 int 到字符串的序列化。

例如,假设一个整数是 10 位,我们可以

// create temporary string to hold each element
char intAsString[10 + 1];

然后将整数转换为字符串

sprintf(intAsString, "%d", v[0]);

或者

itoa( v[0], intAsString, 10 /*decimal number*/ );

您还可以使用 ostringstream 和 << 运算符

如果你看一下 intAsString 和 v[0] 的内存内容,它们是非常不同的,第一个包含代表十进制数系统(基数 10)中 v[0] 的值的 ascii 字母,而 v[0] 包含数字的二进制表示(因为这是计算机存储数字的方式)。

于 2012-07-05T23:13:53.290 回答