c语言中的链式结构

c语言中的链式结构,c,pointers,memory-management,C,Pointers,Memory Management,我希望实现一个简单的数据结构,比如链表,但我还不需要那么复杂的东西,或者我需要吗 假设我有一本书的数据结构 typedef struct { char* name; size_t number; } book; 我想把这些附加到越来越多的书中,在记忆中应该是这样的 ------------------------ | 0 | 1 | 2 | 3 | ...... ------------------------ 因为我不做任何花哨的事情,除了添加一堆书,从不改变顺序,只在程序

我希望实现一个简单的数据结构,比如链表,但我还不需要那么复杂的东西,或者我需要吗

假设我有一本书的数据结构

typedef struct {
    char* name;
    size_t number;
} book;
我想把这些附加到越来越多的书中,在记忆中应该是这样的

------------------------
| 0 | 1 | 2 | 3 | ......
------------------------
因为我不做任何花哨的事情,除了添加一堆书,从不改变顺序,只在程序结束时释放书,所以我不需要链表的所有功能

我试图用这样的双指针来创建书籍的原始结构

public book** add_bookd(book** books, book* b) {
    static int index = -1;
    int count;
    index++;
    count = index + 1;
    book** books = realloc(books, sizeof(book*)*count);
    books[index] = calloc(1, sizeof(book));
    copy_bookd(books[index], b); //this is just a series of memcopy
                                 //since i have POD data types
   return books;
}
我试过用一个非常简单的字符,但我得到了seg错误

char** double_pointer(char** a, char* b) {
    static int index = -1; int count;
    index++;
    count = index + 1;
    a = realloc(a, sizeof(char*)*count);
    for(int i = 0; i < index; i++) {
        a[i] = calloc(1, sizeof(char));
        a[i] = b;
        printf("%s\n",a[i]);
    }
    return a;
}


char** tmp = calloc(1, sizeof(char*));
for(int i = 0; i < 3; i++) {
    double_pointer(tmp, "a");
    //printf("%s\n",tmp)); //seg faults here
}
试图访问tmp[0]gdb表示无法访问0x0处的内存。

这些行:

book** books = realloc(books, sizeof(book*)*count);
books[index] = calloc(1, sizeof(book));
copy_bookd(books[index], b);
显示出一些问题,特别是缺少错误检查

建议:

book* temp = realloc(*books, sizeof(book*)*count);

if( temp != NULL )
{ // then, realloc successful

    *books = temp;
     (*books)[index] = calloc(1, sizeof(book));
     if( (*books)[index] != NULL )
     { // then, calloc successful
         copy_bookd((*books)[index], b);
     }

     else
     {
         // handle calloc failure
     }
}

else
{
    // handle realloc failure
}
这些线路:

book** books = realloc(books, sizeof(book*)*count);
books[index] = calloc(1, sizeof(book));
copy_bookd(books[index], b);
显示出一些问题,特别是缺少错误检查

建议:

book* temp = realloc(*books, sizeof(book*)*count);

if( temp != NULL )
{ // then, realloc successful

    *books = temp;
     (*books)[index] = calloc(1, sizeof(book));
     if( (*books)[index] != NULL )
     { // then, calloc successful
         copy_bookd((*books)[index], b);
     }

     else
     {
         // handle calloc failure
     }
}

else
{
    // handle realloc failure
}

所以你正在寻找一种可能性来存储一些书,你可能只会添加一些?这确实可以通过一种与您已有的方法非常相似的方法来实现。但让我们从头开始:

基本上,您在内存中的某个位置存储一个书籍“数组”,即在一个连续的内存位置中存储多个
struct book
。可以使用指向第一本书的指针指向该数组:

struct book * books;
不知何故,您还需要知道该数组的结束位置。因此,我看到的两种可能性是要么使用sentinel值(类似于C字符串对
'\0'
的作用),要么只跟踪数组的大小。我会选择后者:

size_t count;
由于您不想迷路,我们使用结构化编程技术将这两条信息绑定在一起:

struct bookstore {
  struct book * books;
  size_t count;
};
为了与这样的商店合作,普通的操作应该放在花哨的名字后面。这叫做抽象,可能是编程时最重要的事情。在C中执行此操作的设备是函数。从一开始初始化空存储:

