C 从二进制文件读取/写入链接节点
我在读取包含链接节点的二进制文件时遇到问题 代码如下: lib1.cC 从二进制文件读取/写入链接节点,c,struct,linked-list,C,Struct,Linked List,我在读取包含链接节点的二进制文件时遇到问题 代码如下: lib1.c struct my_stack_node { void *data; struct my_stack_node *next; }; struct my_stack { int size; struct my_stack_node *first; }; int my_stack_write(struct my_stack *stack, char *filename){ int count = 0; struct my_st
struct my_stack_node {
void *data;
struct my_stack_node *next;
};
struct my_stack {
int size;
struct my_stack_node *first;
};
int my_stack_write(struct my_stack *stack, char *filename){
int count = 0;
struct my_stack_node *aux;
FILE *file = fopen(filename, "wb");
if(stack->first != NULL){
aux = stack->first;
count++;
while(aux->next != NULL){
fwrite(&aux ,sizeof(aux), 1, file);
aux = aux->next;
count++;
}
}
fwrite(&stack, sizeof(stack), 1, file); //Escriure stack
fclose(file);
return count;
}
struct my_stack *my_stack_read(char *filename){
struct my_stack *stackRead;
struct my_stack_node *stackNode;
FILE *file = fopen(filename, "rb");
if(!file){
puts("Impossible obrir el fitxer");
return NULL;
}else{
int primerInici = 0;
while(!feof(file)){
if(primerInici == 0){
stackRead = (struct my_stack*) malloc(sizeof(struct my_stack));
fread(stackRead, sizeof(stackRead), 1, file);
primerInici = 1;
}else{
//Crear nou node i llegir-lo del fitxer
stackNode = (struct my_stack_node*) malloc(sizeof(struct my_stack_node));
fread(stackNode, sizeof(stackNode), 1, file);
//Afegir node a la pila
stackNode->next = stackRead->first;
stackRead->first = stackNode;
}
}
fclose(file);
return stackRead;
}
}
main.c
struct my_data {
int val;
char name[60];
};
int main() {
struct my_stack *s, *t, *u;
struct my_data *data, *data1, *data2;
//...more code
u = my_stack_read("/tmp/my_stack.data");
if (! u) {
puts("Error in my_stack_read (u)");
exit(1);
}
if (my_stack_len(s) != my_stack_len(u)) {
puts("Stacks s and u don't have the same len");
exit(1);
}
// Test we can free the data and compare stacks s and u
while((data1 = my_stack_pop(s))) {
data2 = my_stack_pop(u);
if (! data2 || data1->val != data2->val || my_strcmp(data1->name, data2->name)) {
printf("Data in s and u are not the same: %d <> %d\n", data1->val, data2->val);
exit(1);
}
free(data1);
free(data2);
}
//...more code
puts("All tests passed");
return 0;
}
struct my_数据{
int-val;
字符名[60];
};
int main(){
结构my_堆栈*s,*t,*u;
结构my_data*data、*data1、*data2;
//…更多代码
u=my_stack_read(“/tmp/my_stack.data”);
如果(!u){
puts(“我的_堆栈中的错误_读取(u)”;
出口(1);
}
如果(my_stack_len(s)!=my_stack_len(u)){
看跌期权(“s和u没有相同的len”);
出口(1);
}
//测试我们可以释放数据并比较堆栈s和u
而((data1=my_stack_pop){
数据2=我的堆栈弹出(u);
如果(!data2 | | data1->val!=data2->val | | my|u strcmp(data1->name,data2->name)){
printf(“s和u中的数据不相同:%d%d\n”,数据1->val,数据2->val);
出口(1);
}
免费(数据1);
免费(数据2);
}
//…更多代码
看跌期权(“所有测试通过”);
返回0;
}
执行的结果是:
堆栈长度:100
s和u中的数据不相同:22145808 22134800
正确的结果应该是:
所有通过的测试都存在问题(在我的\u堆栈\u写入中):
您正在写入指针aux
。不是由aux
指向的结构。无论是数据
所指的数据,它都是重要的部分
所以。想象你有这样的东西:
my_stack { first=0x100 }
at memoryPosition 0x100 we have : my_stack_node { data=0x200; next=0x300 }
at memoryPosition 0x300 we have : my_stack_node { data=0x500; next=0x600 }
at memoryPosition 0x600 we have : my_stack_node { data=0x700; next=NULL }
对于该结构,您的程序正在写入:0x100、0x300您正在写入构成链接列表的节点的内存地址。您缺少最后一个节点,这是另一种错误。
但这是没有用的。下次运行程序时,节点可能位于不同的内存地址中,因此保存它们没有意义。它是动态内存,每次运行程序时,它可能位于不同的位置 你应该写的是你的链表上列出的数据 同样的错误几乎在整个程序中重复 如何正确写入链表中包含的数据:
void writeStack(struct my_stack *stack, const char *filename)
{
struct my_stack_node *aux;
FILE *file = fopen(filename, "wb");
if ( file==NULL )
{
fprintf( stderr, "Could not open %s for writting.\n", filename );
exit(1);
}
if (stack != NULL)
{
aux = stack->first;
while(aux != NULL)
{
// aux->data is of type void*
// Assuming that aux->data contains a struct my_data
// Most likely it would be better to redefine data as having
// type struct my_data*
fwrite(aux->data ,sizeof(struct my_data), 1, file);
aux = aux->next;
}
}
fclose(file);
}
这里我们遍历列表中的所有节点。对于每一个,我们都将包含的数据写入其中。
注意
fwrite(aux->data,
如何写入aux->data
所指向的数据,这是正确的。而
fwrite(&aux,
将写入aux
中包含的内存地址,这不太可能是正确的。而
fwrite(&aux->data,
将写入aux->data
中包含的内存地址,这也不太可能是正确的
由您添加计数代码并编写读取函数。您只读取和写入堆栈本身,而不是其节点的有效负载,它存储在voa
void*
指针中
节点本身不携带有意义的信息。或者跨会话有意义的信息,而是:data
和next
指针仅在写入数据的会话中有效
堆栈本质上是一个线性数据结构。不存储节点,而是将堆栈数据存储为数据
成员数组。当您读入它们时,用新分配的节点和读取的数据
字段构建一个列表
堆栈使用void*
指针来允许各种数据类型。因此,必须找到一种方法来告诉读写方法如何写入或读取数据
您可以提供一个回调函数,在其中传递打开的文件。如果需要,这种回调可以处理复杂的数据结构,如负载
编辑:下面的代码演示了如何使用自定义函数序列化堆栈以进行读写。对称回调应将数据写入文件并读取数据。读取函数可分配堆栈拥有的内存。用户必须确保释放内存
回调可以返回负数以指示错误。要读取的堆栈不必为空。读取数据只是被推送到堆栈中
#include <stdlib.h>
#include <stdio.h>
#define die(...) exit((printf(__VA_ARGS__), putchar('\n'), 1));
typedef struct Stack Stack;
typedef struct SNode SNode;
struct SNode {
void *data;
SNode *next;
};
struct Stack {
SNode *head;
};
/*
* Core stack functions
*/
void stack_push(Stack *st, void *data)
{
SNode *sn = malloc(sizeof(*sn));
sn->data = data;
sn->next = st->head;
st->head = sn;
}
void *stack_pop(Stack *st)
{
void *data;
SNode *sn;
if (st->head == NULL) die("Undeflow");
sn = st->head;
data = sn->data;
st->head = sn->next;
free(sn);
return data;
}
int stack_empty(const Stack *st)
{
return (st->head == NULL);
}
/*
* Stack write function with custom callback
*/
int stack_write(const Stack *st, const char *filename,
int (*func)(FILE *f, const void *data))
{
const SNode *sn = st->head;
size_t count = 0;
FILE *f = fopen(filename, "wb");
if (f == NULL) return -1;
fwrite(&count, 1, sizeof(count), f);
while (sn) {
if (func(f, sn->data) < 0) {
fclose(f);
return -1;
}
count++;
sn = sn->next;
}
fseek(f, SEEK_SET, 0);
fwrite(&count, 1, sizeof(count), f);
fclose(f);
return count;
}
/*
* Stack read function with custom callback
*/
int stack_read(Stack *st, const char *filename,
int (*func)(FILE *f, void **data))
{
size_t count = 0;
size_t i;
FILE *f = fopen(filename, "rb");
if (f == NULL) return -1;
fread(&count, 1, sizeof(count), f);
for (i = 0; i < count; i++) {
void *p;
if (func(f, &p) < 0) {
fclose(f);
return -1;
}
stack_push(st, p);
}
fclose(f);
return count;
}
/*
* Custom data struct with read/write functions
*/
struct my_data {
int val;
char name[60];
};
int my_data_write(FILE *f, const void *data)
{
if (fwrite(data, sizeof(struct my_data), 1, f) < 1) return -1;
return 0;
}
int my_data_read(FILE *f, void **data)
{
*data = malloc(sizeof(struct my_data));
if (*data == NULL) return -1;
if (fread(*data, sizeof(struct my_data), 1, f) < 1) {
free(data);
return -1;
}
return 0;
}
/*
* Example client code
*/
int main()
{
Stack s = {NULL};
Stack t = {NULL};
struct my_data aa = {23, "Alice Atkinson"};
struct my_data bb = {37, "Bob Bates"};
struct my_data cc = {28, "Carol Clark"};
stack_push(&s, &aa);
stack_push(&s, &bb);
stack_push(&s, &cc);
stack_write(&s, "kk", my_data_write);
while (s.head) stack_pop(&s);
stack_read(&t, "kk", my_data_read);
while (t.head) {
struct my_data *p = stack_pop(&t);
printf("%4d '%s'\n", p->val, p->name);
free(p);
}
return 0;
}
#包括
#包括
#定义die(…)exit((printf(_VA_ARGS),putchar('\n'),1));
typedef结构堆栈;
typedef结构SNode SNode;
结构势垒{
作废*数据;
斯诺德*下一个;
};
结构堆栈{
斯诺德*头;
};
/*
*核心堆栈函数
*/
无效堆栈推送(堆栈*st,无效*数据)
{
SNode*sn=malloc(sizeof(*sn));
序列号->数据=数据;
sn->next=st->head;
st->head=sn;
}
void*stack_pop(stack*st)
{
作废*数据;
SNode*sn;
如果(st->head==NULL)模具(“未流动”);
sn=st->head;
数据=序列号->数据;
st->head=sn->next;
免费(sn);
返回数据;
}
int stack_empty(常量堆栈*st)
{
返回(st->head==NULL);
}
/*
*具有自定义回调的堆栈写入函数
*/
int stack_write(常量stack*st,常量char*filename,
int(*func)(文件*f,常量void*data))
{
const SNode*sn=st->head;
大小\u t计数=0;
文件*f=fopen(文件名,“wb”);
如果(f==NULL)返回-1;
fwrite(&count,1,sizeof(count),f);
while(sn){
if(函数(f,序号->数据)<0){
fclose(f);
返回-1;
}
计数++;
sn=sn->next;
}
fseek(f,SEEK_集,0);
fwrite(&count,1,sizeof(count),f);
fclose(f);
返回计数;
}
/*
*具有自定义回调的堆栈读取函数
*/
int stack_read(stack*st,const char*filename,
int(*func)(文件*f,无效**数据))
{
大小\u t计数=0;
尺寸i;
FILE*f=fopen(文件名为“rb”);
如果(f==NULL)返回-1;
fread(&count,1,sizeof(count),f);
对于(i=0;i#include <stdlib.h>
#include <stdio.h>
#define die(...) exit((printf(__VA_ARGS__), putchar('\n'), 1));
typedef struct Stack Stack;
typedef struct SNode SNode;
struct SNode {
void *data;
SNode *next;
};
struct Stack {
SNode *head;
};
/*
* Core stack functions
*/
void stack_push(Stack *st, void *data)
{
SNode *sn = malloc(sizeof(*sn));
sn->data = data;
sn->next = st->head;
st->head = sn;
}
void *stack_pop(Stack *st)
{
void *data;
SNode *sn;
if (st->head == NULL) die("Undeflow");
sn = st->head;
data = sn->data;
st->head = sn->next;
free(sn);
return data;
}
int stack_empty(const Stack *st)
{
return (st->head == NULL);
}
/*
* Stack write function with custom callback
*/
int stack_write(const Stack *st, const char *filename,
int (*func)(FILE *f, const void *data))
{
const SNode *sn = st->head;
size_t count = 0;
FILE *f = fopen(filename, "wb");
if (f == NULL) return -1;
fwrite(&count, 1, sizeof(count), f);
while (sn) {
if (func(f, sn->data) < 0) {
fclose(f);
return -1;
}
count++;
sn = sn->next;
}
fseek(f, SEEK_SET, 0);
fwrite(&count, 1, sizeof(count), f);
fclose(f);
return count;
}
/*
* Stack read function with custom callback
*/
int stack_read(Stack *st, const char *filename,
int (*func)(FILE *f, void **data))
{
size_t count = 0;
size_t i;
FILE *f = fopen(filename, "rb");
if (f == NULL) return -1;
fread(&count, 1, sizeof(count), f);
for (i = 0; i < count; i++) {
void *p;
if (func(f, &p) < 0) {
fclose(f);
return -1;
}
stack_push(st, p);
}
fclose(f);
return count;
}
/*
* Custom data struct with read/write functions
*/
struct my_data {
int val;
char name[60];
};
int my_data_write(FILE *f, const void *data)
{
if (fwrite(data, sizeof(struct my_data), 1, f) < 1) return -1;
return 0;
}
int my_data_read(FILE *f, void **data)
{
*data = malloc(sizeof(struct my_data));
if (*data == NULL) return -1;
if (fread(*data, sizeof(struct my_data), 1, f) < 1) {
free(data);
return -1;
}
return 0;
}
/*
* Example client code
*/
int main()
{
Stack s = {NULL};
Stack t = {NULL};
struct my_data aa = {23, "Alice Atkinson"};
struct my_data bb = {37, "Bob Bates"};
struct my_data cc = {28, "Carol Clark"};
stack_push(&s, &aa);
stack_push(&s, &bb);
stack_push(&s, &cc);
stack_write(&s, "kk", my_data_write);
while (s.head) stack_pop(&s);
stack_read(&t, "kk", my_data_read);
while (t.head) {
struct my_data *p = stack_pop(&t);
printf("%4d '%s'\n", p->val, p->name);
free(p);
}
return 0;
}