C语言项目篇:二、课程管理系统

         为加强对于C语言的巩固和复习,以实战项目为导向,串起所有C语言的语法,达到活学活用的目的,本篇博客,详细总结利用C语言编码简单编码实现生活中的课程管理系统后台开发的整个过程,学习多文件编程和调试,提高实际的编码开发能力。

目录

一、课程信息结构体设计

二、操作课程的功能函数设计

三、文件操作的函数功能设计

四、函数的具体实现

4.1  文件操作的函数具体实现

4.2  课程管理函数具体实现

五、主函数逻辑代码

六、项目完整代码


整个课程管理系统完成的主要功能如下图所示:

项目描述:

        实现一个简单的课程管理系统,课程的信息主要包括:课程编号、课程名称、授课教师、上课时间、上课地点,为贴近实际,课程信息数据会保存在如上的一个.txt文件中,这样断电后,数据不会丢失,对文件中的数据操作就要用到文件操作的相关知识,每次都是从文件中读取数据,对文件进行操作后,再向文件写入数据,实现永久性的对课程的增删改查。

一、课程信息结构体设计

      由上面的分析可知,描述课程信息主要包括5个结构体成员:课程编号、课程名称、授课教师、上课时间、上课地点,因此,设计如下:


#define MAXSIZE 50typedef struct CourseInfo
{char Id[5];            //课程编号char CourseName[20];   //课程名称char TecherName[15];   //授课教师char CourseTime[40];   //上课时间char Address[5];       //上课地点
}CourseInfo;//定义全局的课程信息数组和记录有效课程信息记录的变量CourseInfo course[MAXSIZE];            //定义课程类型的结构体数组,初始大小为50
int cursize = 0;                      //表示当前的记录个数,数组中有效元素个数

二、操作课程的功能函数设计

根据需求分析,我们主要实现以下几个功能:

  1. 展示课程基本信息
  2. 增加课程
  3. 根据课程名称删除课程
  4. 根据课程名称修改课程
  5. 根据课程名称查找课程
//函数的声明,主要实现课程的增删改查
void listCourse();        //展示课程
void addCourse();        //增加课程
void deleteCourse();    //根据课程名称删除课程
void updateCourse();   //根据课程名称修改课程
int  findCourse();    //根据课程名称查找课程

三、文件操作的函数功能设计

     为实现数据的持久性保存,我们将课程的信息保存到文件中,因此,这便涉及到文件的操作,便需要我们实现以下两个功能:

  1. 从文件中读取数据到内存
  2. 内存向文件写入课程信息数据
//函数的声明
void loadDate(CourseInfo* c, int* cursize);        //将文件数据加载到内存
void saveDate(CourseInfo* c, int* cursize);        //将内存数据保存到文件

四、函数的具体实现

4.1  文件操作的函数具体实现

从文件中读取数据到内存的基本思路:

  1. 打开需要读取的文件
  2. 循环以逗号分隔的形式读取文件的记录数据存放到课程信息的结构体数组中
  3. 关闭文件
//1.将文件数据加载到内存
void loadDate(CourseInfo* c, int* cursize)  //传入结构体指针和记录有效数组元素个数变量的地址
{//1.打开文件FILE* fp = fopen("C:\\Users\\王恒\\Desktop\\courses.txt", "r");if (!fp){printf("文件打开失败!\n");exit(-1);}//2.读取文件数据存放到内存(结构体数组)int i = 0;while (feof(fp) == 0)   //判断是否读取到文件的末尾{fscanf(fp, "%[^,],%[^,],%[^,],%[^,],%[^\n]\n", c[i].Id, c[i].CourseName, c[i].TecherName, c[i].CourseTime, c[i].Address); //fscanf 从文件中逐行读取数据并存储到结构体数组中i++;}*cursize = i;//3.关闭文件fclose(fp);
}

内存向文件写入课程信息数据(输出数据到文件)的基本思路:

  1. 打开需要写入数据的文件
  2. 将数据输出到文件
  3. 关闭文件
