C语言 Malloc和链表的问题



我有一个函数,读取每行填充一个单词的文本文件。下面是一个文本文件的例子,我使用

and
but
five
follows
four
has
is
like
line
lines
littlest
not
once
one
only
other
six
the
three
twice
two
word
words
代码:

typedef struct node node_t;
struct node {
    char data[MAX_WORD];
    int term;
    node_t *next;
};
node_t *head; 
int
int_struct(int lines){
    FILE *fp;
    char ch;
    int n = 0, i, switch_num=1, test_first=0, test_first_2=0;
    node_t *node, *curr_add; 
    fp = fopen("text.txt", "r");
    node = (node_t*)malloc(sizeof(node_t));
    for (i=1; i<=lines; i++){
        switch_num = 1;
        n=0;
        if (test_first != 0){
            if (test_first_2){
                node = (node_t*)malloc(1000000);
            }
            test_first_2=1;
            while ((ch = getc(fp)) != 'n'){
                node -> term = i;
                node -> data[n] = ch;
                n++;
            }
            curr_add -> next = node;
            curr_add = node;
        }
        else{
            test_first = 1;
            head = curr_add = node;
        }
    }
    curr_add -> next = NULL;
    fclose(fp);
    return num;
}

我要做的是读取每个单词并将其添加到链表中。
然而,我有malloc的麻烦(目前我只是添加了很多字节),并需要关于如何正确使用它的函数内我有建议。我做了一个一般的搜索,并尽我最大的努力去做大多数例子所做的事情。但我还是不能让我的函数工作。例如,每次我执行程序时,它都会读取并将所有单词添加到链表中。但是,程序在最后一个单词时崩溃,并返回NULL。如果有人能给我指出正确的方向,我将非常感激。

问题

  1. 不检查返回值。特别是fopenmalloc可能返回NULL。如果是这样,您将在

  2. 复杂逻辑。你不需要这些switch_num, test_firsttest_first_2

  3. 当你逐行读取文本文件时,getc 不需要使用fgets

  4. 内存分配过多。每行不需要超过sizeof(node_t) + 行长度字节。

  5. 已分配的内存未被释放。动态内存应该释放为

使用链表的例子

下面的代码将文本文件读入链表。内存分配给每个列表项,以及文件中产生n * 2内存的每一行其中n是文件的行数。

#include <stdio.h>
#include <stdlib.h>
#include <string.h> /* strerror, strdup */
#include <errno.h>
typedef struct _node {
  unsigned line;
  char *data;
  struct _node *next;
} node_t;

static void
destroy_list(node_t *list)
{
  node_t *node;
  for (node = list; node; node = node->next) {
    if (node->data != NULL)
      free(node->data);
    free(node);
  }
}

static node_t *
create_list_item(const char *data, unsigned line)
{
  node_t *node = calloc(1, sizeof(node_t));
  if (node == NULL) {
    fprintf(stderr, "calloc: %sn", strerror(errno));
  } else {
    node->line = line;
    node->data = strdup(data);
    if (node->data == NULL) {
      fprintf(stderr, "strdup: %sn", strerror(errno));
      free(node);
      node = NULL;
    }
  }
  return node;
}

/* Returns pointer to new linked list */
static node_t *
read_file(FILE *fp, char *buf, size_t buf_len)
{
  node_t *list = NULL;
  node_t *prev = NULL;
  node_t *node;
  unsigned i;
  for (i = 0; fgets(buf, buf_len, fp); prev = node) {
    if ((node = create_list_item(buf, ++i)) == NULL) {
      fprintf(stderr, "calloc: %sn", strerror(errno));
      break;
    }
    if (list == NULL)
      list = node;
    if (prev != NULL)
      prev->next = node;
  }
  return list;
}

static void
print_list(const node_t *list)
{
  const node_t *node;
  for (node = list; node; node = node->next)
    printf("%d: %s", node->line, node->data);
}

int main(int argc, char const* argv[])
{
  const char *filename = "text.txt";
  char buf[1024] = {0};
  FILE *fp = NULL;
  node_t *list = NULL;
  if (NULL == (fp = fopen(filename, "r"))) {
    fprintf(stderr, "failed to open file %s: %sn",
        filename, strerror(errno));
    return 1;
  }
  list = read_file(fp, buf, sizeof(buf));
  fclose(fp);
  if (list) {
    print_list(list);
    destroy_list(list);
  }
  return 0;
}
使用动态数组的例子

为文件中的每一行(两次)分配内存是低效的,不仅因为系统调用(malloc, realloc等)是昂贵的,但也因为这些项目不是连续放置的。访问的内存区域通常更快。

在下面的代码中,链表被替换为动态数组。我们一次初始化10行内存。

#include <stdio.h>
#include <stdlib.h>
#include <string.h> /* strerror, strdup */
#include <errno.h>
typedef struct _node {
  size_t line;
  char *data;
} node_t;

static void
destroy_array(node_t *array, size_t size)
{
  size_t i;
  node_t *item;
  for (i = 0; i < size; i++) {
    item = &array[i];
    if (item->data)
      free(item->data);
  }
  free(array);
}

static void
print_array(node_t *array, size_t size)
{
  size_t i;
  node_t *item;
  for (i = 0; i < size; i++) {
    item = &array[i];
    if (item->data) {
      printf("%ld: %s", item->line, item->data);
    }
  }
}
static node_t *
read_file(FILE *fp, char *buf, size_t buf_len,
    const size_t array_step, size_t *array_size)
{
  node_t *item;
  node_t *array = calloc(array_step, sizeof(node_t));
  size_t size = 0;
  if (array == NULL) {
    fprintf(stderr, "calloc:%sn", strerror(errno));
    return array;
  }
  while (fgets(buf, buf_len, fp)) {
    if (size && size % array_step == 0) {
      array = realloc(array, sizeof(node_t) * (array_step + size));
      if (array == NULL) {
        fprintf(stderr, "realloc:%sn", strerror(errno));
        break;
      }
    }
    item = &array[size++];
    item->line = size;
    item->data = strdup(buf);
    if (item->data == NULL) {
      fprintf(stderr, "strdup: %sn", strerror(errno));
      break;
    }
  }
  *array_size = size;
  return array;
}
int main(int argc, char const* argv[])
{
  node_t *array;
  const size_t array_step = 10;
  size_t array_size;
  const char *filename = "text.txt";
  char buf[1024] = {0};
  FILE *fp = NULL;
  if (NULL == (fp = fopen(filename, "r"))) {
    fprintf(stderr, "failed to open file %s: %sn",
        filename, strerror(errno));
    return 1;
  }
  array = read_file(fp, buf, sizeof(buf), array_step, &array_size);
  fclose(fp);
  if (array) {
    print_array(array, array_size);
    destroy_array(array, array_size);
  }
  return 0;
}

注意node_t结构的变化

相关内容

  • 没有找到相关文章

最新更新