大家好!
I got this work:
char **list = NULL; // global
int number_of_strings = 0; // global
void empty_list_of_strings(void);
void add_string_to_list(char *string);
void print_list_of_strings(void);
int main(int argc, char **argv) {
add_string_to_list("Warrior");
add_string_to_list("Magician");
add_string_to_list("Pirate");
print_list_of_strings();
empty_list_of_strings();
return 0;
}
void empty_list_of_strings(void) {
int k=0;
if(list != NULL) {
for(k=0; k number_of_strings; k++) { // less than
if(list[k] != NULL) {
free(list[k]);
list[k] = NULL;
}
}
free(list);
list = NULL;
number_of_strings = 0;
}
}
void add_string_to_list(char *string) {
if(list != NULL) {
list=realloc(list, (number_of_strings + 2) * sizeof(char*));
list[number_of_strings]=malloc( (strlen(string) + 1) * sizeof(char));
strcpy(list[number_of_strings], string);
number_of_strings++;
list[number_of_strings]=NULL;
} else {
list = malloc( (number_of_strings +2) *sizeof(char *));
list[number_of_strings]=malloc( (strlen(string) + 1) * sizeof(char) );
strcpy(list[number_of_strings], string);
number_of_strings++;
list[number_of_strings]=NULL;
}
}
void print_list_of_strings(void) {
int k=0;
if(list != NULL) {
for(;k number_of_strings;k++) { // less than
if(list[k] != NULL) {
printf("list[%d] = %sn", k, list[k]);
}
}
}
}
现在我想让函数更通用一点,所以我试着改变add_string_to_list函数,使它看起来像这样:
void add_string_to_list(char** test, char *string);
in main I changed this:
int main(int argc, char **argv) {
char **local = list; // is this possible ???
add_string_to_list(local, "Warrior");
add_string_to_list(local, "Magician");
add_string_to_list(local, "Pirate");
list = local; // is this possible ???
print_list_of_strings();
empty_list_of_strings();
return 0;
}
最后我将add_string_to_list函数更改为:
void add_string_to_list(char **test, char *string) {
if(test != NULL) {
test=realloc(test, (number_of_strings + 2) * sizeof(char*));
test[number_of_strings]=malloc( (strlen(string) + 1) * sizeof(char));
strcpy(test[number_of_strings], string);
number_of_strings++;
test[number_of_strings]=NULL;
} else {
test = malloc( (number_of_strings +2) *sizeof(char *));
test[number_of_strings]=malloc( (strlen(string) + 1) * sizeof(char) );
strcpy(test[number_of_strings], string);
number_of_strings++;
test[number_of_strings]=NULL;
}
}
现在我没有得到任何输出。这就像add_to_string函数没有得到正确的指针?我是否以正确的方式发送指向函数的指针?可以这样做吗?
这样,您就不再改变实际的东西了,即main
中的local
。你只需要收到一个副本,然后在上面做一些修改。
要做你想要做的事情,你必须将local
的地址传递给add_string_to_list
,并接收char ***test
而不是char **test
;然后在函数中出现的test
后面加上*
s,必要时用括号()
括起来。
与main
中的3个适当的函数调用add_string_to_list( &local, ... );
一起,将函数定义更改为以下内容即可完成工作:
void add_string_to_list( char ***test, char *string ) {
if ( *test != NULL ) {
*test = realloc( *test, ( number_of_strings + 2 ) * sizeof( char* ) );
(*test)[number_of_strings] = malloc( ( strlen( string ) + 1 ) * sizeof(char) );
strcpy( (*test)[number_of_strings], string );
number_of_strings++;
(*test)[number_of_strings] = NULL;
}
else {
*test = malloc( ( number_of_strings + 2 ) *sizeof( char * ) );
(*test)[number_of_strings] = malloc( ( strlen( string ) + 1 ) * sizeof(char) );
strcpy( (*test)[number_of_strings], string );
number_of_strings++;
(*test)[number_of_strings] = NULL;
}
}
有一件事:在for
循环条件语句部分中提供的代码中也缺少一些<
符号。我记得有两个,也许三个。
关于你的评论// is this possible ???
,是的,他们是。
问题是您的add_string_to_list
函数只修改test
的本地副本。如果您想将列表表示为char **
,那么您的add_string_to_list
函数必须这样编写:
void add_string_to_list(char ***test, char *string) {
if (*test != NULL) {
*test=realloc( ... );
...
} else {
*test=malloc( ... );
...
}
}
许多程序员倾向于通过声明一个结构体来表示列表来避免这种指针混淆:
typedef struct {
char **strings;
int numStrings;
} StringList;
然后你可以初始化列表:
StringList list = { .strings=NULL, .numStrings=0 };
然后你的add_string_to_list
函数看起来像:
void add_string_to_list(StringList *list, char *string) {
if (list->strings != NULL) {
list->strings = realloc( ... );
...
list->numStrings++;
} else {
list->strings = malloc( ... );
...
list->numStrings++;
}
}
然而,我讨厌在编写代码时重复自己,而且我也认为为每个新的列表项执行realloc()
是非常低效的,所以我会这样做:
typedef struct {
char **strings;
int numStrings;
int capacity;
} StringList;
void init_string_list(StringList *list, int capacity) {
list->strings = (char **) malloc(capacity * sizeof(char *));
list->capacity = capacity;
list->numStrings = 0;
}
void resize_string_list(StringList *list, int increment) {
list->capacity += increment;
list->strings = (char **) realloc(list->strings,
(list->capacity * sizeof(char *)));
}
void add_string_to_list(StringList *list, char *string) {
if ((list->capacity - list->numStrings) < 1)
resize_string_list(list, SOME_REASONABLE_INCREMENT_SIZE);
list->strings[list->numStrings++] = strdup(string);
}
...
int main(int argc, char **argv) {
StringList list = {0};
init_string_list(&list, SOME_REASONABLE_STARTING_CAPACITY);
add_string_to_list(&list, "foo");
add_string_to_list(&list, "bar");
add_string_to_list(&list, "baz");
...
}
当然,这只是为了举例的目的。仍然有许多方法可以改进这段代码。但我认为你会同意StringList *list
(或类似的东西)比char ***list
更美观,因此更容易遵循(和维护)。