C LinkList Demo

Updated on with 9 views and 0 comments

list.h head头类,定义接口

// 如果没有定义 LIST_H_宏
#ifndef LIST_H_
// 定义LIST_H宏
#define LIST_H_
// 布尔
#include <stdbool.h>
// 标题长度
#define TSIZE 45
// 电影 结构体
struct film {
  // 电影名称
  char title[TSIZE];
  // 评分
  int rating;
};
// 将 struct film 用 Item类型代替
typedef struct film Item;
// 将 struct node 使用 Node代替
typedef struct node{
  Item item;
  struct node *next;
} Node;
// 链表结构和Node类相同
typedef Node *List;
// 初始化链表
void InitalizeList(List *plist);
// 链表是否为空
bool ListIsEmpty(const List *plist);
// 是否还可以创建新的next节点
bool ListIsFull(const List *plist);
// 所有节点数量
unsigned int ListItemCount(const List *plist);
// 新增一个节点
bool AddItem(Item item, List *plist);
void Traverse(const List *plist, void (*pfun)(Item item));
// 释放所有节点
void EmptyTheList(List *plist);

#endif

list.c 对应 list.h 提供实现类

#include <stdio.h>
#include <stdlib.h>
#include "list.h"

static void CopyToNode(Item item, Node *pnode);
// 初始化链表
void InitalizeList(List *plist)
{ 
    // 直接指向空
    *plist = NULL;
}
// 判断链表是否为空
bool ListIsEmpty(const List *plist)
{
   // 看链表是否指向空就可以了
    return *plist == NULL ? true : false;
}
// 是否还可以新增节点
bool ListIsFull(const List *plist)
{
    Node *pt;
    bool full;
  // 为新节点分配一个内存,分的出来就代表可以新增
    pt = (Node *)malloc(sizeof(Node));
    if (pt == NULL)
    {
        full = true;
    }
    else
    {
        full = false;
    }
    free(pt);
    return full;
}
// 查询所有节点计算总量
unsigned int ListItemCount(const List *plist)
{
    unsigned int count = 0;
    Node *pnode = *plist;
    while (pnode != NULL)
    {
        ++count;
        // 进入下一个节点
        pnode = pnode->next;
    }
    return count;
}
// 添加元素
bool AddItem(Item item, List *plist)
{
    // 新节点
    Node *pnew;
    // 传入链表
    Node *scan = *plist;
   // 为新节点分配内存
    pnew = (Node *)malloc(sizeof(Node));
   // 如果新节点分配不出来就返回false
    if (pnew == NULL)
    {
        return false;
    }
   // 把item内容拷贝到节点的item属性中
    CopyToNode(item, pnew);
   // 新节点的下一个节点设置为空
    pnew->next = NULL;
   // 如果传入的链表为空链表,则直接让指针指向新节点
    if (scan == NULL)
    {
        *plist = pnew;
    }
   // 否则追加至末尾
    else
    {
        while (scan->next != NULL)
        {
            scan = scan->next;
        }
        scan->next = pnew;
    }
    return true;
}
// 接受一个链表,一个void函数,函数参数为Item类型
void Traverse(const List *plist, void (*pfun)(Item item))
{
    Node *pnode = *plist;
    // 挨个调用函数
    while (pnode != NULL)
    {
        (*pfun)(pnode->item);
        pnode = pnode->next;
    }
}
// 释放所有链表内存
void EmptyTheList(List *plist)
{
    Node *psave;
    while (*plist != NULL)
    {
        psave = (*plist)->next;
        free(*plist);
        *plist = psave;
    }
}

static void CopyToNode(Item item, Node *pnode)
{
    pnode->item = item;
}

movie.c 入口函数

// 引入头文件
#include "list.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

void showmovies(Item item);
char *s_gets(char *st, int n);

int main(void)
{
 // 声明一个链表
  List movies;
// 声明一个临时节点
  Item temp;
// 初始化链表
  InitalizeList(&movies);
 // 查看链表是否可以继续创建节点
  if (ListIsFull(&movies))
  {
    fprintf(stderr, "No memory available! Bye!\n");
    exit(EOF);
  }
  puts("Enter first movie title");
// 循环一直输入除非不在进行输入
  while (s_gets(temp.title, TSIZE) != NULL && temp.title[0] != '\0')
  {
    puts("Enter your rating <0-10>");
 // 将输入的数字存入 temp节点的rating属性上
    scanf("%d", &temp.rating);
 // 如果获取到的不是空行
    while (getchar() != '\n')
    {
      continue;
    }
// 将temp加入链表
    if (AddItem(temp, &movies) == false)
    {
      fprintf(stderr, "Problem allocating memory.\n");
      break;
    }
    if (ListIsFull(&movies))
    {
      fprintf(stderr, "List is full.\n");
      break;
    }
    puts("Enter next movie title (empty line to stop);");
  };
  if (ListIsEmpty(&movies))
  {
    printf("No data entered.");
  }
  else
  {
    printf("Here is the movie list :\n");
// 传入一个 链表内存地址 和 含有一个Item参数的函数地址
    Traverse(&movies, showmovies);
  }
  printf("You entered %d movies\n", ListItemCount(&movies));
  EmptyTheList(&movies);
  printf("Bye!\n");

  return 0;
}

void showmovies(Item item)
{
  printf("Movie %s Rating %d\n", item.title, item.rating);
}

char *s_gets(char *st, int n)
{
  char *ret_val;
  char *find;
  ret_val = fgets(st, n, stdin);
  if (ret_val)
  {
    find = strchr(st, '\n');
    if (find)
      *find = '\0';
    else
      while (getchar() != '\n')
        continue;
  }
  return ret_val;
}

标题:C LinkList Demo
作者:ferried
地址:https://blog.eiyouhe.com/articles/2019/12/22/1576996926974.html