经过对c语言的系统学习,我能够初步的做一个管理系统,含有结构体,链表,文件等内容。基于个人爱好,我做了一个春晚节目管理系统,包含链表的增,删,查,改,节目的排序,字体颜色设置等等,并且界面整齐美观。
在此,我将分块将重要的代码部分展示出,且代码中有详细注释,并附上运行结果。
一.预处理模块
#define DEFAULT_SZ 10
#define NAME_MAX 20 //内容限度定义
#define STYLE_MAX 10
#define PLAYER_MAX 20
#define THEME_MAX 20
#define MAX 30
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <windows.h> //system("color 0b")所在的头文件
struct ProInfo {
char name[NAME_MAX];//节目名称
char style[STYLE_MAX];//节目类型
float minute;//节目时长(分钟)
char player[PLAYER_MAX];//表演者姓名
char theme[THEME_MAX];//节目主题
};
//动态节目单版本
struct Program {
struct ProInfo *next;
int sz;//节目个数记录
int capacity;
};
// 初始化节目单
void InitProgram(struct Program *pc);
//增加节目的信息
void AddProgram(struct Program *pc);
//显示节目单
void ShowProgram(struct Program *pc);
//删除指定节目
void DelProgram(struct Program *pc);
//查找指定节目
void SearchProgram(struct Program *pc);
//修改指定节目
void ModifyProgram(struct Program *pc);
//销毁节目单
void DestroyProgram(struct Program *pc);
//退出时保存信息到文件
void SaveProgram(struct Program *pc);
//打开时加载上次保存的信息
void LoadProgram(struct Program *pc);
//扩容
void CheckCapacity(struct Program *pc);
void ChangeColor(short x);//改变字体颜色
void Sort(struct Program *pc); //排序
上面实现一个next结构体指针,指向节目信息结构体,实现一个当前有效节目信息个数sz,实现一个当前节目单最大节目容量capacity.
二. 菜单函数
void menu() { //起始菜单展示
system("cls");
printf("\n\n");
printf("\t\t\t\t~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \n");
printf("\t\t\t\t$\t 欢迎进入我的专属春晚节目单! $\n");
printf("\t\t\t\t$~~~~~~~~~~~~~~~~~Spring Festival Gala~~~~~~~~~~~~~~~~~~~$\n"); //\t为水平制表符,空格较大,但容易掌控,也可用空格代替
printf("\t\t\t\t$\t $\n");
printf("\t\t\t\t$\t 0.退出登录 4.修改节目信息 $\n");
printf("\t\t\t\t$\t 1.录入节目 5.删减节目 $\n");
printf("\t\t\t\t$\t 2.查找节目 6.显示节目信息 $\n");
printf("\t\t\t\t$\t 3.节目排序 7.界面模式设置 $\n");
printf("\t\t\t\t$\t $\n");
printf("\t\t\t\t~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \n");
}
运行结果
三.动态开辟
//动态开辟的版本
void InitProgram(struct Program *pc) { //初始化节目单
pc->sz = 0;
pc->next = malloc(DEFAULT_SZ * sizeof(struct ProInfo));
pc->capacity = DEFAULT_SZ; // 3
LoadProgram(pc);
}
最初宏定义的DEFAULT_SZ为10,则malloc函数实现一开始动态内存开辟10个节目的空间大小,
一开始最大容量capacity 置为10.
三.节目录入函数
void AddProgram(struct Program *pc) { //节目录入函数
struct Program tmp = { 0 };
if (pc->sz == MAX) {
printf("节目单可用空间已满\n");
} else {
printf("\n\n\n\n\n");
printf("\t\t请输入节目名称:----------------- ");
scanf("%s", pc->next[pc->sz].name);
printf("\t\t请输入节目类型:----------------- ");
scanf("%s", pc->next[pc->sz].style);
printf("\t\t请输入节目时长:----------------- ");
scanf("%f", &(pc->next[pc->sz].minute));
printf("\t\t请输入表演者姓名:--------------- ");
scanf("%s", pc->next[pc->sz].player);
printf("\t\t请输入节目主题:----------------- ");
scanf("%s", pc->next[pc->sz].theme);
printf("\n\n");
printf("\t\t\t\t\t\t添加成功!\n");
pc->sz++;
}
}
用pc->next[pc->sz].xxx找到各节目信息位置,将信息存入后有效节目个数sz++,实现对下一个节目信息的存放。
运行结果
四.列表展示函数
void ShowProgram(struct Program *pc) { //节目信息列表展示函数
int i = 0;
printf("\n\n\n");//为了使做出的界面整齐美观
printf("\t\t———————————————————————————————————————————————————————————————————————————————————\n");
printf("\t\t\t\t\t\t 节目信息列表 \t\t\t\n");
printf("\t\t———————————————————————————————————————————————————————————————————————————————————\n");
printf("\t\t 节目名称 节目类型 节目时长 表演者姓名 节目主题\n");
printf("\t\t———————————————————————————————————————————————————————————————————————————————————\n");
for (i = 0; i < pc->sz; i++) {
printf("\t\t%12s\t %-5s\t %-5g %-12s\t%-8s\n",
pc->next[i].name,
pc->next[i].style,
pc->next[i].minute,
pc->next[i].player,
pc->next[i].theme);
}
printf("\t\t———————————————————————————————————————————————————————————————————————————————————\n");
}
运行结果
五.节目查找函数
int FindProgramByName(const struct Program *pc, const char *name) {
int i = 0;
for (i = 0; i < pc->sz; i++) {
if (strcmp(pc->next[i].name, name) == 0) {
return i;
}
}
return -1;
}
void SearchProgram( struct Program *pc) {//节目查找函数
char name[NAME_MAX] = { 0 };
printf("\n\n\n\n\n");
printf("\t\t\t请输入要查找的节目的名字: ");
scanf("%s", name);
int pos = FindProgramByName(pc, name);//对特殊情况的处理
if (pos == -1) {
printf("没有查到该节目\n");
} else {
printf("\n\n\n");
printf("\t%15s\t%5s\t%s\t%15s\t%15s\n",
"节目名称", "节目类型", "节目时长", "表演者姓名", "节目主题");
printf("\n");
printf("\t\t %8s\t%-5s\t %-5g\t%-12s\t %-8s\n",
pc->next[pos].name,
pc->next[pos].style,
pc->next[pos].minute,
pc->next[pos].player,
pc->next[pos].theme);
}
}
strcmp库函数实现对字符串的比较,相同就返回数字0,代表查找成功,返回位置i即可,找不到就返回-1.
运行结果
六.删除节目
void DelProgram(struct Program *pc) { //节目信息删除函数
printf("\n\n\n\n\n");
if (pc->sz == 0) {
printf("节目单为空,无法删除\n");
return;
}
char name[20] = {0};
printf("请输入要删除节目的名字: ");
scanf("%s", name);
// 查找
int pos = FindProgramByName(pc, name);//前一个函数的返回值为此做铺垫
if (pos == -1) {
printf("要删除的节目不存在\n");
} else {
// 删除
//将数组中要被删除的元素后面的元素相应向前放
int j = 0;
for (j = pos; j < pc->sz - 1; j++) {
pc->next[j] = pc->next[j + 1];
}
pc->sz--;
printf("\t\t\t\t\t删除成功\n");
}
}
七.节目修改函数
void ModifyProgram(struct Program *pc) { //修改节目
char name[NAME_MAX] = { 0 };
int code;
printf("\n\n\n");
printf("\t\t\t请输入要修改的节目的名字: ");
scanf("%s", name);
int pos = FindProgramByName(pc, name);
if (pos == -1) {
printf("\t\t\t要修改的节目不存在\n");
} else {
printf("\t\t\t请选择要修改的节目信息代码(1.节目名称2.节目类型3.节目时长4.表演者姓名5.节目主题):\n");
scanf("%d", &code);
printf("\n");
switch (code) { //switch语句选择要修改的项目
case 1:
printf("\t\t\t请输入修改后的节目名称:");
scanf("%s", pc->next[pos].name);
break;
case 2:
printf("\t\t\t请输入修改后的节目类型:");
scanf("%s", pc->next[pos].style);
break;
case 3:
printf("\t\t\t请输入修改后的节目时长:");
scanf("%f", &(pc->next[pos].minute));
break;
case 4:
printf("\t\t\t请输入修改后的表演者姓名:");
scanf("%s", pc->next[pos].player);
break;
case 5:
printf("\t\t\t请输入修改后的节目主题:");
scanf("%s", pc->next[pos].theme);
}
printf("修改成功!\n");
}
}
八.销毁链表
void DestroyProgram(struct Program *pc) { //销毁链表
free(pc->next); //将所有结点释放
pc->next = NULL;
pc->sz = 0;//使内存为零
pc->capacity = 0;
}
九.节目保存函数
void SaveProgram(struct Program *pc) { //节目信息保存函数,该保存函数单独设立,节约代码行数,方便管理
FILE *pf = fopen("springgala.txt", "w");//文件命名
if (pf == NULL) {
perror("fopen"); //perror是专门打印出错信息的库函数
return;
}
int i = 0;
for (i = 0; i < pc->sz; i++) { //将结点信息逐一写入文件
fwrite(&(pc->next[i]), sizeof(struct ProInfo), 1, pf);
}
fclose(pf);//关闭文件
pf = NULL;
}
十.加载信息和扩容函数
void LoadProgram(struct Program *pc) { //加载节目信息
FILE *pf = fopen("springgala.txt", "r"); //r为只读,如果不懂,可以去搜文件的相关知识
if (pf == NULL) {
perror("fopen");
return;
}
struct ProInfo tmp = {0};
while (fread(&tmp, sizeof(struct ProInfo), 1, pf)) {
CheckCapacity(pc);//空间不够的话,得增加空间
pc->next[pc->sz] = tmp;
pc->sz++;
}
fclose(pf);
pf = NULL;
}
void CheckCapacity(struct Program *pc) { //扩容函数
if (pc->sz == pc->capacity) {
struct ProInfo *ptr = (struct ProInfo *)realloc(pc->next, (pc->capacity + 2) * sizeof(struct ProInfo));
if (ptr != NULL) {
pc->next = ptr;
pc->capacity += 2;
printf("扩容成功!\n");
} else {
printf(" 节目单增容失败");
exit(1);
}
}
}
十一.字体颜色设置函数
void ChangeColor(short x) { //字体颜色设置函数
printf("\n\n\n\n");
printf("\t\t\t请输入你想设置的颜色模式:\n");
printf("\n");
printf("\t\t\t(0:黑色 1:蓝色 2:绿色 3:湖蓝 4:红色 5:紫色 6:黄色 7:白色 8:灰色 9:淡蓝):");
scanf("%d", &x);
switch (x) {
case 0:
system("color 00"); //该函数是windows.h下的库函数,里面数字代码的改变可以实现字体颜色的整体改变
break;
case 1:
system("color 01");
break;
case 2:
system("color 02");
break;
case 3:
system("color 03");
break;
case 4:
system("color 04");
break;
case 5:
system("color 05");
break;
case 6:
system("color 06");
break;
case 7:
system("color 07");
break;
case 8:
system("color 08");
break;
case 9:
system("color 09");
break;
}
printf("\n");
printf("\t\t\t设置成功!");
}
标准库中定义了好多的颜色常量,代码中列举了几个常见的。
十二.排序函数
void Sort(struct Program *pc) { //排序函数
struct ProInfo temp; //定义一个中间变量的结点
int code;
printf("请输入你要排序的内容:1.节目名称 2.节目时长(升序):\n");
scanf("%d", &code);
switch (code) { //即可按节目的拼音顺序排序,也可按时长由小到大排序,都为冒泡排序
case 1:
for (int i = 0; i < pc->sz - 1; i++) {
for (int j = 0; j < pc->sz - 1 - i; j++) {
if (strcmp(pc->next[j].name, pc->next[j + 1].name) > 0) {
temp = pc->next[j]; //strcmp为字符串比较函数,在string.h头文件中,若a>b,则(a,b)>0.
pc->next[j] = pc->next[j + 1];
pc->next[j + 1] = temp;
}
}
}
printf("\t\t\t\t排序成功!");
break;
case 2:
for (int i = 0; i < pc->sz - 1; i++) {
for (int j = 0; j < pc->sz - 1 - i; j++) {
if (pc->next[j].minute > pc->next[j + 1].minute) {//比较的内容是float型,就不能用strcmp函数
temp = pc->next[j];
pc->next[j] = pc->next[j + 1];
pc->next[j + 1] = temp;
}
}
}
printf("\t\t\t\t排序成功!");
break;
}
}
两个冒泡排序,一个比较数,一个比较字符串。
十三.主函数
int main() { //主函数
char password[10];
printf("\n\n\n\n\n\n"); //密码登录
printf("\t\t\t\t请输入登录密码:");
scanf("%s", &password);
if (strcmp(password, "610808") != 0) { //此处可以是你任意设定的一串数字
printf("\t\t\t\t\t密码错误!\n");
} else {
printf("\t\t\t\t登录成功!\n");
system("pause"); //暂停函数
int input = 0;
struct Program pro;
InitProgram(&pro); //加载以前保存的信息
menu();//菜单展示函数
do {
printf("请选择->");
scanf("%d", &input);
switch (input) {//switch语句选择将执行的步骤
case 1:
system("cls"); //清屏函数,使界面大方,整齐
AddProgram(&pro);
system("pause");
system("cls");
menu();
break;
case 5:
system("cls");
DelProgram(&pro);
system("pause");
system("cls");
menu();
break;
case 2:
system("cls");
SearchProgram(&pro);
system("pause");
system("cls");
menu();
break;
case 3:
Sort(&pro);
system("pause");
system("cls");
break;
case 4:
system("cls");
ModifyProgram(&pro);
system("pause");
system("cls");
menu();
break;
case 6:
system("cls");
ShowProgram(&pro);
system("pause");
system("cls");
menu();
break;
case 7:
system("cls");
short c = 0;
ChangeColor(c);
system("pause");
system("cls");
menu();
break;
case 0:
system("cls");
//保存信息
SaveProgram(&pro); //实现退出并保存
//销毁节目单链表
DestroyProgram(&pro);
printf("\n\n\n\n\n\n\n\n");
printf("\t\t\t\t\t\t退出节目单并保存信息! \n");
printf("\n\n\n\n\n");
break;
default:
system("cls");
printf("选择错误\n");
break;
}
}
while (input);
}
return 0;
}
把这些分代码逐一复制,即可得到能够正常运行系统(我是在dev c++上运行的哦),大家有什么建议或想法,欢迎评论区留言指正。
拜拜~