//2.将内存的数据保存到文件
void saveDate(CourseInfo* c, int* cursize)
{//1.打开文件FILE* fp = fopen("C:\\Users\\王恒\\Desktop\\courses.txt", "w");if (!fp){printf("文件打开失败!\n");exit(-1);}int size = *cursize;//2.将数据写入文件for (int i = 0; i < size; i++){fprintf(fp, "%s,%s,%s,%s,%s\n", c[i].Id, c[i].CourseName, c[i].TecherName, c[i].CourseTime, c[i].Address);fflush(fp);           //刷新缓冲区}//3.关闭文件fclose(fp);
}

4.2  课程管理函数具体实现

展示课程基本信息基本思路:

  1. 加载数据到内存(结构体数组)
  2. 对结构体数组的元素进行遍历打印
//初始化数据
bool status = false;   //标志位,只需要初始化一次
static void InitData() 
{if (!status){loadDate(course,&cursize);status = true;}
}//函数的具体实现
void listCourse()
{InitData();//从文件读数据到数组loadDate(course, &cursize);for (int i = 0; i < cursize; i++){printf("%s    %-15s %-10s   %-10s     %-10s\n", course[i].Id, course[i].CourseName, course[i].TecherName, course[i].CourseTime, course[i].Address);}printf("\n");}

增加课程的基本思路:

  1. 加载数据到内存(结构体数组)
  2. 输入增加的课程信息数据
  3. 将增加后的课程信息保存到文件中
void addCourse()
{InitData();   //初始化数据printf("请输入课程编号:\n");scanf("%s", course[cursize].Id);printf("请输入课程名称:\n");scanf("%s", course[cursize].CourseName);printf("请输入教师名称:\n");scanf("%s", course[cursize].TecherName);printf("请输入上课时间:\n");scanf("%s", course[cursize].CourseTime);printf("请输入上课地点:\n");scanf("%s", course[cursize].Address);cursize++;//将增加后的课程信息保存到文件中saveDate(course, &cursize);printf("\n");}

根据课程名称删除课程基本思路:

  1. 加载数据到内存(结构体数组)
  2. 遍历结构体数组找该课程,进行数据元素的移动(删除)
  3. 将删除后的课程信息保存到文件中

 

void deleteCourse()
{InitData();            //初始化数据assert(cursize > 0);  //判空操作char s[20] = { 0 };printf("请输入需要删除的课程名称:\n");scanf("%s", s);//1.循环遍历找到该课程int i = 0;for (; i < cursize; i++){if (strcmp(course[i].CourseName, s) == 0){//2.进行数组元素覆盖for (int j = i + 1; j < cursize; j++){course[j - 1] = course[j];         //结构体数组元素整体赋值}//利用内存拷贝函数进行元素删除/*memmove(course + i, course + i + 1, sizeof(CourseInfo) * cursize - 1 - i);memset(&course[cursize-1],0, sizeof(CourseInfo));  将最后一个数组元素清0*/  cursize--;printf("删除成功!\n");break;}}if (i == cursize){printf("未找到该课程,删除失败!\n");printf("\n");}//将删除后的课程信息保存到文件中saveDate(course, &cursize);}

根据课程名称修改课程基本思路:

  1. 加载数据到内存(结构体数组)
  2. 遍历结构体数组找该课程,输入需要修改的课程信息
  3. 将修改后的课程信息保存到文件中
void updateCourse()
{InitData();    //初始化数据assert(cursize > 0);  //判空操作//思路:先根据课程名称找到该课程,然后进行修改其中的成员变量int res=findCourse();if (res == -1){printf("该课程不存在,无法修改!\n");}else{//找到了该课程,且下标为i,对该课程的信息进行修改(成员变量进行修改)printf("请输入需要修改的信息(1-4):1:修改课程编号,2:修改授课教师,3:修改上课时间,4:修改上课地点\n");int choice;char id[10] = {0};char teacher[10] = {0};char time[30] = {0};char address[10] = {0};scanf("%d", &choice);switch (choice){case 1:printf("请输入新的课程编号:\n");scanf("%s", id);strcpy(course[res].Id, id);break;case 2:printf("请输入新的授课教师:\n");scanf("%s", teacher);strcpy(course[res].TecherName, teacher);break;case 3:   printf("请输入新的上课时间:\n");scanf("%s", time);strcpy(course[res].CourseTime, time);break;case 4:printf("请输入新的上课地点:\n");scanf("%s", address);strcpy(course[res].Address, address);break;default:printf("输入有误,请输入1-4");}}//将修改后的课程信息保存到文件中saveDate(course, &cursize);
}

根据课程名称查找课程基本思路:

  1. 加载数据到内存(结构体数组)
  2. 遍历结构体数组找该课程,输出课程信息
int  findCourse()
{InitData();    //初始化数据assert(cursize > 0);  //判空操作char coursename[10] = { 0 };printf("请输入需要查找的课程名称:\n");scanf("%s", coursename);//1.遍历结构体数组int i = 0;for (; i < cursize; i++){if (strcmp(course[i].CourseName, coursename) == 0){break;}}//2.条件判断if (i == cursize){printf("不存在该课程!\n");return -1;}else{printf("该课程存在!\n");//找到该课程,打印该课程对应的信息printf("该课程编号为:%s,该课程授课教师为:%s,该课程上课时间为:%s,该课程上课地点为:%s",course[i].Id,course[i].TecherName,course[i].CourseTime,course[i].Address);printf("\n");return i;}}

五、主函数逻辑代码

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h> 
#include"course.h"//代码的主要逻辑void printmenu()//菜单函数
{printf("   课程管理系统\n");printf("*****************\n");printf("   1.添加课程\n");printf("   2.删除课程\n");printf("   3.查看所有课程\n");printf("   4.根据课程名称搜索\n");printf("   5.修改课程信息\n");printf("   6.退出系统\n");printf("*****************\n");printf("\n");
}int main()
{printmenu();while (1){int choice;printf("请输入你的选择1-6:\n");scanf("%d", &choice);switch (choice){case 1:addCourse();printmenu();break;case 2:deleteCourse();printmenu();break;case 3:listCourse();printmenu();break;case 4:findCourse();	 //根据课程名称查找课程printmenu();break;case 5:updateCourse();   //根据课程名称修改课程信息printmenu();break;case 6:printf("退出系统\n");break;default:printf("输入有误!请输入1-6\n");}}return 0;
}

六、项目完整代码

course.h

#pragma once
#ifndef COURSE_H
#define COURSE_H#define MAXSIZE 50typedef struct CourseInfo
{char Id[5];char CourseName[20];char TecherName[15];char CourseTime[40];char Address[5];
}CourseInfo;//函数的声明,主要实现课程的增删改查void listCourse();        //展示课程
void addCourse();        //增加课程
void deleteCourse();    //根据课程名称删除课程
void updateCourse();   //根据课程名称修改课程
int findCourse();    //根据课程名称查找课程#endif

course.c

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
#include <stdbool.h>   //C语言引入bool类型的头文件
#include "course.h"
#include "fileop.h"
#include <assert.h>
#include <stdlib.h>//定义全局结构体数组和记录有效数组元素个数的变量
CourseInfo course[MAXSIZE];           //定义课程类型的结构体数组,初始大小为50
int cursize = 0;                      //表示当前的记录个数,数组中有效元素个数//初始化数据
bool status = false;  //全局变量
static void InitData()  //加static修饰函数,其他文件无法进行调用
{if (!status){loadDate(course,&cursize);status = true;}
}//函数的具体实现
void listCourse()
{InitData();//从文件读数据到数组loadDate(course, &cursize);for (int i = 0; i < cursize; i++){printf("%s    %-15s %-10s   %-10s     %-10s\n", course[i].Id, course[i].CourseName, course[i].TecherName, course[i].CourseTime, course[i].Address);}printf("\n");}void addCourse()
{InitData();   //初始化数据printf("请输入课程编号:\n");scanf("%s", course[cursize].Id);printf("请输入课程名称:\n");scanf("%s", course[cursize].CourseName);printf("请输入教师名称:\n");scanf("%s", course[cursize].TecherName);printf("请输入上课时间:\n");scanf("%s", course[cursize].CourseTime);printf("请输入上课地点:\n");scanf("%s", course[cursize].Address);cursize++;//将增加后的课程信息保存到文件中saveDate(course, &cursize);printf("\n");}void deleteCourse()
{InitData();            //初始化数据assert(cursize > 0);  //判空操作char s[20] = { 0 };printf("请输入需要删除的课程名称:\n");scanf("%s", s);//1.循环遍历找到该课程int i = 0;for (; i < cursize; i++){if (strcmp(course[i].CourseName, s) == 0){//2.进行数组元素覆盖for (int j = i + 1; j < cursize; j++){course[j - 1] = course[j];         //结构体数组元素整体赋值}//利用内存拷贝函数进行元素删除/*memmove(course + i, course + i + 1, sizeof(CourseInfo) * cursize - 1 - i);memset(&course[cursize-1],0, sizeof(CourseInfo));  将最后一个数组元素清0*/  cursize--;printf("删除成功!\n");break;}}if (i == cursize){printf("未找到该课程,删除失败!\n");printf("\n");}//将删除后的课程信息保存到文件中saveDate(course, &cursize);}void updateCourse()
{InitData();    //初始化数据assert(cursize > 0);  //判空操作//思路:先根据课程名称找到该课程,然后进行修改其中的成员变量int res=findCourse();if (res == -1){printf("该课程不存在,无法修改!\n");}else{//找到了该课程,且下标为i,对该课程的信息进行修改(成员变量进行修改)printf("请输入需要修改的信息(1-4):1:修改课程编号,2:修改授课教师,3:修改上课时间,4:修改上课地点\n");int choice;char id[10] = {0};char teacher[10] = {0};char time[30] = {0};char address[10] = {0};scanf("%d", &choice);switch (choice){case 1:printf("请输入新的课程编号:\n");scanf("%s", id);strcpy(course[res].Id, id);break;case 2:printf("请输入新的授课教师:\n");scanf("%s", teacher);strcpy(course[res].TecherName, teacher);break;case 3:   printf("请输入新的上课时间:\n");scanf("%s", time);strcpy(course[res].CourseTime, time);break;case 4:printf("请输入新的上课地点:\n");scanf("%s", address);strcpy(course[res].Address, address);break;default:printf("输入有误,请输入1-4");}}//将修改后的课程信息保存到文件中saveDate(course, &cursize);
}int  findCourse()
{InitData();    //初始化数据assert(cursize > 0);  //判空操作char coursename[10] = { 0 };printf("请输入需要查找的课程名称:\n");scanf("%s", coursename);//1.遍历结构体数组int i = 0;for (; i < cursize; i++){if (strcmp(course[i].CourseName, coursename) == 0){break;}}//2.条件判断if (i == cursize){printf("不存在该课程!\n");return -1;}else{printf("该课程存在!\n");//找到该课程,打印该课程对应的信息printf("该课程编号为:%s,该课程授课教师为:%s,该课程上课时间为:%s,该课程上课地点为:%s",course[i].Id,course[i].TecherName,course[i].CourseTime,course[i].Address);printf("\n");return i;}}

fileop.h

#pragma once
#ifndef FILE_OP_H
#define FILE_OP_H#include"course.h"//函数的声明
void loadDate(CourseInfo* c, int* cursize);        //将文件数据加载到内存
void saveDate(CourseInfo* c, int* cursize);        //将内存数据保存到文件
#endif 

fileop.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"fileop.h"#include<stdlib.h>
#include<stdio.h>   //写在.c文件中//函数的具体实现//1.将文件数据加载到内存
void loadDate(CourseInfo* c, int* cursize)  //传入结构体指针和记录有效数组元素个数变量的地址
{//1.打开文件FILE* fp = fopen("C:\\Users\\王恒\\Desktop\\courses.txt", "r");if (!fp){printf("文件打开失败!\n");exit(-1);}//2.读取文件数据存放到内存(结构体数组)int i = 0;while (feof(fp) == 0)   //判断是否读取到文件的末尾{fscanf(fp, "%[^,],%[^,],%[^,],%[^,],%[^\n]\n", c[i].Id, c[i].CourseName, c[i].TecherName, c[i].CourseTime, c[i].Address); //fscanf 从文件中逐行读取数据并存储到结构体数组中i++;}*cursize = i;//3.关闭文件fclose(fp);
}//2.将内存的数据保存到文件
void saveDate(CourseInfo* c, int* cursize)
{//1.打开文件FILE* fp = fopen("C:\\Users\\王恒\\Desktop\\courses.txt", "w");if (!fp){printf("文件打开失败!\n");exit(-1);}int size = *cursize;//2.将数据写入文件for (int i = 0; i < size; i++){fprintf(fp, "%s,%s,%s,%s,%s\n", c[i].Id, c[i].CourseName, c[i].TecherName, c[i].CourseTime, c[i].Address);fflush(fp);}//3.关闭文件fclose(fp);
}

     至此,整个项目就结束了,可以看出项目的整体逻辑比较简单,可以用来训练我们的编码逻辑思维,逐步训练就可以达到实际开发的高度!如果喜欢,点赞加关注!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/48673.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Internet 控制报文协议 —— ICMPv4 和 ICMPv6 详解

ICMP 是一种面向无连接的协议&#xff0c;负责传递可能需要注意的差错和控制报文&#xff0c;差错指示通信网络是否存在错误 (如目的主机无法到达、IP 路由器无法正常传输数据包等。注意&#xff0c;路由器缓冲区溢出导致的丢包不包括在 ICMP 响应范围内&#xff0c;在 TCP 负责…

Docker、containerd、CRI-O 和 runc 之间的区别

容器与 Docker 这个名称并不紧密相关。你可以使用其他工具来运行容器 您可以使用 Docker 或一堆非Docker 的其他工具来运行容器。docker只是众多选项之一&#xff0c;Docker&#xff08;公司&#xff09;在生态系统中创建了一些很棒的工具&#xff0c;但不是全部。 容器方面有…

利用【MATLAB】和【Python】进行【图与网络模型】的高级应用与分析】

目录 一、图与网络的基本概念 1. 无向图与有向图 2. 简单图、完全图、赋权图 3. 顶点的度 4. 子图与连通性 5. 图的矩阵表示 MATLAB代码实例 Python代码实例 二、最短路径问题 1. 最短路径问题的定义 2. Dijkstra算法 MATLAB代码实例 Python代码实例 三、最小生…

无法启动此程序,因为计算机丢失api-ms-win-core-path-l1-1-0.dll的解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

Microsoft Visual C++ 2010 Express 使用

Microsoft Visual C 2010 Express 使用 Microsoft Visual C 2010 Express&#xff08;简称VC 2010 Express&#xff09;是一款免费的集成开发环境&#xff08;IDE&#xff09;&#xff0c;专为C和C语言的开发者设计。 安装 下载|本站链接【VC2010简体中文版】的安装包并解压…

C#学习-刘铁猛

文章目录 1.委托委托的具体使用-魔板方法回调方法【好莱坞方法】&#xff1a;通过委托类型的参数&#xff0c;传入主调方法的被调用方法&#xff0c;主调方法可以根据自己的逻辑决定调用这个方法还是不调用这个方法。【演员只用接听电话&#xff0c;如果通过&#xff0c;导演会…

mysql oracle postgreSQL区别

MySQL、Oracle Database和PostgreSQL是三种流行的关系型数据库管理系统&#xff08;RDBMS&#xff09;&#xff0c;它们各有特点&#xff0c;适用于不同的应用场景。以下是它们之间的一些主要区别&#xff1a; 1.许可证和成本&#xff1a; 1.MySQL是一个开源数据库&#xff0c;…

一个集Swagger2 和 OpenAPI3为一体的增强接口文档工具,一把为您的API文档需求量身定制的“利刃”(附源码)

前言 在微服务和分布式系统架构日益普及的今天&#xff0c;API文档的管理与维护成为了开发过程中的一个关键环节。开发者们常常面临着API文档更新不及时、格式不统一、难以维护和阅读的问题。此外&#xff0c;随着API数量的增加&#xff0c;管理和维护这些文档变得越来越复杂。…

unity2022 il2cpp 源码编译

新建一个XCODE静态库工程 从unity安装目录中找到il2cpp源码 Editor\Data\il2cpp\ 改名 il2cpp/libil2cpp -> il2cpp/il2cpp 加入工程中 ->工程根目录 extends/zlib libil2cpp/ buildSettings 相关设置 IOS Deployment Target ios 12.0 Header Search Paths $(in…

Anthropic的Claude安卓版能否赢得用户青睐?

Anthropic的Claude安卓版能否赢得用户青睐&#xff1f; 前言 Anthropic 就在7月18日&#xff0c;这家以"可控AI"著称的初创公司再次出手&#xff0c;推出了Claude的Android版本应用。这款APP不仅支持实时语言翻译&#xff0c;更传承了Anthropic一贯的隐私保护政策。C…

C++游戏时间——Maker_Game游戏头文件组1.0

我们都知道,C++可以写控制台、图形界面、静态库程序。 这几天,我写游戏都写炸毛了,但对于对静态库一窍不通的我,只能写图形库和控制台。 于是。。。。 Maker_Game游戏头文件组1.0诞生了! #include <Maker_Game/Ege.h> #include <Maker_Game/Console.h> Co…

基于SpringBoot+Vue的校园志愿者管理系统(带1w+文档)

基于SpringBootVue的校园志愿者管理系统(带1w文档) 基于SpringBootVue的校园志愿者管理系统(带1w文档) 本次设计任务是要设计一个校园志愿者管理系统&#xff0c;通过这个系统能够满足管理员和志愿者的校园志愿者信息管理功能。系统的主要功能包括首页、个人中心、志愿者管理、…

pytorch学习(十六)conda和pytorch的安装

1.安装anaconda 1.1 首先下载安装包 1&#xff09;进入anaconda官网 Anaconda | The Operating System for AI 2&#xff09;注册一下 3&#xff09;下载 4&#xff09;一直点直到安装完 5&#xff09;配置环境变量 在path路径中加入 Anaconda安装路径 Anaconda安装路径\S…

LeetCode 123题: 买卖股票的最佳时机 III代码优化(原创)

之前完成了LeetCode 123题&#xff1a; 买卖股票的最佳时机 III&#xff08;原创&#xff09;-CSDN博客&#xff0c;虽然完成代码编写&#xff0c;并提交成功&#xff0c;但运行效率不是很高。执行时长高达62ms&#xff0c;见下图&#xff1a; 看了下代码感觉可以通过将三维数组…

提交(git-add git-commit git-push)

当修改好一个功能的时候&#xff0c;可以提交到远程仓库&#xff0c;这样就等于更新了一次版本&#xff0c;那么下次改修了文件的话&#xff0c;是跟这个版本做对比的 git status&#xff0c; 查看文件修改情况&#xff0c;git add 假如你只想提交1个文件&#xff0c;那么直接…

IOC、DI<5> Unity、AOP、延迟获取对象、检索容器中注册信息

Unity.InterceptionExtension.ICallHandler实现一个操作日志记录功能 其它跟上一次一样 <?xml version"1.0" encoding"utf-8" ?> <configuration><configSections><section name"unity" type"Microsoft.Practice…

新手入门python该如何开始学习?学习路线是什么呢?

今天这篇文章从三个点给大家介绍一下新手学习Python的正确路线是什么、python最核心的知识点是什么 Python学习路线 Python学习路线可以大致分为以下几个阶段&#xff0c;每个阶段都包含了一系列核心知识点和技能&#xff1a; 第一阶段&#xff1a;Python基础 Python语言基础…

扫描某个网段下存活的IP:fping

前言&#xff1a; 之前用arp统计过某网段下的ip&#xff0c;但是有可能统计不全。网络管理平台又不允许登录。想要知道当前的ip占用情况&#xff0c;可以使用fping fping命令类似于ping&#xff0c;但比ping更强大。与ping需要等待某一主机连接超时或发回反馈信息不同&#x…

递归与迭代

1. 概念区别 递归&#xff08;recursion&#xff09;&#xff1a;递归常被用来描述以自相似方法重复事物的过程&#xff0c;在数学和计算机科学中&#xff0c;指的是在函数定义中使用函数自身的方法。&#xff08;A调用A&#xff09; 迭代&#xff08;iteration&#xff09;&…

nodejs学习之Rollup

官网 https://github.com/rollup/rollup 英文文档 中文文档 是什么 Rollup 是一个用于 JavaScript 的模块打包工具&#xff0c;它将小的代码片段编译成更大、更复杂的代码&#xff0c;例如库或应用程序。它使用 JavaScript 的 ES6 版本中包含的新标准化代码模块格式&#xf…