我正在最终确定客户端/服务器程序,其中客户端使用堆栈执行二进制代码。客户端必须能够连接到服务器,然后服务器将继续执行堆栈。为此,我需要将我的堆栈结构发送到服务器。所以我需要首先序列化我的“堆栈”对象,然后反序列化它,但我不擅长那个关闭指针操作。我一直在寻找一个lib,但谷歌的JSON和Prot-c看起来很复杂,所以如果我能得到一些帮助来手动序列化/反序列化那个堆栈,那将非常方便。
我的堆栈基于列表实现:
struct list {
int Element;
list next;
};
struct stack
{
list l;
};
将现有的“堆栈”对象发送到服务器的最简单方法是什么?
感谢名单!
答案 0 :(得分:1)
BSON代替JSON,它比Google协议缓冲区轻,但仍然有点笨重。
可以找到更便宜的替代品here。
next
字段的类型应为list*
而不是list
。否则你有一个循环定义,一个列表不能合理地包含整个其他列表。
另外,就个人品味而言,我会将内部列表节点数据类型node
和列表提示(第一个节点)称为list
。
此外,您需要typedef struct list list
才能在其他结构定义中使用list
或list*
。
示例:
/* this is your list.h file */
/* Forward declaration of `node` allows us to use
* `node` as a datatype in stead of using `struct node`
* everywhere.
*/
typedef struct node node;
/* Creating an alias called `list` for `node` types
* we will only use this when refferring to the first
* node of the list.
*/
typedef node list;
/* A container that will help us carry around multiple
* types of data.
*/
typedef struct any_value any_value;
/* An enum that will be used by the any_value container
* to discern what type of data is currently present.
*/
typedef enum type_flag type_flag;
/* this is your list.c file */
struct node {
/* A void pointer to the value allows us to use
* different types of values.
*/
any_value value;
node* next;
node* prev;
}
enum type_flag {
INTEGER, STRING, SUBLIST
}
struct any_value {
type_flag type;
int length;
void* value;
}
答案 1 :(得分:0)
指定的列表结构是递归定义的。我想你的意思是
typedef struct list list;
struct list {
int element;
list *next
}
在这种情况下,它是一个简单的一维列表。您可以简单地将其展平为int element
数组,并将其重新构建为列表服务器端。
答案 2 :(得分:0)
如果您不需要任何流量优化,您可以将结构使用的内存视为字节数组(它可能非常特定于平台,所以要小心,特别是在客户端和服务器上使用不同的32位和64位体系结构时)。并将其作为简单的字符串发送。
struct to_send{
struct stack _stack;
struct list _list;
};
int send(struct to_send data){
char *string;
string = (char*)malloc(sizeof(struct to_send));
memcpy(string, &data, sizeof(struct to_send));
/* some abstract function which transfers string to client - tx(char *data, int len)*/
tx(string, sizeof(struct to_send));
return 1;
}
/* function that receives string and converts it back to structure */
struct to_send *recv(char *input, int len){
struct to_send *data;
data = (struct to_send*)malloc(sizeof(struct to_send));
memcpy(data, input, len);
return data;
}
另外,为了避免使用指向下一个结构的指针的某些分段错误,最好添加下一个结构的一些id并使用它进行存储和操作。
struct list{
int element;
int list_id;
}
答案 3 :(得分:0)
如果您知道列表的大小,可以分配一个包含列表大小的数组,然后用列表填充数组。
答案 4 :(得分:0)
假设存在push
,如下所示,您可以使用recv_stack
和send_stack
功能,如下所示。错误报告很简陋,但结构很容易改进。
void push(int k, struct stack* s);
#define ERR_SUCCESS 0
#define ERR_PROTOCOL 1
void send_int(FILE* f, int k)
{
fprintf(f, "%d", k);
}
void send_stack(FILE* f, const struct stack* s)
{
int flag = 0;
const struct list* a = &s->l;
fprintf(f, "{ ");
while(a != NULL)
{
send_int(f, a->Element);
a = a->next;
if(flag)
{
fprintf(f, ", ");
}
flag = 1;
}
fprintf(f, " }\n");
}
#define RECV_READ_LBRACE 1
#define RECV_READ_INTEGER 2
#define RECV_CONT_INTEGER 3
#define RECV_FINAL 4
int
recv_stack(FILE* f, struct stack* s)
{
int state = RECV_READ_LBRACE;
int error = ERR_SUCCESS;
int ax = 0;
do {
char c = fgetc(f);
switch(state)
{
case RECV_READ_LBRACE:
if(c == '{')
{
state = RECV_READ_INTEGER;
}
else
{
state = RECV_FINAL;
error = ERR_PROTOCOL;
}
break;
case RECV_READ_INTEGER:
if(isdigit(c))
{
state = RECV_CONT_INTEGER;
ax = c - '0';
}
else if(c != ' ')
{
state = RECV_FINAL;
error = ERR_PROTOCOL;
}
break;
case RECV_CONT_INTEGER:
if(isdigit(c))
{
ax *= 10;
ax += c - '0';
}
else if(c == ',')
{
state = RECV_READ_INTEGER;
push(ax, s);
}
else if(c == '}')
{
state = RECV_FINAL;
push(ax, s);
}
else
{
state = RECV_FINAL;
error = ERR_PROTOCOL;
}
break;
}
} while(state != RECV_FINAL);
return error;
}