char init_store(struct bookstore * store) {
  assert(store != NULL);
  store->count = 0;
  store->books = malloc(0);
  return (store->books == NULL) ? 0 : 1;
}
并添加其双重功能,即“完成”存储的功能:

这些函数仅在已有的
struct bookstore
实例上运行。您可以在堆栈或堆上分配它们(通过
malloc
,不要忘记
释放

现在进入关键部分:添加一本书。为此,您需要放大“数组”,以便能够在其中存储新项目。这是使用
realloc
完成的。然后,您只需将书复制到空闲位置即可添加:

char add_book(struct bookstore * store, struct book book) {
  assert(store != NULL);
  assert(store->books != NULL);
  struct book * books =
    realloc(store->books, (store->count + 1) * sizeof(struct book));
  if (books == NULL) {
    return 0;
  }
  books[store->count] = book;
  store->books = books;
  store->count += 1;
  return 1;
}
这就是我的方法,尽管还有很多优化的空间。但是请注意,上面的代码未经测试


该方法基本上与您的方法相同:您将使用指向(包含)书籍指针的指针。重要的区别是大小也会被存储。您的代码为此使用了一个静态局部变量,这本质上限制了您只有一个书籍“列表”。作为一个建议:避免像地狱一样的全局或静态。

所以你正在寻找一种可能性来存储一些书,你可能只会添加到其中?这确实可以通过一种与您已有的方法非常相似的方法来实现。但让我们从头开始:

基本上,您在内存中的某个位置存储一个书籍“数组”,即在一个连续的内存位置中存储多个
struct book
。可以使用指向第一本书的指针指向该数组:

struct book * books;
不知何故,您还需要知道该数组的结束位置。因此,我看到的两种可能性是要么使用sentinel值(类似于C字符串对
'\0'
的作用),要么只跟踪数组的大小。我会选择后者:

size_t count;
由于您不想迷路,我们使用结构化编程技术将这两条信息绑定在一起:

struct bookstore {
  struct book * books;
  size_t count;
};
为了与这样的商店合作,普通的操作应该放在花哨的名字后面。这叫做抽象,可能是编程时最重要的事情。在C中执行此操作的设备是函数。从一开始初始化空存储:

char init_store(struct bookstore * store) {
  assert(store != NULL);
  store->count = 0;
  store->books = malloc(0);
  return (store->books == NULL) ? 0 : 1;
}
并添加其双重功能,即“完成”存储的功能:

这些函数仅在已有的
struct bookstore
实例上运行。您可以在堆栈或堆上分配它们(通过
malloc
,不要忘记
释放

现在进入关键部分:添加一本书。为此,您需要放大“数组”,以便能够在其中存储新项目。这是使用
realloc
完成的。然后,您只需将书复制到空闲位置即可添加:

char add_book(struct bookstore * store, struct book book) {
  assert(store != NULL);
  assert(store->books != NULL);
  struct book * books =
    realloc(store->books, (store->count + 1) * sizeof(struct book));
  if (books == NULL) {
    return 0;
  }
  books[store->count] = book;
  store->books = books;
  store->count += 1;
  return 1;
}
这就是我的方法,尽管还有很多优化的空间。但是请注意,上面的代码未经测试


该方法基本上与您的方法相同:您将使用指向(包含)书籍指针的指针。重要的区别是大小也会被存储。您的代码为此使用了一个静态局部变量,这本质上限制了您只有一个书籍“列表”。作为建议:避免像地狱一样的全局或静态。

有许多方法可以跟踪许多结构。最简单的动态结构是结构的动态数组。同样的内存管理方法也适用,但您可以添加另一个外部结构,以帮助保存与该图书集合相关的信息。例如,如果您有多个感兴趣的收藏,您可以做类似的事情:

typedef {
    size_t nbooks;
    size_t allocsz;
    char colname[16];
    struct {
        char* name;
        size_t number;
    } book;
} collection;
这样的方法允许一个结构保存它包含的图书数量、当前分配大小和收藏的唯一名称(例如小说、非小说等)

你可以考虑这样的事情是否会增加足够的额外数据来满足你的需求。对于结构数组的基本处理,动态声明