公交線路圖
一. 設計要求:
1、需要用到多個文件,例如文本文件,文件名stations.txt,保存站點信息,格式可以自行設計,例如:編號 站名。等等
2、設計公交線路所需的存儲結構,將文件中的數據讀入內存。
3、提供用戶操作的菜單和界面實現添加、刪除、修改公交、站點、線路信息,注意數據間的關聯性。
4、將修改後的信息保存迴文件。
5、其他查詢操作參見教程。
二. 設計內容:
1、 數據格式**:**
在這個課設中我設計的是兩個文件,一個文件用來存放公交車站名的“stations.txt”,一個用來存放公交線路“bus.txt”。
(1)**“stations.txt”**文件的第一行,記錄的爲公交車站的數量,依次往下,爲所存的公交車站名,其格式爲:
① 公交車站數
② 公交車站名
③ 公交車站名
④ 公交車站名
(2)**“bus.txt****”**文件的第一行,記錄的爲公交車每個站之間有幾條線路,就是一站算一條線路(例如:公交車從仙來廣場到慶豐苑是走了一條線路,從仙來廣場到金三角,就要先從仙來廣場到慶豐苑,再從慶豐苑到金三角,這樣看,是走了兩條線路) 第二行開始記錄公交名,公交車的一條線路的起點和終點,還有兩站之間的距離,其格式爲:
① 公交線路數量
② 公交車名 起始站 終點站 距離
③ 公交車名 起始站 終點站 距離
④ 公交車名 起始站 終點站 距離
…………………………
例如:
公交車名 起始站 終點站 距離
105 圖書館 人民政府 432
105 人民政府 萬達廣場 856
這就說明105路公交車,會經過圖書館–>人民廣場–>萬達廣場。
2、 數據結構**:**
將文件中的數據讀入內存,建立圖的存儲結構,,以下爲存儲結構的C語言定義:
typedef int StationsType;//StationsType 定義整形的變量
typedef struct TrafficNode
{
char name[MAX_STRING_NUM]; //公交號
int EndCity; //該有向邊指向的頂點在數組中的位置,即該公交站編號
int Number ; //用於記錄每站之間的距離
} TrafficNodeDat;
typedef struct VNode
{
StationsType stations;
int BusNum; // 標記下面 Bus 數組裏元素個數
TrafficNodeDat Bus[MAX_TRAFFIC_NUM]; // 數組成員爲結構體,記錄了到達的終點站、距離、和公交號
} VNodeDat;
VNodeDat AdjList[MAX_VERTEX_NUM];
3、 查詢公交線路:
當輸入公交號後,就會輸出公交線路的信息如下圖:
4、 添加公交站:
輸入公交站名存儲成功後會輸出Save OK
5、 刪除公交站:
輸入公交需要刪除的公交站成功會提醒:
6、 添加公交線路:
輸入所規定的起始,終點站,公交號和兩站之間的距離:
7、 刪除公交:
輸入公交號刪除成功則輸出OK:
二. 系統子程序及功能設計**:**
int ShowMenu()
int SeekStations(char *name) // 尋找公交站
int SearchBus(char *name)// 查詢公交站
int InsertStations(char *Name) // 添加公交站
int DelStations(char *Name) // 刪除公交站
int SaveSysInfo() // 向程序輸入數據
int InsertBus(char *bus, char *StartCity, char *EndStations, int number)//添加公交
int DelPath(char *name)// 刪除公交
int InitSysData();
三.實驗總結:
1. 在做課設的時候,起初我設計的是一個公交一次性輸入許多路線,這樣也十分的符合公交的特性,但是在做到最優路徑的是吧,出現了大量的bug,於是我進行了查閱資料,於是我就改成了現在的這樣,兩站兩站的輸入信息和存儲信息,只要起始站和終點站,這樣設計。雖然這樣麻煩許多,但是在設計的時候自己對於這種方法掌握的更快一點,於是終於設計出來了這個課設。
2. 這個課設還是有很大的完善空間,在繼續最優路徑搜索的時候,在某些情況下會出現無法輸出的情況,在進行了測試後,發現對於一些不存在的公交站查詢的時候,不會報錯,同時在輸出的時候,不是很人性化,同時該程序的一些地方寫的代碼十分的繁瑣,從而影響了運行速度。這些都是在之後的學習中,需要改進和完善的地方。
四.程序代碼**
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define ERR 0
#define OK 1
#define Dij_MAXN 100
#define MAX_VERTEX_NUM 100
#define MAX_STRING_NUM 100
#define MAX_TRAFFIC_NUM 100
const char StationsFile[] = "stations.txt";
const char BusFile[] = "bus.txt";
typedef int StationsType;//StationsType 定義整形的變量
typedef struct TrafficNode
{
char name[MAX_STRING_NUM]; // 公交號 //MAX_STRING_NUM 最爲 10
int EndStations; // 該有向邊指向的頂點在數組中的位置,即該公交站編號
int Number ; // 用於記錄每站之間的距離
} TrafficNodeDat;
typedef struct VNode
{
StationsType stations;
int BusNum; // 標記下面 Bus 數組裏元素個數
TrafficNodeDat Bus[MAX_TRAFFIC_NUM]; // 數組成員爲結構體,記錄了到達的終點站、距離0、和公交號
} VNodeDat;
VNodeDat AdjList[MAX_VERTEX_NUM];
char StationsName[MAX_VERTEX_NUM][MAX_STRING_NUM]; // 公交站名,採用第一下標爲該城市在本程序中的編號
int StationsNum; // 公交站數目
int ShowMenu()
{
printf("\n|****************** 歡迎使用城市交通系統 *******|\n");
printf("\n|------------------1: 添加公交站 --------------|");
printf("\n|------------------2: 刪除公交線路 ------------|");
printf("\n|------------------3: 添加交通路線 ------------|");
printf("\n|------------------4: 刪除公交 ----------------|");
printf("\n|------------------5: 查詢最短的路線 ----------|");
printf("\n|------------------6: 查詢公交線路 ------------|");
printf("\n|------------------7: 清除屏幕 ----------------|");
printf("\n|------------------0: 退出 --------------------|");
printf("\n|***********************************************|\n");
printf("\n 請輸入你的選擇 :");
return 0;
}
int SeekStations(char *name) // 尋找公交站
{
int i;
for (i = 0; i<StationsNum; i++)
{
if (strcmp(name, StationsName[i]) == 0) // 比較函數,若相等,則返回 i 值
{
return i;
}
}
return -1;
}
int SaveSysInfo() // 向程序輸入數據
{
FILE *fp;
int i, j, total;
fp = fopen(StationsFile, "w"); // 打開 StationsFile 文檔
fprintf(fp, "%d\n", StationsNum); // 往文檔中寫公交站的數量
for (i = 0; i<StationsNum; i++)
{
fprintf(fp, "%s\n", StationsName[i]); // 往文檔中寫公交站的名字
}
fclose(fp);// 將 StationsFile 文檔關閉
total = 0;
fp = fopen(BusFile, "w");// 打開 BusFile 文檔
for (i = 0; i<StationsNum; i++) // 計算公交的數量
{
total += AdjList[i].BusNum;
}
fprintf(fp, "%d\n", total); // 往文檔中寫公交的數量
for (i = 0; i<StationsNum; i++) //
{
for (j = 0; j<AdjList[i].BusNum; j++) // 往文檔中寫公交的車次、始發站、終點站
{
fprintf(fp, "%s %s %s ", AdjList[i].Bus[j].name,
StationsName[i],
StationsName[AdjList[i].Bus[j].EndStations]);
fprintf(fp, " %d\n", AdjList[i].Bus[j].Number);// 往文檔中寫
}
}
fclose(fp);
return 1;
}
int InsertStations(char *Name) // 添加公交站
{
strcpy(StationsName[StationsNum], Name);
AdjList[StationsNum].stations = StationsNum;
AdjList[StationsNum].BusNum = 0;
StationsNum++;
return 1;
}
int DelStations(char *Name) // 刪除公交站
{
int stations, i, j,o=1,k=1;
stations = SeekStations(Name);
printf("%s",Name);
while (true)
{
while (StationsName[k] != Name)
{
k++;
}
if (k > StationsNum)
{
o--;
printf(" 未找到此公交站,請重新輸入! ");
return 0;
}
for (i = stations; i < StationsNum - 1; i++)
{
strcpy(StationsName[i], StationsName[i + 1]);
AdjList[i].BusNum = AdjList[i + 1].BusNum;
for (j = 0; j < AdjList[i].BusNum; j++)
{
strcpy(AdjList[i].Bus[j].name, AdjList[i + 1].Bus[j].name);
AdjList[i].Bus[j].EndStations = AdjList[i + 1].Bus[j].EndStations;
AdjList[i].Bus[j].Number = AdjList[i + 1].Bus[j].Number;
}
}
StationsNum--;
}
return 1;
}
int InsertBus(char *bus, char *StartCity, char *EndStations, int number)//添加公交
{
int i, j;
i = SeekStations(StartCity);
j = SeekStations(EndStations);
AdjList[i].Bus[AdjList[i].BusNum].Number = number;
AdjList[i].Bus[AdjList[i].BusNum].EndStations = j;
strcpy(AdjList[i].Bus[AdjList[i].BusNum].name, bus);
AdjList[i].BusNum++; // 公交的數加 1
return 1;
}
int DelPath(char *name)// 刪除公交
{
int i, j, flag = 0;
for (i = 0; i<StationsNum; i++)
{
for (j = 0; j<AdjList[i].BusNum; j++)
if (strcmp(AdjList[i].Bus[j].name, name) == 0)
{
flag = 1;
break;
}
if (flag==0)
{
for (; j<AdjList[i].BusNum - 1; j++) // 把刪除的公交後的每個公交都前移一位
{
AdjList[i].Bus[j].Number = AdjList[i].Bus[j + 1].Number;
AdjList[i].Bus[j].EndStations = AdjList[i].Bus[j + 1].EndStations;
strcpy(AdjList[i].Bus[j].name, AdjList[i].Bus[j + 1].name);
}
AdjList[i].BusNum--;
break;
}
}
return 1;
}
int InitSysData()
{
FILE *fp;
int i, j, num, number;
char stmp1[MAX_STRING_NUM];
char stmp2[MAX_STRING_NUM];
char stmp3[MAX_STRING_NUM];
fp = fopen(StationsFile, "r");
if (!fp)
{
printf("\nError:Cannot Open Stations File...\n");
return -1;
}
fscanf(fp, "%d", &StationsNum);
for (i = 0; i<StationsNum; i++)
{
fscanf(fp, "%s", &StationsName[i]);
AdjList[i].stations = i;
AdjList[i].BusNum = 0;
}
fclose(fp);
fp = fopen(BusFile, "r");
if (!fp)
{
printf("\nError:Cannot Open Bus File...\n");
return -1;
}
fscanf(fp, "%d", &num);
for (i = 0; i<num; i++)
{
fscanf(fp, "%s", &stmp1); // 公交的車次
fscanf(fp, "%s", &stmp2); // 公交的始發站
fscanf(fp, "%s", &stmp3); // 公交的終點站
j = SeekStations(stmp2);
AdjList[j].Bus[AdjList[j].BusNum].EndStations = SeekStations(stmp3); // 將公交的車號、始發站、終點站讀出
strcpy(AdjList[j].Bus[AdjList[j].BusNum].name, stmp1);
fscanf(fp, "%d", &number);
AdjList[j].Bus[AdjList[j].BusNum].Number = number;
AdjList[j].BusNum++;
}
fclose(fp);
return 1;
}
int SearchBus(char *name)// 查詢公交站
{
FILE *fp;
int i, j, num, number;
char stmp1[MAX_STRING_NUM];
char stmp2[MAX_STRING_NUM];
char stmp3[MAX_STRING_NUM];
int stmp4;
fp = fopen(BusFile, "r");
if (!fp)
{
printf("\nError:Cannot Open Bus File...\n");
return -1;
}
fscanf(fp, "%d", &num);
for (i = 0; i<num; i++)
{
fscanf(fp, "%s", &stmp1); // 公交的車次
fscanf(fp, "%s", &stmp2); // 公交的始發站
fscanf(fp, "%s", &stmp3); // 公交的終點站
fscanf(fp, "%d", &stmp4); // 公交站之間的距離
if(strcmp(stmp1,name) == 0)
{
printf("%s %s %s %d\n" , stmp1 ,stmp2 ,stmp3 ,stmp4);
}
}
fclose(fp);
return 1;
}
int main()
{
char name[MAX_STRING_NUM]; // 公交站名
char s_city[MAX_STRING_NUM]; // 始發站
char e_city[MAX_STRING_NUM]; // 終點站
int Command, number = 1;
int startcity, endcity, traveltype = 0;
while (true)
{
printf("\n");
ShowMenu(); // 主菜單
scanf("%d", &Command);// 輸入選擇
switch (Command) // 對菜單的內容進行選擇
{
case 0: // 退出
return 0;
case 1: // 添加公交
InitSysData(); // 讀出文檔中已存的信息
printf("\n 輸入公交站名 :");
scanf("%s", &name); // 輸入城市名
InsertStations(name); // 將城市插入到數組中
SaveSysInfo(); // 把公交的信息寫入文檔中
printf(" Save OK!\n");
break;
case 2: // 刪除公交站
InitSysData(); // 讀出文檔中已有的信息
printf("\n 輸入公交站名 :");
scanf("%s", &name);
DelStations(name); // 將公交刪除
SaveSysInfo(); // 將處理過的信息寫入文檔中
printf("Save OK!\n");
break;
case 3: // 添加路線
InitSysData();
printf(" 起始公交站名 :");
scanf("%s", &s_city); // 起始站
printf(" 終點公交站名 :");
scanf("%s", &e_city); // 終點站
printf(" 輸入公交號 :");
scanf("%s", &name);
printf(" 距離 :");
scanf("%d", &number);
InsertBus(name, s_city, e_city, number);
SaveSysInfo();
printf(" Save OK!\n");
break;
case 4: // 刪除公交
InitSysData();
printf(" 輸入需要刪除的公交車名 :");
scanf("%s", &name);
DelPath(name); // 將路線進行刪除
SaveSysInfo();
printf("Save OK!\n");
break;
/*case 5: // 最小所坐站
InitSysData();
printf("\n 起始公交站 :");
scanf("%s", &name);
startcity = SeekStations(name);
if (startcity<0)
{
printf("Error station Name:No such station!\n");
break;
}
printf(" 終點公交站 :");
scanf("%s", &name);
endcity = SeekStations(name);
if (endcity<0)
{
printf("Error station Name:No such station!\n");
break;
}
//CalcMinNum(startcity, endcity, traveltype); // 計算最少的站數
printf("\n");
break;
*/
case 6:
InitSysData();
printf(" 輸入公交號 :");
scanf("%s", &name);
SearchBus(name);
break;
case 7:
system("cls");// 清除屏幕
}
}
}
最後:
在本課設中對於車站的輸入大家要格外注意,因爲個人水平的原因,使用這種方法更讓我好理解和進行搜索,在之後的學習中,我會完善該課設,在之後的博客中會進行補充。