加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

如何在C中动态分配内存并确定数组大小?

发布时间:2020-12-16 10:27:52 所属栏目:百科 来源:网络整理
导读:我试图从 python背景教自己C.我目前的小问题是尝试对数组长度等内容进行较少的硬编码,并根据输入动态分配内存. 我写了以下程序.我希望社区的建议可以通过以下方式进行修改: 1.)使第一个和最后一个名称元素变长.目前,他们的长度被硬编码为MAX_NAME_LENGTH.这
我试图从 python背景教自己C.我目前的小问题是尝试对数组长度等内容进行较少的硬编码,并根据输入动态分配内存.

我写了以下程序.我希望社区的建议可以通过以下方式进行修改:

1.)使第一个和最后一个名称元素变长.目前,他们的长度被硬编码为MAX_NAME_LENGTH.这将涉及更改Names structdeclaration以及我为其元素分配值的方式.

2.)Bonus:找出一些方法来逐步向name_list数组中添加新元素,而无需事先确定其长度.基本上使它成为可扩展的列表.

/* namelist.c 

   Loads up a list of names from a file to then do something with them.

*/
#include <stdlib.h>
#include <stdio.h>
#include <memory.h>

#define DATAFILE "name_list.txt"
#define DATAFILE_FORMAT "%[^,]%*c%[^n]%*c"
#define MAX_NAME_LENGTH 100

typedef struct {
  char first[MAX_NAME_LENGTH];
  char last[MAX_NAME_LENGTH];
} Name;


int main() {
  FILE *fp = fopen(DATAFILE,"r");

  // Get the number of names in DATAFILE at runtime.
  Name aName;
  int lc = 0;
  while ((fscanf(fp,DATAFILE_FORMAT,aName.last,aName.first))!=EOF) lc++;
  Name *name_list[lc];

  // Now actually pull the data out of the file
  rewind(fp);
  int n = 0;
  while ((fscanf(fp,aName.first))!=EOF)
  {
    Name *newName = malloc(sizeof(Name));
    if (newName == NULL) {
      puts("Warning: Was not able to allocate memory for ``Name`` ``newName``on the heap.");
    } 
    memcpy(newName,&aName,sizeof(Name));
  name_list[n] = newName;
  n++;
  }

  int i = 1;
  for (--n; n >= 0; n--,i++) {
    printf("%d: %s %sn",i,name_list[n]->first,name_list[n]->last);
    free(name_list[n]);
    name_list[n] = NULL;
  }

  fclose(fp);
  return 0;
}

name_list.txt的示例内容:

Washington,George
Adams,John 
Jefferson,Thomas
Madison,James

更新1:

我已经实现了链接列表和@Williham建议的一些辅助函数,结果如下.

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define DATAFILE "name_list.txt"
#define MAX_NAME_LENGTH 30
#define DATAFILE_FORMAT "%29[^,]%*c%29[^n]%*c"

static const int INPUT_BUFFER_SIZE_DEFAULT = sizeof(char) * MAX_NAME_LENGTH;

typedef struct _Name Name;

struct _Name {
  char *first;
  char *last;
  Name *next;
};

int get_charcount(char *str);

Name * create_name_list(char *filename);
void print_name_list(Name *name);
void free_name_list (Name *name);

int main() {

  // Read a list of names into memory and 
  // return the head of the linked list.
  Name *head = create_name_list(DATAFILE);

  // Now do something with all this data.
  print_name_list(head);

  // If you love something,let it go.
  free_name_list(head);
  head = NULL;
  return 0;
}

int get_charcount (char *str) 
{
  int input_length = 1;
    while (str[input_length] != '')
    {
      input_length++;
    }
  return input_length;
}

Name * create_name_list(char *filename)
{
  FILE *fp = fopen(DATAFILE,"r");
  char *first_input_buffer = malloc(INPUT_BUFFER_SIZE_DEFAULT);
  char *last_input_buffer = malloc(INPUT_BUFFER_SIZE_DEFAULT);

  Name *firstNamePtr;
  Name *previousNamePtr;
  while ((fscanf(fp,last_input_buffer,first_input_buffer))!=EOF)
  {
    Name *newNamePtr = malloc(sizeof(Name));

    if (previousNamePtr) 
    {
      previousNamePtr->next = newNamePtr;
      previousNamePtr = newNamePtr;
    } 
    else 
    {
      firstNamePtr = previousNamePtr = newNamePtr;
    }

    char *temp_buffer = malloc(get_charcount(first_input_buffer));
    strcpy(temp_buffer,first_input_buffer);
    newNamePtr->first = malloc(get_charcount(first_input_buffer));
    strcpy(newNamePtr->first,temp_buffer);


    realloc(temp_buffer,get_charcount(last_input_buffer));

    strcpy(temp_buffer,last_input_buffer);
    newNamePtr->last = malloc(get_charcount(last_input_buffer));
    strcpy(newNamePtr->last,temp_buffer);

    free(temp_buffer);
    temp_buffer = NULL;
  }
  previousNamePtr->next = NULL;
  previousNamePtr = NULL;
  free(first_input_buffer);
  free(last_input_buffer);
  first_input_buffer = NULL;
  last_input_buffer = NULL;
  fclose(fp);

  return firstNamePtr;
}

void print_name_list (Name *name)
{
  static int first_iteration = 1;
  if (first_iteration) 
  {
    printf("nList of Namesn");
    printf("=============n");
    first_iteration--;
  }
  printf("%s %sn",name->first,name->last);
  if (name->next)
    print_name_list(name->next);
  else
    printf("n");
}

void free_name_list (Name *name)
{
  if (name->next)
    free_name_list(name->next);
  free(name->first);
  free(name->last);
  name->first = NULL;
  name->last = NULL;
  name->next = NULL;
  free(name);
  name = NULL;
}

解决方法

一个非常简单的方法是根本不使用数组,而是使用链表:

这可以通过多种方式完成,但最简单的可能是修改Name结构,如下所示:

typedef struct _Name Name;

struct _Name {
  char *first;
  char *last;
  Name *next;
};

使用char *而不是char []将需要一些strcpying,但这实际上既不是在这里也不是在那里.要扩展数组,您现在可以一次一个地对这些元素进行malloc;然后适当地设置.

注意:在创建新的尾部元素时,请记住在NULL旁边设置.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读