【C语言】学习笔记11——简单链表及多文件程序编译(windows下)

1. 在Windows下需要在一个工程project下才能进行多文件编译。用的IDE是Dev c++ 5.11

 

简单介绍:

  .h 文件:主要是结构定义,函数签名, 每个 .h 文件必须有一个同名 .c 文件, 是对 .h 文件函数签名的具体实现

代码

list.h

/* list.h */
/*简单链表类型的头文件*/

#ifndef LIST_H_
#define LIST_H_
#include <stdbool.h>    // C99特性 

#define TSIZE  45
struct film 
{
    int rating;
    char title[45];
}; 

/*一般类型定义*/
typedef struct film Item;

typedef struct node
{
    Item item;
    struct node * next;
} Node;

typedef Node * List;

/* 函数原型 */

/*
操作: 初始化一个链表
前提条件: plist指向一个链表
后置条件: 链表初始化为空 
*/ 

void InitializeList(List * plist);

/*
操作:确定链表是否为空定义,plsit指向一个已初始化的链表
后置条件:如果链表为空, 则该函数返回真,否则返回假 
*/ 
bool ListIsEmpty(const List * plist);
 
 
 /*
 操作: 确定链表是否已满, plist指向一个已初始化的链表
 后置条件: 如果链表已满, 返回真,否则返回假 
 */
 bool ListIsFull(const List * plist);
 
/*
操作: 确定链表中的项数, pList指向一个已初始化的链表
后置条件: 返回链表中的项数 
*/ 
unsigned int ListItemCount(const List * plist);

/*
操作: 在链表的末尾添加项
前提条件: item是一个待添加至链表的项, pList指向一个已初始化的链表
后置条件: 如果可以,将item添加到链表末尾,返回true,否则返回false 
*/ 
bool AddItem(Item item, List * plist);

/*
操作: 把函数作用于链表中的每一项
        pList指向一个已初始化的链表 
        pfun指向一个函数,该函数接受一个Item类型的参数, 且无返回值
后置条件: pfun指向的函数作用于链表中的每一项一次 
*/ 
void Traverse(const List *plist, void (*pfun)(Item item));

/*
操作:  释放已分配的内存 (如果有的话)
       pList指向一个已初始化的链表 
后置条件: 释放为链表分配的所有内存, 链表设置为空。 
*/ 
void EmptyTheList(List * plist);

#endif 

list.c

/* list.c */
/*支持链表操作的函数*/

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

static void CopyToNode(Item item, Node * pnode);

/*接口函数*/
/*表链表设置为空*/
void InitializeList(List * plist)
{
    *plist = NULL;
}


/* 如果链表为空,返回true */
bool ListIsEmpty(const List * plist)
{
    return plist == NULL; 
} 
 
 
 /* 如果链表已满, 返回真,否则返回假 */
 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; 
} 

/* 创建存储项的节点, 并将其添加至由plist指向的列表的末尾*/ 
bool AddItem(Item item, List * plist)
{
    Node * pnew;
    Node * scan = * plist;
    
    pnew = (Node *)malloc(sizeof(Node));
    if(pnew == NULL)
        return false;   //分配存储空间失败,退出,并返回false
    
    CopyToNode(item, pnew);
    pnew->next = NULL;
    if (scan == NULL)
        *plist = pnew;
    else
    {
        while (scan->next != NULL)
            scan = scan->next;
        scan->next = pnew;
    }
    return true;
    
}

/* 访问每一个节点并执行 pfun 指向的函数*/ 
void Traverse(const List *plist, void (*pfun)(Item item))
{
    Node *pnode = *plist;
    
    while (pnode != NULL)
    {
        (*pfun)(pnode->item);
        pnode = pnode->next;
    }

}

/* 释放由 malloc() 分配的内存, 设置链表指针为 NULL */ 
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

/* movie.c */
/* 使用链表 */

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

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

int main()
{
    List movies;
    Item temp;
    
    // 初始化
    InitializeList(&movies);
    if (ListIsFull(&movies))
    {
        fprintf(stderr, "No memory available! Bye!\n");
        exit(1);
    }
    
    /* 获取用户输入并存储 */
    puts("Enter first movie title:");
    while (s_gets(temp.title, TSIZE) != NULL && temp.title[0] != '\0')
    {
        puts("Enter your rating <0-10>:");
        scanf("%d", &temp.rating);
        while(getchar() != '\n')
            continue;
        if (AddItem(temp, &movies) == false)
        {
            fprintf(stderr, "Problem allocating memory\n");
            break;
        }
        if(ListIsFull(&movies))
        {
            puts("The list is now full.");
            break;
        }
        puts("Enter next movie title (empty line to stop):");
    }
    if(ListIsEmpty(&movies))
        printf("No data entered. ");
    else
    {
        printf("Here is the mpvie list:\n");
        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)            //如果地址不是NULL 
            *find = '\0';   //在此放置一个空字符
        else
            while (getchar() != '\n')
                continue;    //处理输入行中剩余的字符 
     }
     return ret_val;
 }
 
 /*
 output:
 Enter first movie title:
weqer
Enter your rating <0-10>:
5
Enter next movie title (empty line to stop):
e212e
Enter your rating <0-10>:
6
Enter next movie title (empty line to stop):

Here is the mpvie list:
Movie: weqer, Rating: 5
Movie: e212e, Rating: 6
You entered 2 movies.
Bye!

 */

文件之间的关系, 我用的不是film3.c,是movie.c

 

 

 

 

  

posted @ 2018-09-08 16:56  早起的虫儿去吃鸟  阅读(622)  评论(0编辑  收藏  举报