【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

 

 

 

 

  

相关文章
|
23天前
|
存储 算法 C语言
"揭秘C语言中的王者之树——红黑树:一场数据结构与算法的华丽舞蹈,让你的程序效率飙升,直击性能巅峰!"
【8月更文挑战第20天】红黑树是自平衡二叉查找树,通过旋转和重着色保持平衡,确保高效执行插入、删除和查找操作,时间复杂度为O(log n)。本文介绍红黑树的基本属性、存储结构及其C语言实现。红黑树遵循五项基本规则以保持平衡状态。在C语言中,节点包含数据、颜色、父节点和子节点指针。文章提供了一个示例代码框架,用于创建节点、插入节点并执行必要的修复操作以维护红黑树的特性。
45 1
|
23天前
|
NoSQL 编译器 程序员
【C语言】揭秘GCC:从平凡到卓越的编译艺术,一场代码与效率的激情碰撞,探索那些不为人知的秘密武器,让你的程序瞬间提速百倍!
【8月更文挑战第20天】GCC,GNU Compiler Collection,是GNU项目中的开源编译器集合,支持C、C++等多种语言。作为C语言程序员的重要工具,GCC具备跨平台性、高度可配置性及丰富的优化选项等特点。通过简单示例,如编译“Hello, GCC!”程序 (`gcc -o hello hello.c`),展示了GCC的基础用法及不同优化级别(`-O0`, `-O1`, `-O3`)对性能的影响。GCC还支持生成调试信息(`-g`),便于使用GDB等工具进行调试。尽管有如Microsoft Visual C++、Clang等竞品,GCC仍因其灵活性和强大的功能被广泛采用。
49 1
|
20天前
|
编译器 C语言 计算机视觉
C语言实现的图像处理程序
C语言实现的图像处理程序
42 0
|
4天前
|
存储 编译器 程序员
C语言程序的基本结构
C语言程序的基本结构包括:1)预处理指令,如 `#include` 和 `#define`;2)主函数 `main()`,程序从这里开始执行;3)函数声明与定义,执行特定任务的代码块;4)变量声明与初始化,用于存储数据;5)语句和表达式,构成程序基本执行单位;6)注释,解释代码功能。示例代码展示了这些组成部分的应用。
22 10
|
2天前
|
存储 C语言
C语言程序设计核心详解 第九章 结构体与链表概要详解
本文档详细介绍了C语言中的结构体与链表。首先,讲解了结构体的定义、初始化及使用方法,并演示了如何通过不同方式定义结构体变量。接着,介绍了指向结构体的指针及其应用,包括结构体变量和结构体数组的指针操作。随后,概述了链表的概念与定义,解释了链表的基本操作如动态分配、插入和删除。最后,简述了共用体类型及其变量定义与引用方法。通过本文档,读者可以全面了解结构体与链表的基础知识及实际应用技巧。
|
2天前
|
存储 算法 C语言
C语言手撕实战代码_循环单链表和循环双链表
本文档详细介绍了用C语言实现循环单链表和循环双链表的相关算法。包括循环单链表的建立、逆转、左移、拆分及合并等操作;以及双链表的建立、遍历、排序和循环双链表的重组。通过具体示例和代码片段,展示了每种算法的实现思路与步骤,帮助读者深入理解并掌握这些数据结构的基本操作方法。
|
8天前
|
存储 测试技术 C语言
C语言实现链表的各种功能
本文详细介绍了如何使用C语言实现链表的各种功能,包括链表节点结构的定义与操作函数的实现。链表作为一种常用的数据结构,具有节点自由插入删除、动态变化等特点。文中通过`link_list.h`和`link_list.c`两个文件,实现了链表的初始化、插入、删除、查找、修改等核心功能,并在`main.c`中进行了功能测试。这些代码不仅展示了链表的基本操作,还提供了丰富的注释帮助理解,适合作为学习链表的入门资料。
|
2天前
|
存储 C语言
C语言程序设计核心详解 第十章:位运算和c语言文件操作详解_文件操作函数
本文详细介绍了C语言中的位运算和文件操作。位运算包括按位与、或、异或、取反、左移和右移等六种运算符及其复合赋值运算符,每种运算符的功能和应用场景都有具体说明。文件操作部分则涵盖了文件的概念、分类、文件类型指针、文件的打开与关闭、读写操作及当前读写位置的调整等内容,提供了丰富的示例帮助理解。通过对本文的学习,读者可以全面掌握C语言中的位运算和文件处理技术。
|
2天前
|
存储 C语言
C语言程序设计核心详解 第七章 函数和预编译命令
本章介绍C语言中的函数定义与使用,以及预编译命令。主要内容包括函数的定义格式、调用方式和示例分析。C程序结构分为`main()`单框架或多子函数框架。函数不能嵌套定义但可互相调用。变量具有类型、作用范围和存储类别三种属性,其中作用范围分为局部和全局。预编译命令包括文件包含和宏定义,宏定义分为无参和带参两种形式。此外,还介绍了变量的存储类别及其特点。通过实例详细解析了函数调用过程及宏定义的应用。
|
8天前
|
Linux C语言
C语言 多进程编程(三)信号处理方式和自定义处理函数
本文详细介绍了Linux系统中进程间通信的关键机制——信号。首先解释了信号作为一种异步通知机制的特点及其主要来源,接着列举了常见的信号类型及其定义。文章进一步探讨了信号的处理流程和Linux中处理信号的方式,包括忽略信号、捕捉信号以及执行默认操作。此外,通过具体示例演示了如何创建子进程并通过信号进行控制。最后,讲解了如何通过`signal`函数自定义信号处理函数,并提供了完整的示例代码,展示了父子进程之间通过信号进行通信的过程。