【问题标题】:Arraylist in C not workingC中的Arraylist不起作用
【发布时间】:2011-04-13 13:39:33
【问题描述】:

我目前正在编写一个程序来在 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

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;
}

【问题讨论】:

    标签: c arrays data-structures arraylist dynamic-arrays


    【解决方案1】:

    正如其他人所指出的,问题出在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;
      }
    }
    

    这甚至适用于第一次分配,因为如果您将 NULL 传递给 realloc(),它的工作方式与 malloc() 类似。

    PS:

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

    【讨论】:

    • 非常感谢,伙计。问题已解决。 :-)
    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

        【解决方案4】:

        问题的根源在这里:

        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_data 在堆栈上声明。调用返回后使用该内存不再安全。您需要为 malloc 的数据分配空间,例如

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-05-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多