2

大家好,很抱歉问,但我可以找到任何合适的解决方案。我正在研究一个文件系统,我将每个文件节点作为键值对保存在 GDBM 数据库中。我有一个具有一些属性的结构,我将其转换为字节数组

结构mystruct:

typedef struct nold{
char* name;
char* surname;
 int age;
}mystruct;

我将其转换为字节数组

dead.name="john";
dead.surname="doe";
dead.age=22;

//copy bytes of the our struct 
char buffer[sizeof(dead)]; 
memcpy(buffer, &dead, sizeof(dead));

为了存储在数据库中,我们使用如下数据结构:

 typedef struct {
         char *dptr;
         int  dsize;
      } datum

我填写基准结构如下:

//create a key datum
char* k="file.txt";
key.dptr=k;
key.dsize=strlen(k)+1;



//create a value datum  here I assign bytes
value.dptr=buffer;
value.dsize = sizeof(dead);

现在我将 GDBM 存储为键值对

然后在另一个文件中,我读取了我存储的数据并尝试将其重新转换为结构

datum result;

//read
result=gdbm_fetch(file,key);

char* bytes=result.dptr;

mystruct* reborn;

reborn=(mystruct*)bytes;


//print from our new struct
printf("%s\n",reborn->name);
printf("%s\n",reborn->surname);
printf("%d\n",reborn->age);

它打印以下内容:

E���D$�$ˈ�k����E��
$�$ˈ�k����E��
22

它设法恢复结构,但 char* 的数据丢失了。仅涵盖整数数据。知道为什么会这样吗?如何解决?它不能通过存储字节数组来解决,如何将字节数组转换为十六进制或 base64 并将其存储。

我真的在努力解决这个问题。提前谢谢你。

4

3 回答 3

2

struct 中的指针只是指向字符数组的指针,而不是字符数组本身:

typedef struct nold{
   char* name;
   char* surname;
   int age;
}mystruct;

mystruct s;
s.name = "Salam";

这将为字符串“Salam”保留一个内存空间,将字符串 Salam 放入并返回指向 s.name 的指针。

现在您正在将整个结构复制到其他结构中,您正在使用 sizeof(mystruct) 从结构地址复制,实际上它不包含字符串“Salam”,它只是包含指向“Salam”的指针。

如果你想这样做,你必须为 name 预先分配一些空间:

#define MAX_NAME_LEN    50
typedef struct nold{
   char name[MAX_NAME_LEN];
   char surname[MAX_NAME_LEN];
   int age;
}mystruct;

mystruct s;
strcpy(s.name, "Salam");

现在 memcpy 可以工作了

mystruct d;
memcpy(&d, &s, sizeof(mystruct);
于 2016-12-15T14:26:24.357 回答
2

指针值仅在特定程序的特定运行的上下文中才有意义。可以将它们写入并读回它们,但必须记住,指针指定一个地址,而不是(直接)驻留该地址的数据,如果该地址对于访问它的程序确实有效的话。您不会通过传递指针在进程之间传递指向的数据。

您也许可以通过将要传达的数据直接放入结构中来解决问题:

typedef struct {
     char data[MAX_DATA_SIZE];
     int  dsize;
} datum;

这种方法的缺点是您必须为数据大小设置一个固定的上限,但在许多情况下这不是问题。如果您需要无限数据,那么您需要一种完全不同的方法。

于 2016-12-15T14:41:25.030 回答
1

问题是 name 和 surname 是指向字符串文字的指针。因此,您的结构不包含字符串本身,而是指向文字所在的数据部分的指针。一旦将其复制到缓冲区,实际上您只是在复制指针值。重建后,这些指针值现在将指向某个不包含您的字符串的任意区域。

编辑:这是一个将数据传输到缓冲区的函数:

size_t copyMyStructToBuffer(mystruct *aPerson, char **buffer) {
    size_t nameLen = strlen(aPerson->name);
    size_t surnameLen = strlen(aPerson->surname);
    size_t structLen = nameLen + 1 + surnameLen + 1 + sizeof(int);
    *buffer = malloc(structLen);

    memcpy(*buffer, aPerson->name, nameLen + 1); // w/ terminator
    memcpy((*buffer)[nameLen+1], aPerson->surname, surnameLen + 1); // w/ terminator
    memcpy((*buffer)[nameLen+1+surnameLen+1], &aPerson->age, sizeof(int));

    return structLen;
}

以及如何使用它:

mystruct dead;
dead.name = "John";
dead.surname = "Doe";
dead.age = 22;
char *buff;
size_t buffLen;
buffLen = copyMyStructToBuffer(&dead, &buff);
// use buff here
free(buff);

诚然,这段代码很难维护。

于 2016-12-15T14:39:12.763 回答