C语言 C 中的数组列表不起作用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3732856/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 06:27:26  来源:igfitidea点击:

Arraylist in C not working

carraysdata-structuresarraylistdynamic-arrays

提问by Slash_D

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.

我目前正在编写一个程序来在 C 中实现一个数组列表(或动态数组)。嗯......我想我已经完成了 70 - 80%,但是,我在对它们进行测试时发现我的代码存在严重问题的机器。

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:

简而言之,我将一组字符串( char* )插入到我的数组列表中,并尝试在几次操作后获取并显示它们。然而,这就是我得到的:

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

数组列表.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;
}

回答by caf

As others have noted, the problem is in the arraylist_add()function, which needs to dynamically allocate memory. This problem is actually perfectly suited for realloc(), which will expand the dynamically allocated array (meaning you don't have to do the copying loop):

正如其他人所指出的,问题出在arraylist_add()需要动态分配内存的函数中。这个问题实际上非常适合realloc(),它将扩展动态分配的数组(意味着您不必执行复制循环):

void arraylist_add(struct arraylist *list, value_type value) {
  int size = arraylist_get_size(*list);
  value_type *new_data;

  new_data = realloc(list->data, (size + 1) * sizeof new_data[0]);

  if (new_data)
  {
      new_data[size] = value;
      arraylist_set_data_collection(list, new_data);
      ++list->size;
  }
}

This will even work for the first allocation, since realloc()works like malloc()if you pass it a NULL.

这甚至适用于第一次分配,因为realloc()就像malloc()您将NULL.

PS:

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.

为了使实现更高效,您不应该每次将数组扩展一个条目 - 相反,应将分配的块数与条目数分开跟踪。

回答by Naveen

In the arraylist_addmethod you are storing the address of a local variable new_datain 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 using malloci.e. you need to do something like value_type* new_data = (value_type*)malloc( (size + 1) * sizeof(value_type));. Also remember that you have to deallocate this memory yourself using free.

在该arraylist_add方法中,您将局部变量的地址存储new_data到列表中。一旦控制权离开函数,这个变量就会被销毁。因此,您有无效的指针,当取消引用时会调用未定义的行为。要解决此问题,您需要使用mallocie为堆中的字符串分配内存,您需要执行类似value_type* new_data = (value_type*)malloc( (size + 1) * sizeof(value_type));. 还请记住,您必须使用free.

回答by Paul

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.

乍一看:在 arraylist_add 中,您将 new_data 声明为局部变量。当您将其传递给 arraylist_set_data_collection 时,它会将指针传递给此数据。但是,一旦 arraylist_add 返回到 main,new_data 超出范围,因此不再有效。

Consider doing a deep copy and handling the memory manually with malloc and free.

考虑使用 malloc 和 free 进行深度复制并手动处理内存。

回答by Grumdrig

The root of your problem is here:

你的问题的根源在这里:

void arraylist_add(struct arraylist *list, value_type value) {
  int size = arraylist_get_size(*list);
  value_type new_data[size + 1];
  ...
  arraylist_set_data_collection(list, new_data);
  ...
  ++list->size;
}

new_datais 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 with malloc, e.g.

new_data在栈上声明。在调用返回后使用该内存不再安全。您需要为数据分配空间malloc,例如