【问题标题】:How to make a custom size array in a struct in C如何在 C 中的结构中创建自定义大小的数组
【发布时间】:2022-11-09 19:40:51
【问题描述】:

我有这样的代码

#ifndef hashtable
#define hashtable

// define the maxmium size
#define INITIAL_SIZE 5
#define LOAD_FACTOR 0.7

typedef struct hashtable
{
    int keyArray[INITIAL_SIZE];

    // 1d array of strings with maximum length 100 (plus '\0 character')
    char valueArray[INITIAL_SIZE][100 + 1]; 
    bool isActiveArray[INITIAL_SIZE]; // for deleting elements

    int count;
    int capacity;
    double loadFactor;

    // true: linear probing, false: quadratic probing
    bool collisionHandler;

} table;

#endif

hashtable.h 文件中

我在其中定义了一个带有键数组和值数组等的哈希表。 我对如何调整哈希表的大小感到困惑,因为每当创建一个新结构以调整大小时,我都会遇到无法更改我的INITIAL_SIZE 的问题,尤其是在#define 语句中,尽管我想做一个新表的容量为2*INITIAL_SIZE 等等......

这是我的 initTable() 代码,我在其中制作表格以防万一

void initTable(table* p, int size, double loadFactor, bool collisionHandler) {
    // constructor
    p->count = 0;
    p->capacity = size;
    p->loadFactor = loadFactor; 
    p->collisionHandler = collisionHandler;

    memset( p->keyArray, 0, sizeof p->keyArray );
    memset( p->valueArray, 0, sizeof p->valueArray );
    memset( p->isActiveArray, 0, sizeof p->isActiveArray );    
    
} 

即使完全删除 INITIAL_SIZE,如何调整数组大小,接受任何建议

谢谢您的帮助, 座位

【问题讨论】:

  • 使用INITIAL_SIZE 作为数组大小意味着它的常量,您想调整数组的大小,所以不要使用常量

标签: c struct hashtable


【解决方案1】:

宏(定义)不是变量,它们在编译之前被它们的值替换,所以在你的代码中所有的 INITIAL_SIZE 都将被 5 替换。

当您在代码中声明一个变量时,它将在堆栈上静态分配并且其大小是恒定的。您无法更改结构中数组的大小,因此您需要将数组放在结构之外以及指向它的指针,如下所示:

typedef struct hashtable
{
    int    *keyArray;
    char   *valueArray; 
    bool   *isActiveArray;
    
    int    count;
    int    capacity;
    double loadFactor;
    
    bool   collisionHandler;
} table;

然后你需要动态分配带有malloc 的数组。 malloc 函数接受您要分配的大小的参数并返回一个指向已分配区域(在堆上)的指针。 例如:

table p;
int   size = 5;
p.keyArray = malloc(size * sizeof(int)); // sizeof is a c operator that return the size of a type in bytes

if (p.keyArray == NULL)  // it is a good practice to protect a malloc by checking its return value
   exit(1);

//p.keyArray now points to an array of size 5, you can now use it like any other array

当您不再需要数组时,您必须使用 free 函数释放分配的内存

free(p.keyArray);

最后是执行数组大小调整的完整代码:

void resize(int **array, int old_size, int new_size)
{
    int *new_array = malloc(new_size * sizeof(int)); // allocate the new area
    if (!new_array) // protect the malloc
       exit(1);
    memcpy(new_array, *array, old_size * sizeof(int)); // copy the content from the old area to the new one
    free(*array); // free the old area
    *array = new_array; // and change the pointer of the old area
}

或使用 realloc:

void resize(int **array, int new_size)
{
    *array = realloc(*array, new_size * sizeof(int));
    if (!*array)
        exit(1);
}

编辑: 正如 Neil 所说,realloc 方法更好,因为您让 malloc 进行内部优化(如果初始区域旁边的区域足够,它只会扩展该区域,从而避免复制数组的内容)。我只是想向您展示第一个版本的 malloc 逻辑。

【讨论】:

  • malloc 代码总是复制表格,而realloc 代码可以在不复制的情况下扩展内存;我认为这是首选。
  • 感谢@jgiron42 的回答。但是,在测试您的答案时,我遇到了一个小缺陷。复制 p->valueArray 和 p->isActiveArray 的答案是成功的;但是,当使用 memcpy 复制整数的 p-keyArray 时,我发现该行需要为 memcpy(new_keys, *keys, old_size*sizeof(int))。不确定我是否做错了什么,但这对我有用。
【解决方案2】:

@jgiron42 的答案几乎是完美的,使用 malloc 重新分配并使用整数、char 和 bool 指针用于 hashtable.h 中的列表,在我的代码/问题中,使其完全工作的唯一方法是复制一个新的 int* 键数组时需要这样做 - > memcpy(new_keys, *keys, old_size * sizeof(int)); 而不是适用于 char 和 bool 数组 memcpy(new_bools, *bools, old_size);

【讨论】:

    猜你喜欢
    • 2020-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-09
    • 1970-01-01
    • 2010-09-20
    相关资源
    最近更新 更多