项目功能:
a.可实时浏览目前处于运行中的所用公交线路的信息;
b.可及时记录并做存储调度后的公交线路;
c.可删除进站后的公交运行记录,以便进行新的调度;
d,可按照不同信息进行特定排序查询,以便找到最关心的行车记录。
e.可将调度后的公交信息按照不同的优先级进行记录;
f.可根据指定车次,快速查询该车次目前所有的信息;
g.可及时修改指定运行中车次的其他信息(比如: 运行站点的改变)
项目流程:
应用到的知识点:
1.数据结构 (单向链表)
2.文件操作 (数据存储和加载)
3.基础算法 (选择排序)
4.链表原理和基本操作 链表的头插法,尾插法,链表节点的删除 和查询及数据修改。
5.动态内存申请及二级指针 二级指针实现链表外排序。
file.h
cpp
#ifndef __FILE_H
#define __FILE_H
#include "slist.h"
int load(NODE** head);
int save(const NODE* head);
#endif
file.c
cpp
#include "file.h"
#include <stdio.h>
// 文件的读取
int load(NODE** head)
{
FILE *fp = fopen("bus.dat","r");
if(!fp)
return -1;
DATA data = {0};
while(fread(&data,sizeof(DATA),1,fp) == 1)
{
slist_addTail(head,data);
}
fclose(fp);
return 0;
}
// 文件的写入
int save(const NODE* head)
{
if(!head)
return -1;
FILE *fp = fopen("bus.dat","w");
if(!fp)
return -1;
NODE* p = (NODE*)head;
while(p)
{
fwrite(&(p -> data),sizeof(DATA),1,fp);
p = p -> next;
}
fclose(fp);
return 0;
}
menu.h
cpp
#ifndef __MENU_H
#define __MENU_H
#include "slist.h"
void welcome();
int mainmenu(NODE**);
int browsemenu(NODE**);
int addmenu(NODE**);
int deletemenu(NODE**);
#endif
menu.c
cpp
#include "menu.h"
#include "function.h"
#include <stdio.h>
void welcome(void)
{
puts("**********************");
puts("*** ****");
puts("*** ****");
puts("***公交调度子系统 ****");
puts("*** ****");
puts("*** ****");
puts("*** ver1.00.00 ****");
puts("*** ****");
puts("*** ****");
puts("**********************");
puts("*** 按任意键继续 ****");
getchar();
}
int mainmenu(NODE** head)
{
puts("**********************");
puts("*** 1.显示记录 ****");
puts("*** 2.添加记录 ****");
puts("*** 3.删除记录 ****");
puts("*** 4.查询记录 ****");
puts("*** 5.修改记录 ****");
puts("*** 0.退出 ****");
puts("**********************");
puts("\n");
while(getchar() != '\n') ;
char sel = 0;
printf("\t请选择:");
scanf("%c",&sel);
switch(sel)
{
case '0':
return 0;
case '1':
while(browsemenu(head)) ;
break;
case '2':
while(addmenu(head)) ;
break;
case '3':
while(deletemenu(head)) ;
break;
case '4':
//query(*head);
break;
case '5':
break;
default :
puts("功能开发中...");
}
return sel != 0;
}
int browsemenu(NODE** head)
{
puts("**************************");
puts("*** 1.运行车次排序 ****");
puts("*** 2.按照终点站排序 ****");
puts("*** 3.按照里程排序 ****");
puts("*** 4.不排序显示 ****");
puts("*** 0.返回上一级 ****");
puts("**************************");
puts("\n");
int sel = -1;
printf("\t请选择:");
scanf("%d",&sel);
switch(sel)
{
case 0:
return 0;
case 1:
case 2:
case 3:
Sort(*head,sel);
break;
case 4:
slist_showAll(*head);
break;
default :
puts("功能开发中...");
}
return sel;
}
int addmenu(NODE** head)
{
puts("**************************");
puts("*** 1.头插 ****");
puts("*** 2.尾插 ****");
puts("*** ****");
puts("*** 0.返回上一级 ****");
puts("**************************");
puts("\n");
int sel = -1;
printf("\t请选择:");
scanf("%d",&sel);
switch (sel)
{
case 0:
return 0;
case 1:
case 2:
addrecord(head,sel);
break;
default:
puts("功能开发中,敬请期待...");
}
return sel;
}
int deletemenu(NODE** head)
{
puts("**************************");
puts("*** 1.按车次删除 ****");
puts("*** 2.按站点删除 ****");
puts("*** ****");
puts("*** 0.返回上一级 ****");
puts("**************************");
puts("\n");
int sel = -1;
printf("\t请选择:");
scanf("%d",&sel);
switch (sel)
{
case 0:
return 0;
case 1:
case 2:
slist_showAll(*head);
deleterecord(head,sel);
break;
default:
puts("功能开发中,敬请期待...");
}
return sel;
}
slist.h
cpp
#ifndef __SLIST_H
#define __SLIST_H
struct Bus
{
int line;
char start[20];
char stop[20];
char current[20];
float km;
};
typedef struct Bus DATA;
typedef struct node
{
DATA data;
struct node *next;
}NODE;
int slist_create(NODE**,DATA);
int slist_addHead(NODE** head,DATA data);
int slist_addTail(NODE** head,DATA data);
int slist_insert(NODE** head,DATA pos,DATA data);
NODE* slist_find(const NODE* head,DATA data);
int slist_update(const NODE* head,DATA old,DATA newdata);
void slist_showAll(const NODE* head);
int slist_delete(NODE** head,DATA data);
void slist_destroy(NODE** head);
#endif
slist.c
cpp
#include "slist.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
/*
@function: int slist_create(NODE** head,DATA data);
@berif: 创建单项链表
@argument: head: 指向头指针变量的地址,用来接收首节点地址
data: 存储在节点中的数据
@return : 成功返回 0
失败返回 -1
*/
int slist_create(NODE** head,DATA data)
{
NODE* p = (NODE*)malloc(sizeof(NODE));
if(!p)
{
return -1;
}
p -> data = data;
p -> next = NULL;
*head = p;
return 0;
}
/*
@function: int slist_addHead(NODE** head,DATA data);
@berif: 向链表头部插入一个节点数据
@argument: head: 指向头指针变量的地址,用来接收首节点地址
data: 存储在新节点中的数据
@return : 成功返回 0
失败返回 -1
*/
int slist_addHead(NODE** head,DATA data)
{
NODE* p = (NODE*)malloc(sizeof(NODE));
if(!p)
{
return -1;
}
p -> data = data;
p -> next = *head;
*head = p;
return 0;
}
/*
@function: int slist_addTail(NODE** head,DATA data);
@berif: 向链表尾部插入一个节点数据
@argument: head: 指向头指针变量的地址,用来接收首节点地址
data: 存储在新节点中的数据
@return : 成功返回 0
失败返回 -1
*/
int slist_addTail(NODE** head,DATA data)
{
NODE * pNew = (NODE*)malloc(sizeof(NODE));
if(!pNew)
{
return -1;
}
pNew -> data = data;
pNew -> next = NULL;
NODE* p = *head, *q = NULL;
if(!p)
{
*head = pNew;
return 0;
}
while(p)
{
q = p;
p = p -> next;
}
q -> next = pNew;
return 0;
}
/*
@function: int slist_insert(NODE** head,DATA pos ,DATA data);
@berif: 向链表节点值为pos的位置插入一个节点数据data
@argument: head: 指向头指针变量的地址
pos: 插入节点位置的节点数据
data: 存储在新节点中的数据
@return : 成功返回 0
失败返回 -1
*/
int slist_insert(NODE** head,DATA pos,DATA data)
{
NODE *pNew = (NODE*)malloc(sizeof(NODE));
if(!pNew)
return -1;
pNew -> data = data;
pNew -> next = NULL;
NODE *p = *head, *q = NULL;
if(!p)
{
*head = pNew;
return 0;
}
if(memcmp(&(p -> data),&pos,sizeof(DATA)) == 0)
{
pNew -> next = *head;
*head = pNew;
return 0;
}
while(p)
{
if(memcmp(&(p -> data),&pos,sizeof(DATA)) == 0)
{
pNew -> next = p;
q -> next = pNew;
return 0;
}
q = p;
p = p -> next;
}
q -> next = pNew;
return 0;
}
/*
@function: NODE* slist_find(const NODE* head,DATA data);
@berif: 查找链表数据data
@argument: head: 指向头指针变量
data: 待查找的数据
@return : 成功返回节点的地址
失败返回NULL
*/
NODE* slist_find(const NODE* head,DATA data)
{
const NODE* p = head;
while(p)
{
if(memcmp(&(p -> data),&data,sizeof(DATA)) == 0)
{
return (NODE*)p;
}
p = p -> next;
}
return NULL;
}
/*
@function: int slist_update(const NODE* head,DATA old,DATA newdata);
@berif: 更新链表数据old 为 newdata
@argument: head: 指向头指针变量
old: 待更新的节点数据
newdata: 更新后的节点数据
@return : 成功返回 0
失败返回 -1
*/
int slist_update(const NODE* head,DATA old,DATA newdata)
{
NODE* p = NULL;
if(!(p = slist_find(head,old)))
return -1;
p -> data = newdata;
return 0;
}
/*
@function: void slist_showAll(const NODE* head);
@berif: 遍历链表数据
@argument: head: 指向头指针变量
@return : 无
*/
void slist_showAll(const NODE* head)
{
const NODE* p = head;
int num = 0;
printf("%10s%12s%12s%12s%10s\n","车次","起始站","终点站","当前站点","总里程");
while(p)
{
num++;
printf("%10d%12s%12s%12s%.1f\n",p->data.line,p->data.start,p->data.stop,\
p->data.current,p->data.km);
p = p -> next;
}
printf("\n总共有%d条记录\n",num);
}
/*
@function: int slist_delete(NODE** head,DATA data);
@berif: 删除链表中节点值为data的节点
@argument: head: 指向头指针变量的地址
data: 删除节点中的数据
@return : 成功返回 0
失败返回 -1
*/
int slist_delete(NODE** head,DATA data)
{
NODE *p = *head, *q = NULL;
if(!p)
return -1;
if(memcmp(&(p -> data),&data,sizeof(DATA)) == 0)
{
*head = p -> next;
free(p);
return 0;
}
while(p)
{
if(memcmp(&(p -> data),&data,sizeof(DATA)) == 0)
{
q -> next = p -> next;
free(p);
return 0;
}
q = p;
p = p -> next;
}
return -1;
}
/*
@function: void slist_destroy(NODE** head);
@berif: 回收链表
@argument: head: 指向头指针变量的地址
@return : 无
*/
void slist_destroy(NODE** head)
{
NODE* p = *head, *q = NULL;
while(p)
{
q = p;
p = p -> next;
free(q);
}
*head = NULL;
}
function.h
cpp
#ifndef __FUNCTION_H
#define __FUNCTION_H
#include "slist.h"
int addrecord(NODE**,int);
int deleterecord(NODE**,int);
void Sort(NODE*,int);
#endif
function.c
cpp
#include "function.h"
#include "file.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int addrecord(NODE** head,int sel)
{
DATA data = {0};
printf("请输入运行车次:");
scanf("%d",&(data.line));
printf("请输入起始站点:");
scanf("%s",data.start);
printf("请输入终点站点:");
scanf("%s",data.stop);
printf("请输入当前站点:");
scanf("%s",data.current);
printf("请输入线路总里程:");
scanf("%f",&(data.km));
int ret = 0;
if(sel == 1)
ret = slist_addHead(head,data);
else
ret = slist_addTail(head,data);
ret = save(*head);
return ret;
}
static int delete_byline(NODE** head,int line)
{
NODE* p = *head;
while(p)
{
if(p -> data.line == line)
break;
p = p -> next;
}
if(!p)
return -1;
return slist_delete(head,p -> data);
}
static int delete_bystation(NODE** head,const char* station)
{
NODE* p = *head;
while(p)
{
if (strcmp(p -> data.stop, station) == 0)
break;
p = p -> next;
}
if(!p)
return -1;
return slist_delete(head,p -> data);
}
int deleterecord(NODE** head,int sel)
{
char ch = '\0';
do
{
if(sel == 1)
{
int line = 0;
printf("请输入要删除的车次:");
scanf("%d",&line);
if(delete_byline(head,line) == 0)
{
save(*head);
slist_showAll(*head);
}
else
puts("你删除的车次不存在");
printf("是否继续删除?[Y/N]");
}
else
{
char station[20] ={ 0};
printf("请输入要删除的终点站:");
scanf("%s",station);
if(delete_bystation(head,station) == 0)
{
save(*head);
slist_showAll(*head);
}
else
puts("你删除的车次不存在,");
printf("是否继续删除?[Y/N]");
}
while(getchar()!='\n');
ch = getchar();
}while(ch == 'Y' || ch == 'y');
return 0;
}
int compare(NODE* p ,NODE* q, int sel)
{
switch(sel)
{
case 1:
return p -> data.line < q -> data.line;
case 2:
return strcmp(p -> data.stop, q -> data.stop) < 0;
case 3:
return p -> data.km < q -> data.km;
}
return 0;
}
void Sort(NODE* head,int sel)
{
int n = 0;
NODE* p = head;
while(p)
{
n++;
p = p -> next;
}
NODE** ps = (NODE**)calloc(sizeof(NODE*),n);
if(!ps)
return ;
register int i = 0;
p = head;
while(p)
{
ps[i++] = p;
p = p -> next;
}
register int j = 0;
for(i = 0; i < n -1; i++ )
{
int m = i;
for(j = i + 1; j < n; j++)
{
if(compare(ps[m],ps[j],sel))
m = j;
}
if(m != i)
{
NODE* t = ps[i];
ps[i] = ps[m];
ps[m] = t;
}
}
for(i = 0 ; i < n; i++)
{
printf("%6d%-20s%-20s%-20s%-.1f\n",ps[i]->data.line,ps[i]->data.start,ps[i]->data.stop,\
ps[i]->data.current,ps[i]->data.km);
}
free(ps);
}
main.c
cpp
#include "slist.h"
#include "menu.h"
#include "slist.h"
#include "file.h"
#include <stdio.h>
int main(void)
{
NODE* head = NULL;
load(&head);
welcome();
while(mainmenu(&head)) ;
slist_destroy(&head);
return 0;
}