圆圆圈圈圆圆 发表于 2023-6-14 21:49:06

新手菜鸟求助,怎么把写统计当前排队人数最多的窗口业务类型,为新增窗口提供依据

我已完成的代码如下:

#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;
}


//可统计当前排队人数最多的窗口业务类型,为新增窗口提供依据;

isdkz 发表于 2023-6-14 22:18:30

为了统计当前排队人数最多的窗口业务类型,你需要创建一个统计函数,并在其中遍历所有的窗口,跟踪并比较每个窗口的排队人数。这个函数将返回人数最多的窗口的类型。

以下是代码的概念性实现,你可能需要按照你的具体项目来对其进行修改:

// 函数返回排队人数最多的窗口的业务类型
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]
查看完整版本: 新手菜鸟求助,怎么把写统计当前排队人数最多的窗口业务类型,为新增窗口提供依据