鱼C论坛

 找回密码
 立即注册
查看: 722|回复: 1

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

[复制链接]
发表于 2023-6-14 21:49:06 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
我已完成的代码如下:

#include <stdio.h>
#include "util.h"
#include "linklist.h"

typedef enum
{
    wsNormal = 0, //窗口正常
    wsPause  = 1
} EWinStatus;

#define WIN_TYPE_SIZE 32
typedef char WinType[WIN_TYPE_SIZE];
static char gszWinTypeTip[256];
static WinType gWinType[10] = {0}; //窗口业务类型,最多10个类型
static LinkListMan gLinkMan = {0};
static int gQueueId = 1; //排队号
char gaWinPointDesc[][WIN_TYPE_SIZE] = {"差", "良", "好"};
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[2][16] = {"正常", "暂停"};

    PRINTF("窗口号\t状态\t排队人数\t平均得分\n");
    while (p != NULL)
    {
        const SWin *pWin = &(p->win);
        char szScore[32];

        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[pWin->status], 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.Point],q->win.ScoreSum, q->win.RemarkNum);
        }
        else if(nPoint == 3)
        {
            printf("暂不评价,谢谢!\n");
        }
        else
        {
            printf("评价错误!\n");
        }
        return;
    }
}

Status LoadData()
{
    int Num, i;
    char szDefaultWinType[][WIN_TYPE_SIZE] = {"个人业务", "对公业务", "现金业务", "非现金业务"};
    char szTag[32];
    char szSection[32];

    //读取窗口的业务类型
    Num = ReadCfgFileInt("WinType", "Num", 4);
    for (i = 1; i <= Num; i++)
    {
        sprintf(szTag, "Type%d", i);
        ReadCfgFileString("WinType", szTag, szDefaultWinType[i-1], gWinType[i-1], 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[32];

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


//可统计当前排队人数最多的窗口业务类型,为新增窗口提供依据;
最佳答案
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;
}
这个函数首先获取第一个窗口节点,然后遍历所有的窗口。对于每个窗口,它会计算队列的长度,并检查这是否是目前为止找到的最大长度。如果是,那么它就更新最大队列长度,并记录下当前窗口的类型。

当函数完成遍历所有窗口后,它将返回排队人数最多的窗口的类型。你可以使用这个函数的返回值来决定新增窗口的类型。

注意:这个函数假定窗口类型用整数表示,并且每个窗口都有一个唯一的类型。如果你的实现不同,你可能需要进行适当的修改。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 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;
}
这个函数首先获取第一个窗口节点,然后遍历所有的窗口。对于每个窗口,它会计算队列的长度,并检查这是否是目前为止找到的最大长度。如果是,那么它就更新最大队列长度,并记录下当前窗口的类型。

当函数完成遍历所有窗口后,它将返回排队人数最多的窗口的类型。你可以使用这个函数的返回值来决定新增窗口的类型。

注意:这个函数假定窗口类型用整数表示,并且每个窗口都有一个唯一的类型。如果你的实现不同,你可能需要进行适当的修改。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-12-22 11:33

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表