【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

 

 

 

 

  

相关文章
|
3月前
|
存储 自然语言处理 编译器
【C语言】编译与链接:深入理解程序构建过程
【C语言】编译与链接:深入理解程序构建过程
|
2月前
|
存储 缓存 算法
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式,强调了合理选择数据结构的重要性,并通过案例分析展示了其在实际项目中的应用,旨在帮助读者提升编程能力。
90 5
|
1月前
|
存储 自然语言处理 Unix
【C语言】C语言 4 个编译过程详解
编译是将源代码转换为目标代码的过程。它是在编译器的帮助下完成的。编译器检查源代码是否存在语法或结构错误,如果源代码没有错误,则生成目标代码。
75 1
|
2月前
|
C语言
C语言编程中,错误处理至关重要,能提升程序的健壮性和可靠性
C语言编程中,错误处理至关重要,能提升程序的健壮性和可靠性。本文探讨了C语言中的错误类型(如语法错误、运行时错误)、基本处理方法(如返回值、全局变量、自定义异常处理)、常见策略(如检查返回值、设置标志位、记录错误信息)及错误处理函数(如perror、strerror)。强调了不忽略错误、保持处理一致性及避免过度处理的重要性,并通过文件操作和网络编程实例展示了错误处理的应用。
85 4
|
2月前
|
并行计算 算法 测试技术
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面,旨在通过综合策略提升程序性能,满足实际需求。
84 1
|
2月前
|
网络协议 物联网 数据处理
C语言在网络通信程序实现中的应用,介绍了网络通信的基本概念、C语言的特点及其在网络通信中的优势
本文探讨了C语言在网络通信程序实现中的应用,介绍了网络通信的基本概念、C语言的特点及其在网络通信中的优势。文章详细讲解了使用C语言实现网络通信程序的基本步骤,包括TCP和UDP通信程序的实现,并讨论了关键技术、优化方法及未来发展趋势,旨在帮助读者掌握C语言在网络通信中的应用技巧。
67 2
|
2月前
|
程序员 C语言
C语言中的指针既强大又具挑战性,它像一把钥匙,开启程序世界的隐秘之门
C语言中的指针既强大又具挑战性,它像一把钥匙,开启程序世界的隐秘之门。本文深入探讨了指针的基本概念、声明方式、动态内存分配、函数参数传递、指针运算及与数组和函数的关系,强调了正确使用指针的重要性,并鼓励读者通过实践掌握这一关键技能。
57 1
|
3月前
|
存储 自然语言处理 编译器
|
3月前
|
C语言
C语言学习笔记-知识点总结上
C语言学习笔记-知识点总结上
109 1
|
3月前
|
自然语言处理 编译器 Linux
C语言中抽象的编译和链接原理
C语言中抽象的编译和链接原理
34 1

热门文章

最新文章