我必须在c中实现动态数组。这是它的结构:
typedef void (*PrintArrayElement)(const void* element);
typedef struct {
size_t size;
size_t capacity;
void** array;
PrintArrayElement printElement; // Callback
} dynamic_array;
我已经实现了向数组添加元素的功能:
void arrayAddItem(dynamic_array* container, void* item)
{
if (container->size == container->capacity)
{
void** temp = container->array;
container->capacity <<= 1;
container->array = (void **)realloc(container->array, container->capacity * sizeof(void*));
if (!container->array)
{
printf("Out of Memory\n");
container->array = temp;
return;
}
}
container->array[container->size] = strdup(item);
container->size++;
}
我还有在字符串中查找单词索引的功能:
dynamic_array* findWord(char str[], char keyword[])
{
dynamic_array* indexes;
arrayInit(&indexes, 16, printInt);
int i = 0;
int start = 0;
int end = 0;
size_t len = strlen(str);
while (i < len) {
while (i < len && !isalpha(str[i]))
{
i++;
}
if (isalpha(str[i]))
{
start = i;
while (i < len && isalpha(str[i]))
{
i++;
}
end = i;
char* word = (char*)malloc(end - start + 1);
strncpy(word, &str[start], end - start);
word[end - start] = '\0';
if(strcmp(word, keyword) == 0)
{
printf("%d\n", start);
arrayAddItem(indexes, &start);
}
free(word);
}
}
return indexes;
}
所以我写了
dynamic_array* test_find_array1 = findWord("hello, world, hello", "hello");
并等待有两个元素的dynamic_array:0和14,但我有一个带有指针的dynamic_array。而主要的问题是,有时我有正确的答案,但我没有重写代码。为什么会发生?
我尝试重写 findWord 函数和 arrayAddItem 但它仍然是随机的。我不知道出了什么问题。让我知道我是否应该从项目中添加一些其他功能的代码。
您应该提供一个程序而不是不完整的代码片段。您缺少标头、
arrayInit()
、printInt()
和 main()
的实现。另外你的程序会泄漏内存。我添加了示例实现供您测试代码。
printElement
未使用,因此您应该从此处提供的最小程序中删除它。
arrayAddItem
初始化为 0,
capacity
将失败。您期望分配内存,并且 malloc(0)
是实现定义的,并且可能为 NULL,如果 realloc()
失败,现在会与检查发生冲突。我添加了一个检查,如果是 0,则默认为 capacity = 1
。
arrayAddItem()
使用 strdup()
来复制 item
,这意味着它采用一个字符串。在 findWord()
中,您传入 int
,因此这很可能会出现段错误。更改 API 以期望调用者提供数据的副本,并且调用者还负责释放所述数据(为了对称)。
arrayAddItem()
失败(新容量而不是旧容量),
container->capacity
将返回无效的 realloc()
。我更新了代码以使用变量。
arrayAddItem()
错误处理策略不一致。您忽略 strdup()
失败的可能性,并在 realloc()
失败时返回损坏的数据。您不会检查 arrayInit()
是否失败,因此我认为您不会返回任何内容。现在在失败时编码 exit(1)
。 API 需要更改才能避免这些错误,但如果你内存不足,你可能无论如何都会退出。
findWord()
最小化变量范围并避免未使用的 start = 0
和 end = 0
。
findWord()
尚不清楚您是否要存储索引数组或字符串数组,因此此处使用字符串(word
)。如果你不想存储它,那么花费所有精力来创建关键字的副本有点愚蠢,所以这就是我所做的(并且只有免费的word
,如果它不是关键字)。如果你想存储索引,只需执行 strncmp()
并检查你找到的字符串的长度是否与关键字的长度相同。然后为 int
分配空间并将其传递给 arrayAddItem()
。
#include <ctype.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct {
size_t size;
size_t capacity;
void** array;
} dynamic_array;
void arrayInit(dynamic_array **container, size_t capacity)
{
*container = malloc(sizeof **container);
if(!*container)
{
printf("malloc failed\n");
exit(1);
}
(*container)->size = 0;
(*container)->capacity = capacity;
(*container)->array = capacity ? malloc(sizeof *(*container)->array * capacity) : NULL;
if(capacity && !(*container)->array)
{
printf("malloc of array failed\n");
exit(1);
}
}
void arrayFree(dynamic_array *container) {
if(!container) return;
free(container->array);
free(container);
}
void arrayAddItem(dynamic_array* container, void* item) {
if (container->size == container->capacity)
{
size_t new_capacity = container->capacity ? container->capacity * 2 : 1;
void **new_array = realloc(container->array, sizeof *(container->array) * new_capacity);
if(!new_array)
{
printf("malloc failed\n");
exit(1);
}
container->capacity = new_capacity;
container->array = new_array;
}
container->array[container->size] = item;
container->size++;
}
dynamic_array* findWord(char str[], char keyword[]) {
dynamic_array* indexes;
arrayInit(&indexes, 0);
int i = 0;
size_t len = strlen(str);
while (i < len) {
while (i < len && !isalpha(str[i]))
i++;
if (isalpha(str[i]))
{
int start = i;
while (i < len && isalpha(str[i]))
{
i++;
}
int end = i;
char* word = malloc(end - start + 1);
if(!word)
{
printf("malloc failed\n");
exit(1);
}
strncpy(word, &str[start], end - start);
word[end - start] = '\0';
if(strcmp(word, keyword) == 0)
{
printf("%d\n", start);
arrayAddItem(indexes, word);
} else
free(word);
}
}
return indexes;
}
int main(void)
{
dynamic_array *container = findWord("hello world", "hello");
for(size_t i = 0; i < container->size; i++)
{
printf("%s\n", (char *) container->array[i]);
free(container->array[i]);
}
arrayFree(container);
}