C 中的数组列表不工作
我目前正在编写一个程序来在 C 中实现数组列表(或动态数组)。嗯...我想我已经完成了 70 - 80%,但是,在对几个代码进行测试时,我发现我的代码存在严重问题的机器。
简而言之,我将一组字符串( char* )插入到我的数组列表中,并尝试在几次操作后获取并显示它们。然而,这就是我得到的结果:
CHECK: 1
CHECK: 2
CHECK: ܗ¿èۗ¿
CHECK: EàEàHAÿE؉Ⱥ
CHECK: 5
CHECK: 6
不幸的是,尽管我已经检查了代码两次,但我仍然无法找出代码中的问题所在。
数组列表.h
#ifndef _ARRAYLIST_H
#define _ARRAYLIST_H
#include <stdio.h>
typedef char* value_type;
struct arraylist {
int size;
value_type* data;
};
extern void arraylist_initial(struct arraylist *list);
extern int arraylist_get_size(const struct arraylist list);
extern value_type* arraylist_get_data_collection(const struct arraylist list);
extern void arraylist_set_data_collection(struct arraylist *list, value_type* data);
extern void arraylist_add(struct arraylist *list, value_type value);
extern value_type arraylist_get(const struct arraylist list, int index);
extern int arraylist_indexof(const struct arraylist list, value_type value);
#endif
数组列表.c
#include "arraylist.h"
void arraylist_initial(struct arraylist *list) {
list->size = 0;
list->data = NULL;
}
int arraylist_get_size(const struct arraylist list) {
return list.size;
}
value_type* arraylist_get_data_collection(const struct arraylist list) {
return list.data;
}
void arraylist_set_data_collection(struct arraylist *list, value_type* data) {
list->data = data;
}
void arraylist_add(struct arraylist *list, value_type value) {
int size = arraylist_get_size(*list);
value_type new_data[size + 1];
int index = 0;
for(; index != size; ++index) {
new_data[index] = arraylist_get(*list, index);
}
new_data[index] = value;
arraylist_set_data_collection(list, new_data);
++list->size;
}
value_type arraylist_get(const struct arraylist list, int index) {
if(index < arraylist_get_size(list)) {
return list.data[index];
}
else {
return NULL;
}
}
int arraylist_indexof(const struct arraylist list, value_type value) {
int index = 0;
for(; index != arraylist_get_size(list); ++index) {
if(strcmp(list.data[index], value) == 0) {
return index;
}
}
return -1;
}
int main(void){
struct arraylist list;
arraylist_initial(&list);
arraylist_add(&list, "1");
arraylist_add(&list, "2");
arraylist_add(&list, "3");
arraylist_add(&list, "4");
arraylist_add(&list, "5");
arraylist_add(&list, "6");
int index = 0;
for(; index != 6; ++index) {
printf("CHECK: %s\n", arraylist_get(list, index));
}
return 0;
}
I am currently writing a program to implement an arraylist (or dynamic array) in C. Hmm... I think I have 70 - 80% done with it, however, I found a serious problem with my code when testing them on a couple of machines.
Briefly, I inserted a group of strings( char* ) into my arraylist, and tried to get and display them after couples of operations. However, this is what I got:
CHECK: 1
CHECK: 2
CHECK: ܗ¿èۗ¿
CHECK: EàEàHAÿE؉Ⱥ
CHECK: 5
CHECK: 6
Unfortunately, I still cannot figure out where the problem is in my codes, even though I have reviewed my codes twice.
arraylist.h
#ifndef _ARRAYLIST_H
#define _ARRAYLIST_H
#include <stdio.h>
typedef char* value_type;
struct arraylist {
int size;
value_type* data;
};
extern void arraylist_initial(struct arraylist *list);
extern int arraylist_get_size(const struct arraylist list);
extern value_type* arraylist_get_data_collection(const struct arraylist list);
extern void arraylist_set_data_collection(struct arraylist *list, value_type* data);
extern void arraylist_add(struct arraylist *list, value_type value);
extern value_type arraylist_get(const struct arraylist list, int index);
extern int arraylist_indexof(const struct arraylist list, value_type value);
#endif
arraylist.c
#include "arraylist.h"
void arraylist_initial(struct arraylist *list) {
list->size = 0;
list->data = NULL;
}
int arraylist_get_size(const struct arraylist list) {
return list.size;
}
value_type* arraylist_get_data_collection(const struct arraylist list) {
return list.data;
}
void arraylist_set_data_collection(struct arraylist *list, value_type* data) {
list->data = data;
}
void arraylist_add(struct arraylist *list, value_type value) {
int size = arraylist_get_size(*list);
value_type new_data[size + 1];
int index = 0;
for(; index != size; ++index) {
new_data[index] = arraylist_get(*list, index);
}
new_data[index] = value;
arraylist_set_data_collection(list, new_data);
++list->size;
}
value_type arraylist_get(const struct arraylist list, int index) {
if(index < arraylist_get_size(list)) {
return list.data[index];
}
else {
return NULL;
}
}
int arraylist_indexof(const struct arraylist list, value_type value) {
int index = 0;
for(; index != arraylist_get_size(list); ++index) {
if(strcmp(list.data[index], value) == 0) {
return index;
}
}
return -1;
}
int main(void){
struct arraylist list;
arraylist_initial(&list);
arraylist_add(&list, "1");
arraylist_add(&list, "2");
arraylist_add(&list, "3");
arraylist_add(&list, "4");
arraylist_add(&list, "5");
arraylist_add(&list, "6");
int index = 0;
for(; index != 6; ++index) {
printf("CHECK: %s\n", arraylist_get(list, index));
}
return 0;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
正如其他人所指出的,问题出在 arraylist_add() 函数中,该函数需要动态分配内存。这个问题实际上非常适合
realloc()
,它将扩展动态分配的数组(意味着您不必执行复制循环):这甚至适用于第一次分配,因为 <如果您向其传递
NULL
,则 code>realloc() 的工作方式与malloc()
类似。PS:
为了提高实现效率,您不应每次将数组扩展一个条目 - 相反,应分别跟踪已分配块的数量和条目的数量。
As others have noted, the problem is in the
arraylist_add()
function, which needs to dynamically allocate memory. This problem is actually perfectly suited forrealloc()
, which will expand the dynamically allocated array (meaning you don't have to do the copying loop):This will even work for the first allocation, since
realloc()
works likemalloc()
if you pass it aNULL
.PS:
To make the implementation more efficient, you shouldn't expand the array by one entry each time - instead, keep track of the number of allocated blocks separately from the number of entries.
在 arraylist_add 方法中,您将局部变量 new_data 的地址存储到列表中。一旦控件脱离函数,该变量就会被销毁。因此,您有无效的指针,当解除引用时会调用未定义的行为。要解决此问题,您需要使用 malloc 从堆中为字符串分配内存,即您需要执行类似 value_type* new_data = (value_type*)malloc( (size + 1) * 的操作sizeof(value_type));。另请记住,您必须使用
free
自行释放该内存。In the
arraylist_add
method you are storing the address of a local variablenew_data
in to the list. This variable will destroyed as soon as the control comes out of the function. Hence you have invalid pointers which when derefrenced invoke undefined behavior. To fix this problem, you need to allocate memory for the string from heap usingmalloc
i.e. you need to do something likevalue_type* new_data = (value_type*)malloc( (size + 1) * sizeof(value_type));
. Also remember that you have to deallocate this memory yourself usingfree
.乍一看:在 arraylist_add 中,您将 new_data 声明为局部变量。当您将其传递给 arraylist_set_data_collection 时,它会传递指向该数据的指针。然而,一旦 arraylist_add 返回到 main,new_data 就超出了范围,因此不再有效。
考虑进行深度复制并使用 malloc 和 free 手动处理内存。
At first glance: in arraylist_add you declare new_data as a local variable. When you pass that to arraylist_set_data_collection, it passes the pointer to this data. However, once arraylist_add returns to main, new_data is out of scope, and is therefore no longer valid.
Consider doing a deep copy and handling the memory manually with malloc and free.
问题的根源在于:
new_data
在堆栈上声明。调用返回后使用该内存不再安全。您需要使用malloc
为数据分配空间,例如The root of your problem is here:
new_data
is declared on the stack. It's no longer safe to use that memory after the call returns. You need to allocate space for the data withmalloc
, e.g.