1.問題
假定我們的程序模擬的是 xauat 網上書店的電話接待臺接電話(離散事件)的過程。
用戶在打電話諮詢時,先輸入自己的標識(如姓名或會員號),然後進入排隊等待被
接聽電話。xauat 服務人員會根據該用戶在書店已購買書籍的累計消費情況對撥入的
電話進行排序。累計消費超過 3000 元的爲 1 類用戶,最先得到服務;累計消費不到
3000 元、但已滿 2000 元的 2 類用戶在沒有 1 類用戶情況下會得到服務;累計消
費不滿 2000 元、但已滿 1000 元的 3 類用戶在沒有前兩類用戶情況下會得到服務;
累積消費不滿 1000 元的用戶爲 4 類用戶,在沒有前三類用戶情況下會得到服務。同
類用戶根據時間先後確定被接聽的次序。
這些離散事件事先存入文件 sample.txt,程序接收的離散事件需要從
sample.txt 獲取。
2.程序
sample.txt
call.cpp
頭文件dlist.cpp(見前面博客:用C++語言實現雙端隊列)
#include <iostream>
#include <string>
#include <fstream>
#include "dlist.cpp"
using namespace std;
struct message{ //撥入電話的信息
int timestamp; //時間點
string name; //客戶名字
int status; //用戶等級
int duration; //需要持續的時間片長度
message() //初始化
{
timestamp = 0;
name = "";
status = 0;
duration = 0;
}
};
void get(Dlist<message> &one,Dlist<message> &two,Dlist<message> &three,Dlist<message> &four,message *newm) //向隊列中插入信息
{
if(1 == newm->status) //如果這個電話用戶是1類用戶
{
one.insertBack(newm); //在1類隊列執行尾插操作,將這個信息插入
cout << "Call from " << newm->name << " a Level1 member" << endl; //打印出相應信息
}
if(2 == newm->status)//如果這個電話用戶是2類用戶
{
two.insertBack(newm);//在2類隊列執行尾插操作,將這個信息插入
cout << "Call from " << newm->name << " a Level2 member" << endl; //打印出相應信息
}
if(3 == newm->status)//如果這個電話用戶是3類用戶
{
three.insertBack(newm);//在3類隊列執行尾插操作,將這個信息插入
cout << "Call from " << newm->name << " a Level3 member" << endl;//打印出相應信息
}
if(4 == newm->status)//如果這個電話用戶是4類用戶
{
four.insertBack(newm);//在4類隊列執行尾插操作,將這個信息插入
cout << "Call from " << newm->name << " a Level4 member" << endl;//打印出相應信息
}
}
bool do_call(Dlist<message> &one,Dlist<message> &two,Dlist<message> &three,Dlist<message> &four,int &need_tick) //處理電話
{
message *newm = NULL;
newm = one.removeFront(); //嘗試從1類隊列取元素
if(newm != NULL) //如果取到了元素,則說明1類隊列有元素,優先處理
{
cout << "Answering call from " << newm->name << endl;//打印出相應信息
need_tick = newm->duration; //將這個電話所需要的持續時間片返回
return true;
}
newm = two.removeFront();//嘗試從2類隊列取元素
if(newm != NULL)//如果取到了元素,則說明2類隊列有元素,優先處理
{
cout << "Answering call from " << newm->name << endl;//打印出相應信息
need_tick = newm->duration; //將這個電話所需要的持續時間片返回
return true;
}
newm = three.removeFront();//嘗試從3類隊列取元素
if(newm != NULL)//如果取到了元素,則說明3類隊列有元素,優先處理
{
cout << "Answering call from " << newm->name << endl;//打印出相應信息
need_tick = newm->duration;//將這個電話所需要的持續時間片返回
return true;
}
newm = four.removeFront();//嘗試從4類隊列取元素
if(newm != NULL)//如果取到了元素,則說明4類隊列有元素,優先處理
{
cout << "Answering call from " << newm->name << endl;//打印出相應信息
need_tick = newm->duration;//將這個電話所需要的持續時間片返回
return true;
}
return false; //如果都沒有取到,說明所有電話都處理完了,返回false
}
int main()
{
Dlist<message> one; //存儲撥入的1類用戶電話信息
Dlist<message> two; //存儲撥入的2類用戶電話信息
Dlist<message> three; //存儲撥入的3類用戶電話信息
Dlist<message> four; //存儲撥入的4類用戶電話信息
int tick = 0; //當前時間片
int need_tick = 0; //完成當前電話還需要持續的時間
int mcount = 0; //撥入電話的總數
int i = 0;
bool f = true; //判斷信息是否全部處理完
message *newm;
ifstream pin;
pin.open("sample.txt",ios::in); //打開文件
if (!pin.is_open())
{
cout << "未成功打開文件" << endl;
}
pin >> mcount; //讀取文件的第一行
for(tick = 0;f;tick++) //循環,從第0個時間片開始,直到處理完所有電話退出
{
cout << "Starting tick #" << tick << endl; //打印出當前時間
for(i = 0;i < mcount;i++) //循環,讀取出文件中每行的信息
{
newm = new message(); //分配空間存儲電話信息
if(mcount <= 0) //如果所有信息已經讀完則跳出循環
{
break;
}
pin >> newm->timestamp >> newm->name >> newm->status >> newm->duration; //從文件中讀取一行信息
if(newm->timestamp == tick) //判斷是否是當前時間撥入的
{
get(one,two,three,four,newm); //如果是當前時間撥入的電話,則調用函數將其信息存入隊列中
mcount--; //要讀取的信息少了一行
}
else break;//如果不是當前時間則直接跳出循環
}
if(need_tick == 0) //判斷上一次通話是否還需要時間片,如果need_tick等於0,說明上一個電話已經處理完
{
f = do_call(one,two,three,four,need_tick); //如果上一個電話已經處理完則開始處理下一個電話
}
need_tick--;//減去當前消耗的時間片
}
delete newm;
}
3.結果
結果解釋:
這個程序是雙端隊列中隊列的應用,處理的是模擬的離散事件。程序運行結果如圖所
示,按照要求每個時間片開始時先打印“Starting tick #<tick>”提示信息,然後
先打印出當前時間片接收到的電話,將其存儲起來,然後打印當前時間片中處理的電
話,直到所有電話處理完程序結束。