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

简介: 1. 在Windows下需要在一个工程project下才能进行多文件编译。用的IDE是Dev c++ 5.11   简单介绍:   .h 文件:主要是结构定义,函数签名, 每个 .h 文件必须有一个同名 .

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

 

 

 

 

  

相关文章
|
5天前
|
存储 C语言
【数据结构】手把手教你单链表(c语言)(附源码)
本文介绍了单链表的基本概念、结构定义及其实现方法。单链表是一种内存地址不连续但逻辑顺序连续的数据结构,每个节点包含数据域和指针域。文章详细讲解了单链表的常见操作,如头插、尾插、头删、尾删、查找、指定位置插入和删除等,并提供了完整的C语言代码示例。通过学习单链表,可以更好地理解数据结构的底层逻辑,提高编程能力。
27 4
|
24天前
|
Windows
重装系统学习笔记(一):Windows10重装步骤(正版)
这篇博客文章详细介绍了如何使用微软官方工具重装Windows 10系统,包括下载安装工具、准备U盘、设置BIOS以及系统安装的步骤。
34 0
重装系统学习笔记(一):Windows10重装步骤(正版)
|
26天前
|
存储 缓存 C语言
C语言:链表和数组有什么区别
C语言中,链表和数组是两种常用的数据结构。数组是一种线性结构,元素在内存中连续存储,通过下标访问,适合随机访问且大小固定的情况。链表由一系列不连续的节点组成,每个节点存储数据和指向下一个节点的指针,适用于频繁插入和删除操作的场景,链表的大小可以动态变化。
|
5天前
|
C语言
【数据结构】双向带头循环链表(c语言)(附源码)
本文介绍了双向带头循环链表的概念和实现。双向带头循环链表具有三个关键点:双向、带头和循环。与单链表相比,它的头插、尾插、头删、尾删等操作的时间复杂度均为O(1),提高了运行效率。文章详细讲解了链表的结构定义、方法声明和实现,包括创建新节点、初始化、打印、判断是否为空、插入和删除节点等操作。最后提供了完整的代码示例。
20 0
|
27天前
|
C语言
C语言学习笔记-知识点总结上
C语言学习笔记-知识点总结上
62 1
|
27天前
|
C语言
无头链表再封装方式实现 (C语言描述)
如何在C语言中实现无头链表的再封装,包括创建节点和链表、插入和删除操作、查找和打印链表以及销毁链表的函数。
26 0
|
27天前
|
C语言
C语言链式结构之有头单链表再封装写法
本文介绍了如何使用C语言对有头单链表进行封装,包括节点的创建、链表的初始化、数据的插入和删除,以及链表的打印等功能。
15 1
|
27天前
|
C语言
C语言结构体链式结构之有头单链表
文章提供了一个C语言实现的有头单链表的完整代码,包括创建链表、插入、删除和打印等基本操作。
20 1
|
25天前
|
存储 文件存储 C语言
深入C语言:文件操作实现局外影响程序
深入C语言:文件操作实现局外影响程序
|
27天前
|
C语言
无头链表二级指针方式实现(C语言描述)
本文介绍了如何在C语言中使用二级指针实现无头链表,并提供了创建节点、插入、删除、查找、销毁链表等操作的函数实现,以及一个示例程序来演示这些操作。
19 0