我正在用C语言制作一个字符串列表,我在网上找不到任何可以轻松添加和清除字符串列表的东西。这将接近Perl的"push"函数。
我想在这里分享我想到的代码:
#include <stdio.h>//printf
#include <stdlib.h>//EXIT_FAILURE, malloc, realloc
#include <string.h>//need for strcmp and strlen
void *add_name(char **restrict array, size_t *restrict size, size_t *restrict number_of_names, const char *restrict NAME) {//this function works, when freed inside main()
for (unsigned int name = *number_of_names-1; name <= 0; name--) {
if (strcmp(array[name], NAME) == 0) {
return array;//if this name is already in the list, don't add it
}
}
const size_t NAME_SIZE = strlen(NAME)*sizeof(char)+sizeof(char*);
*size += NAME_SIZE;
array = realloc(array, *size);
if (array == NULL) {
puts("realloc of array failed.n");
exit(EXIT_FAILURE);
}
array[*number_of_names] = malloc(NAME_SIZE);
if (array[*number_of_names] == NULL) {
printf("alloc of array[%zu] failed.n", *number_of_names);
exit(EXIT_FAILURE);
}
strcpy(array[*number_of_names], NAME);
*number_of_names += 1;
return array;
}
void *clear_names(char **restrict array, size_t *restrict size, size_t *restrict number_of_names) {//empty the list of names
for (size_t name = 0; name < *number_of_names; name++) {
free(array[name]); array[name] = NULL;//this is missing something
if (array[name] != NULL) {
printf("free of array[%zu] failed.n", name);
}
}
*number_of_names = 0;
*size = sizeof(char);
array = realloc(array, *size);
if (array == NULL) {
printf("realloc of array failed @ line %un",__LINE__);
exit(EXIT_FAILURE);
}
return array;
}
int main (void) {
puts("This program demonstrates how to add to and clear a list of names.");
size_t name_list_size = sizeof(char);
char **name_list = malloc(name_list_size);
size_t number_of_names = 0;
name_list = add_name(name_list, &name_list_size, &number_of_names, "James");
name_list = add_name(name_list, &name_list_size, &number_of_names, "Mary");
name_list = add_name(name_list, &name_list_size, &number_of_names, "Mary");
name_list = add_name(name_list, &name_list_size, &number_of_names, "Thomas");
for (size_t name = 0; name < number_of_names; name++) {
printf("%sn",name_list[name]);
}
name_list = clear_names(name_list, &name_list_size, &number_of_names);
//
name_list = add_name(name_list, &name_list_size, &number_of_names, "Matthew");
name_list = add_name(name_list, &name_list_size, &number_of_names, "Mark");
name_list = add_name(name_list, &name_list_size, &number_of_names, "Luke");
name_list = add_name(name_list, &name_list_size, &number_of_names, "John");
for (size_t name = 0; name < number_of_names; name++) {
printf("%sn",name_list[name]);
}
//
name_list = clear_names(name_list, &name_list_size, &number_of_names);
name_list = add_name(name_list, &name_list_size, &number_of_names, "Titus");
printf("size = %zu number_of_names = %zun", name_list_size, number_of_names);
name_list = add_name(name_list, &name_list_size, &number_of_names, "Peter");
printf("size = %zu number_of_names = %zun", name_list_size, number_of_names);
name_list = add_name(name_list, &name_list_size, &number_of_names, "Bartholomew");
printf("size = %zu number_of_names = %zun", name_list_size, number_of_names);
name_list = add_name(name_list, &name_list_size, &number_of_names, "Paul");
printf("size = %zu number_of_names = %zun", name_list_size, number_of_names);
for (size_t name = 0; name < number_of_names; name++) {
printf("%sn",name_list[name]);
}
name_list = clear_names(name_list, &name_list_size, &number_of_names);
free(name_list); name_list = NULL;
return 0;
}
我的建议如下:
- 将
realloc
分配给临时指针,因此如果它返回NULL,您不会销毁array
- 使用
strdup
代替malloc
作为字符串存储 - 使用
lsearch
检查&插入字符串 - 当增加
array
的大小时,通过加倍而不是线性进行 - 打包数组,它的计数&
struct
(见下文)中的容量,并将其作为参数传递给add &明确功能
您需要添加一个比较函数以传递给lsearch
。如果lsearch
添加了一个名称,它将更新计数。分配仍然取决于您,因此在调用它之前请确保容量超过计数。
如果你这样做,我想你会发现你的代码更小,更简单。它还可以添加delete &搜索功能。
使用结构体的一个优点是可以使用较短的名称,例如:
struct name_list_t {
char **array;
size_t n, capacity; } names = { .array = NULL };
//当在main()中释放时,该函数有效
咩。这个注释实际上没有意义,因为函数没有被释放。我明白你的意思,但你在逼我工作。
HTH。