我正在尝试将2D可变长度c字符串数组存储到结构中,以便可以通过网络套接字传输和重建它。
计划是在数据包的标题中包含行和列,以帮助我阅读后面的可变大小镜头和arr。我相信我必须在语法上错误地编写指针,否则将它们设置为struct时需要使用某种aux指针。
struct STORAGE {
int rows; // hdr
int cols; // hdr
int** lens;
const char*** arr;
}
// code
int rows = 11;
int cols = 2;
int lens[rows][cols];
const char* arr[rows][cols];
// ... fill with strings ...
// ... along with lens ...
STORAGE store;
store.rows = rows;
store.cols = cols;
store.lens = lens;
store.arr = arr;
编译此代码时出现这些错误:
错误:从
int
到int**
的无效转换[-fpermissive]错误:分配中无法将
const char* [11][2]
转换为“ const char ***”
我主要来自Java背景,但我确实了解指针如何工作等等。对于有我背景的人(主要是java / c ++和更少的c语言)来说,这一句的语法有点偏。有什么建议吗?
注意:之所以我不使用更复杂的类型(例如字符串,映射,向量等),是因为我需要通过网络传输结构(即,如果指针的大小可变,则指向堆的指针将无法工作) )。除非有人可以提供更好的解决方案,否则它必须是低级数组。
答案 0 :(得分:2)
除非有人可以提供更好的解决方案,否则它必须是低级数组。
一维std::vector<int>
或std::vector<uint8_t>
已经为您提供了一个使用std::vector::data()
成员连续分配的低级数组。
您需要的其他任何尺寸都可以通过适当地分割数据来确定。对于网络传输,您需要预先提供必要的分区尺寸,然后再发送数据。
类似的东西:
Transmit num_of_dimensions
Transmit dim_size_1, dim_size_2, dim_size_3, ...
Transmit data
Receive num_of_dimensions
Loop Receiving dimension sizes
Receive dim_size_1 * dim_size_2 * dim_size_3 * ... of data
我可能要处理的情况是一个看起来像这样的类/结构:
template<typename T>
class MultiDimensional {
size_t num_dimensions_; // If known in advance can be made a template parameter also
std::vector<size_t> dimension_sizes_;
std::vector<T> data_;
public:
const T& indexing_accessor(...) const;
T& indexing_accessor(...);
std::vector<uint8_t> render_transmision_data();
// construct from transmission data
MultiDimensional(std::vector<uint8_t>& transmission_data);
};
答案 1 :(得分:0)
使用诸如数组之类的低级东西不会对您有太大帮助,因为它已经太复杂了。此外,它还会使您陷入兼容性问题的困境(例如考虑字节顺序)。
除非您有非常严格的性能限制,否则请使用专门为联网设计的解决方案:protocol buffers。对于您的情况来说,这有点过头了,但是如果您需要添加任何内容,它可以很好地扩展。
要使用协议缓冲区,请先在.proto
文件中定义“消息”(结构),然后使用Proto编译器将它们编译为C ++。
您可以这样定义您的消息(这是一个完整的.proto
文件):
syntax = "proto2";
package test;
message Storage {
message Row {
repeated string foo = 1;
}
repeated Row row = 1;
}
没有直接支持2D数组的方法,但是数组的数组就可以了(repeated
意味着给定字段中可以有多个值,它基本上是一个向量)。如果需要快速访问它们,可以添加用于数组大小的字段,但是在大多数实际情况下,检查重复字段的大小就足够了。
获得的是一类具有所需所有字段,负责内存管理并具有a bunch of methods to serialize and deserialize的类。
由于需要使用getter和setter,因此C ++代码的使用时间会更长一些,但是您无需考虑序列化这一事实就可以很好地抵消它-它本身就可以发生。
在C ++中使用此东西的示例可能看起来像这样:
#include "test.pb.h" // Generated from test.proto
using ::test::Storage;
int main() {
Storage s;
Storage::Row* row1 = s.add_row();
row1->add_foo("foo 0,0");
row1->add_foo("foo 0,1");
Storage::Row* row2 = s.add_row();
row2->add_foo("foo 1,0");
row2->add_foo("foo 1,1");
assert(s.row_size() == 2);
assert(s.row(0).foo_size() == 2);
s.PrintDebugString(); // prints to stdout
}
在结果中,您将获得以下输出(请注意,这是调试输出,而不是实际的序列化):
row {
foo: "foo 0,0"
foo: "foo 0,1"
}
row {
foo: "foo 1,0"
foo: "foo 1,1"
}
出于完整性考虑:在上面的示例中,源文件为test.proto
和test.cpp
,使用以下文件进行编译:
protoc --cpp_out=. test.proto
g++ test.cpp test.pb.cc -o test -lprotobuf