新手菜鸟求助,怎么把写统计当前排队人数最多的窗口业务类型,为新增窗口提供依据
我已完成的代码如下:#include <stdio.h>
#include "util.h"
#include "linklist.h"
typedef enum
{
wsNormal = 0, //窗口正常
wsPause= 1
} EWinStatus;
#define WIN_TYPE_SIZE 32
typedef char WinType;
static char gszWinTypeTip;
static WinType gWinType = {0}; //窗口业务类型,最多10个类型
static LinkListMan gLinkMan = {0};
static int gQueueId = 1; //排队号
char gaWinPointDesc[] = {"差", "良", "好"};
static bool gbSave = false;
LNode *GetWinNode(int nWinId);
int NodePtr2Pos(LNode *p);
void OnWinShow(void *para);
void OnWinNew(void *para);
void OnWinDel(void *para);
void OnWinPause(void *para);
void OnWinResume(void *para);
void OnCustomerArrive(void *para);
void OnCustomerLeave(void *para);
Status LoadData();
void UnloadData();
void OnWinManage(void *para)
{
SCmd acmd[] = {{"WinShow", "窗口状态", OnWinShow},
{"WinNew", "窗口新增", OnWinNew},
{"WinDel", "窗口删除", OnWinDel},
{"WinPause","窗口业务暂停", OnWinPause},
{"WinResume", "窗口业务恢复", OnWinResume},
{"", "", NULL},
{"CustomerArrive","取号排队", OnCustomerArrive},
{"CustomerLeave", "办结离队", OnCustomerLeave}
};
if (LoadData() != OK)
{
PRINTF("配置数据加载失败!\n");
return;
}
CmdLoop(acmd, numof(acmd), NULL);
UnloadData();
}
void OnWinShow(void *para)
{
LNode *p = GetFirstElemNodePtr(gLinkMan);
char szStatus = {"正常", "暂停"};
PRINTF("窗口号\t状态\t排队人数\t平均得分\n");
while (p != NULL)
{
const SWin *pWin = &(p->win);
char szScore;
if (pWin->RemarkNum > 0)
{
float fAvg = (float)pWin->ScoreSum / (float)pWin->RemarkNum;
sprintf(szScore, "%f", fAvg);
}
else
{
strcpy(szScore, "-");
}
PRINTF("%d\t%s\t%d\t\t%s\n", pWin->id, szStatus, QueueLength(pWin->Q), szScore);
p = GetNextElemNodePtr(p);
}
}
void OnWinNew(void *para)
{
int nWinId, nType;
LNode *pWinNode;
SWin win = {0};
if (!InputInteger(nWinId, "请输入整数型窗口编号:")) return;
pWinNode = GetWinNode(nWinId);
if (pWinNode != NULL)
{
PRINTF("%d 窗口已经存在!\n", nWinId);
return;
}
if (!InputInteger(nType, gszWinTypeTip)) return;
win.id = nWinId;
win.type = nType;
QueueInit(win.Q);
if (LL_Append(gLinkMan, win) == OK)
{
PRINTF("新增窗口成功!\n");
gbSave = true;
}
else
{
PRINTF("新增窗口失败!\n");
gbSave = true;
}
}
void OnWinDel(void *para)
{
int nWinId;
if(!InputInteger(nWinId,"请输入待删除的窗口编号:")) return;
LNode *pNode = GetWinNode(nWinId);
if(pNode == NULL)
{
PRINTF("%d 窗口不存在,删除失败!\n",nWinId);
return;
}
if(!QueueIsEmpty(pNode->win.Q))
{
PRINTF("该窗口有排队,无法删除!\n");
return;
}
int pos = NodePtr2Pos(pNode);
printf("gLinkMan.num=%d\n", gLinkMan.num);
if(LL_Delete(gLinkMan, pos) == OK)
{
PRINTF("%d 该窗口被成功删除!\n",nWinId);
gbSave = true;
}
else
{
PRINTF("%d 窗口(pos=%d)删除失败!\n",pos, nWinId);
}
}
//窗口业务暂停
void OnWinPause(void *para)
{
SWin win = {0};
OnWinShow(NULL);
int nWinId;
//RUN_HERE;
if(!InputInteger(nWinId,"请输入待暂停的窗口编号:")) return;
//RUN_HERE;
LNode *p = GetFirstElemNodePtr(gLinkMan);
PRINTF("p=%d\n", p);
while(p!=NULL)
{
if(p->win.id == nWinId)
{
p->win.status = wsPause;
PRINTF("%d 窗口暂停成功!\n",nWinId);
return;
}
p=GetNextElemNodePtr(p);
}
PRINTF("%d窗口不存在,请重试!\n",nWinId);
return;
}
//窗口业务恢复
void OnWinResume(void *para)
{
SWin win = {0};
int nWinId;
OnWinShow(NULL);
if(!InputInteger(nWinId,"请输入待恢复的窗口编号:")) return;
LNode *p = GetFirstElemNodePtr(gLinkMan);
while(p!=NULL)
{
if(p->win.id == nWinId)
{
if(p->win.status == wsNormal)
{
PRINTF("%d 窗口恢复失败!\n",nWinId);
return;
}
else
{
p->win.status = wsNormal;
PRINTF("%d 窗口恢复成功!\n",nWinId);
return;
}
}
p=GetNextElemNodePtr(p);
}
PRINTF("%d 窗口不存在,请重试!\n",nWinId);
return;
}
//取号排队
void OnCustomerArrive(void *para)
{
int nType,nQueueLen;
int nQueueLenMin=9999;
LNode *p=GetFirstElemNodePtr(gLinkMan);
LNode *q=NULL;
if(p==NULL)
{
return ;
}
if(!InputInteger(nType,"请输入要办理的窗口业务:"))return;//查找对应窗口,检查窗口状态、人数
while(p!=NULL)
{
if((p->win.type == nType) && (p->win.status == wsNormal))
{
nQueueLen = QueueLength(p->win.Q);
if(nQueueLen<=nQueueLenMin)
{
nQueueLenMin = nQueueLen;
q=p;
}
}
p=p->next;
}
if(q == NULL)
{
PRINTF("未找到开设窗口,取号失败!\n");
}
if(QueueEnter(q->win.Q,gQueueId))
{
PRINTF("已在%d窗口排队成功,您的号码为%d!\n",q->win.id,gQueueId);
gQueueId++;
return;
}
}
//办结离队
void OnCustomerLeave(void *para)
{
SWin win = {0};
LNode* p=GetFirstElemNodePtr(gLinkMan);
LNode* q;
OnWinShow(NULL);
//出队
int WinID, e,nPoint;
int nQueueId;
int nQueueIdMin =9999;
SWin *pLeaveWin = NULL;
//分析最早入队的顾客出队
while(p!=NULL)
{
if (QueueGetHead(p->win.Q, nQueueId))
{
//printf("nQueueId=%d\n", nQueueId);
if (nQueueId < nQueueIdMin)
{
nQueueIdMin = nQueueId;
q = p;
}
}
p=p->next;
}
if (q == NULL)
{
PRINTF("没有窗口排队,无顾客办结业务!\n");
return;
}
if(QueueLeave(q->win.Q, e))
{
printf("%d窗口客户(排队号=%d)出队成功!\n", q->win.id, e);
if(!InputInteger(nPoint,"请对本次服务评价(0=差, 1=良,2=好,3=不评价):")) return;
if((0<= nPoint) && (nPoint <= 2))
{
q->win.Point=nPoint;
q->win.ScoreSum+=nPoint;
q->win.ScoreSum/q->win.RemarkNum++;
printf("评价成功!评价为%s,总分值=%d, 评价人数=%d。谢谢!\n", gaWinPointDesc,q->win.ScoreSum, q->win.RemarkNum);
}
else if(nPoint == 3)
{
printf("暂不评价,谢谢!\n");
}
else
{
printf("评价错误!\n");
}
return;
}
}
Status LoadData()
{
int Num, i;
char szDefaultWinType[] = {"个人业务", "对公业务", "现金业务", "非现金业务"};
char szTag;
char szSection;
//读取窗口的业务类型
Num = ReadCfgFileInt("WinType", "Num", 4);
for (i = 1; i <= Num; i++)
{
sprintf(szTag, "Type%d", i);
ReadCfgFileString("WinType", szTag, szDefaultWinType, gWinType, WIN_TYPE_SIZE);
}
ReadCfgFileString("WinType", "Tip", "1=个人业务, 2=对公业务, 3=现金业务, 4=非现金业务", gszWinTypeTip, sizeof(gszWinTypeTip));
LL_Init(gLinkMan);
Num = ReadCfgFileInt("Common", "WinNum", 0);
for (i = 1; i <= Num; i++)
{
SWin win = {0};
sprintf(szSection, "Win%d", i);
win.id = ReadCfgFileInt(szSection, "ID", i);
win.type = ReadCfgFileInt(szSection, "type", i);
win.ScoreSum = ReadCfgFileInt(szSection, "ScoreSum", 0);
win.RemarkNum = ReadCfgFileInt(szSection, "RemarkNum", 0);
win.status = wsNormal;
QueueInit(win.Q);
if (LL_Append(gLinkMan, win) != OK) return ERROR;
}
return OK;
}
void UnloadData()
{
char szSection;
if(gbSave) WriCfgFileInt("Common", "WinNum",gLinkMan.num);
for(int i = gLinkMan.num;i>=1;i--)
{
if(gbSave)
{
sprintf(szSection,"Win%d",i);
LNode *p = GetNodePtr(gLinkMan,i);
assert(p != NULL);
SWin *pWin = &(p->win);
WriCfgFileInt(szSection, "ID",pWin->id);
WriCfgFileInt(szSection, "type", pWin->type);
WriCfgFileInt(szSection, "ScoreSum",pWin->ScoreSum );
WriCfgFileInt(szSection, "RemarkNum", pWin->RemarkNum);
}
LL_Delete(gLinkMan,i);
}
delete gLinkMan.L;
}
LNode *GetWinNode(int nWinId)
{
LNode *p = GetFirstElemNodePtr(gLinkMan);
while (p != NULL)
{
if (p->win.id == nWinId) return p;
p = GetNextElemNodePtr(p);
}
return p;
}
//获取指定节点(以指针表示)的顺序号(起始位1,0非法)
int NodePtr2Pos(LNode *p)
{
int pos = 0;
LNode *t = gLinkMan.L;
while(t != NULL)
{
if (t == p) return pos;
pos++;
t = t->next;
}
return 0;
}
//可统计当前排队人数最多的窗口业务类型,为新增窗口提供依据;
为了统计当前排队人数最多的窗口业务类型,你需要创建一个统计函数,并在其中遍历所有的窗口,跟踪并比较每个窗口的排队人数。这个函数将返回人数最多的窗口的类型。
以下是代码的概念性实现,你可能需要按照你的具体项目来对其进行修改:
// 函数返回排队人数最多的窗口的业务类型
int GetMostCrowdedWindowType() {
int maxQueueLength = -1; // 初始化最大队列长度为-1,表示目前没有找到任何窗口
int mostCrowdedWinType = -1; // 初始化为-1,表示没有找到排队人数最多的窗口类型
LNode *p = GetFirstElemNodePtr(gLinkMan); // 获取第一个窗口节点
// 遍历所有的窗口
while (p != NULL) {
int queueLength = QueueLength(p->win.Q); // 获取当前窗口的队列长度
if (queueLength > maxQueueLength) { // 如果当前窗口的队列长度大于最大队列长度
maxQueueLength = queueLength; // 更新最大队列长度
mostCrowdedWinType = p->win.type; // 更新排队人数最多的窗口的类型
}
p = GetNextElemNodePtr(p); // 移动到下一个窗口
}
return mostCrowdedWinType;
}
这个函数首先获取第一个窗口节点,然后遍历所有的窗口。对于每个窗口,它会计算队列的长度,并检查这是否是目前为止找到的最大长度。如果是,那么它就更新最大队列长度,并记录下当前窗口的类型。
当函数完成遍历所有窗口后,它将返回排队人数最多的窗口的类型。你可以使用这个函数的返回值来决定新增窗口的类型。
注意:这个函数假定窗口类型用整数表示,并且每个窗口都有一个唯一的类型。如果你的实现不同,你可能需要进行适当的修改。
页:
[1]