停車場收費系統 -开发者知识库

停車場收費系統 -开发者知识库,第1张

#include <stdio.h>
#include <string.h>
#include <stdlib.h>


#include "api.h"
#include "SubwayCharge.h"


FILE *pfWrite  = NULL;


#ifdef __cplusplus
extern "C"
{
#endif
int opGetDistanceBetweenTwoStation(char* sStartStation, char* sObjectStation, int* pnDistance);
int ComputeBasePrice(int distance);
int ComputeChargePrice(int nBasePrice,TravelInfo_ST* pstTravelInfo);
int GetSameStationChargePrice(TravelInfo_ST* pstTravelInfo);
    int ChargeProcess(int nChargePrice, TravelInfo_ST* pstTravelInfo);
    int AddHistoryItemOnListTail(int nChargePrice, TravelInfo_ST* pstTravelInfo);
int IsCheckTimeValid(QueryCond_ST* pstQueryCond, LogItem_ST *logAddr);


    HistoryItem *removeNodeByCardNo(int iCradNo);


    void removeHistoryList(void);


    int IsValidTravel(TravelInfo_ST* pstTravelInfo);
    void searchHistoryNode(int iCardNo);
void Swap(LogItem_ST &logItemA, LogItem_ST &logItemB);
    void SortByCardID(LogItem_ST logItems[], int nItems);
void readFile(void);
    void writeFile(HistoryItem *historyFile);


    void queryLogInf(QueryCond_ST* pstQueryCond);
#ifdef __cplusplus
}
#endif


CardStat_EN g_CardStatusInfo[MAX_MEMBER_NUM] = {CARD_VALID};


/*****************************************************************************
 函 數 名  : main
 功能描述  : 主入口參數(考生無需更改)
 輸入參數  : argc  程序啟動時的參數個數
             argv  程序啟動時的參數
 輸出參數  : 無
 返 回 值  : 無
*****************************************************************************/
void main(int argc, char* argv[])
{
    pHeadHistory = NULL;
readFile();


    /*啟動Socket服務偵聽5555端口(apiServerStart函數在lib庫已實現)*/
    apiServerStart(argc, argv);


    return;
}


/*****************************************************************************
 函 數 名  : opResetProc
 功能描述  : 考生需要實現的接口
             完成程序初始化,或程序功能復位操作
             程序啟動自動調用該函數,r/R命令時自動調用該函數
 輸入參數  : 無
 輸出參數  : 無
 返 回 值  : 無
*****************************************************************************/
void opResetProc(void)
{
    int i = 0;
    for(i = 0; i < MAX_MEMBER_NUM; i )
{
g_CardStatusInfo[i] = CARD_VALID;       //卡號為0-9的可用
}


}


/*****************************************************************************
 函 數 名  : opChargeProc
 功能描述  : 考生需要實現的接口
             完成請求扣費的功能(詳見試題規格說明)
             c/C命令時自動調用該函數
 輸入參數  : pstTravelInfo  單次乘車記錄信息
 輸出參數  : 無
 返 回 值  : 無
*****************************************************************************/
void opChargeProc(TravelInfo_ST* pstTravelInfo)
{
    int nBasePrice = 0;
    int nChargePrice = 0;




    //首先判斷卡是否可用
    if(CARD_UNVAILD == g_CardStatusInfo[pstTravelInfo->nCardNo])
    {
    apiPrintErrInfo(E22);
    return;
    }


    //其次判斷出站時間是否大於等於入站時間
    if(apiTimeDiff(pstTravelInfo->nInHour,pstTravelInfo->nInMinute,pstTravelInfo->nOutHour,pstTravelInfo->nOutMinute) > 0)
    {
    apiPrintErrInfo(E02);
    apiWriteLog(0, pstTravelInfo, RET_ERROR);
    return;
    }


    //最后判斷路徑是否有效
    if (RET_ERROR == IsValidTravel(pstTravelInfo))
    {
        apiPrintOpStatusInfo(I10, pstTravelInfo->nCardNo, pstTravelInfo->nCardMoney);
        return;
    }


    int nDistance = 0;
int flag = 0;
//計算兩個站點之間的距離


flag = opGetDistanceBetweenTwoStation(pstTravelInfo->sInStation ,pstTravelInfo->sOutStation, &nDistance);
if(RET_ERROR == flag)
{
apiPrintOpStatusInfo(I10,pstTravelInfo->nCardNo, pstTravelInfo->nCardMoney);
apiWriteLog(0, pstTravelInfo, RET_ERROR);
return;
}
//計算基本票價
nBasePrice = ComputeBasePrice(nDistance);


//計算扣費票價
nChargePrice = ComputeChargePrice(nBasePrice,pstTravelInfo);


//進行扣費,並將扣費記錄寫入鏈表尾
ChargeProcess(nChargePrice, pstTravelInfo);
return ;


}


/*****************************************************************************
 函 數 名  : opQueryLogProc
 功能描述  : 考生需要實現的接口
             完成查詢乘車記錄日志的功能(詳見試題規格說明)
             q/Q命令時自動調用該函數
 輸入參數  : pstQueryCond  日志查詢條件
 輸出參數  : 無
 返 回 值  : 無
*****************************************************************************/
void opQueryLogProc(QueryCond_ST* pstQueryCond)
{


    int nTimeDiff = 0;




if (NULL == pstQueryCond)
{
//apiPrintErrInfo(E99);
return;
}
    nTimeDiff = apiTimeDiff(pstQueryCond->nStartHour,pstQueryCond->nStartMinute,
                    pstQueryCond->nEndHour,pstQueryCond->nEndMinute);
    if (nTimeDiff > 0)
    {
        apiPrintErrInfo(E02);
        return;
    }


    //printf("%d\n", pstQueryCond->nCardNo);
    if(CARD_UNVAILD == g_CardStatusInfo[pstQueryCond->nCardNo])
    {
       apiPrintErrInfo(E22);
       return;
    }




    queryLogInf(pstQueryCond);


    return;






}


/*****************************************************************************
 函 數 名  : opQueryHistoryChargeListProc
 功能描述  : 考生需要實現的接口
             完成查詢指定卡號的票卡消費歷史記錄功能(詳見試題規格說明)
 輸入參數  : iCardNo  待查詢的票卡卡號
 輸出參數  : 無
 返 回 值  : 無
*****************************************************************************/
void opQueryHistoryChargeListProc(int iCardNo)
{
HistoryItem *p1 = pHeadHistory;


    if (pHeadHistory == NULL)
    {
        apiPrintErrInfo(E21);
        return;
    }


    if (g_CardStatusInfo[iCardNo] == CARD_UNVAILD)
    {
        apiPrintErrInfo(E22);
        return;
    }


    if (0 == iCardNo)
    {
        while(p1 != NULL)
        {
            apiPrintHistoryChargeList(p1);
            writeFile(p1);
            p1 = p1->pNextHistory;
        }
    }
    else
        searchHistoryNode(iCardNo);


    fclose(pfWrite);
}


/*****************************************************************************
 函 數 名  : opDestroyCardProc
 功能描述  : 考生需要實現的接口
             完成注銷指定卡號的票卡消費歷史記錄功能(詳見試題規格說明)
 輸入參數  : iCardNo  待注銷的票卡卡號
 輸出參數  : 無
 返 回 值  : 無
*****************************************************************************/
void opDestroyCardProc(int iCardNo)
{
    int i = 0;


    if ((iCardNo < 0) || (iCardNo > 9))
    {
        apiPrintErrInfo(E99);
        return;
    }
    if ((0 == iCardNo) && (g_CardStatusInfo[0] == CARD_VALID))
    {
        for(i = 0; i < MAX_MEMBER_NUM; i )
    {
    g_CardStatusInfo[i] = CARD_UNVAILD;       //卡號為1-9的不可用
    }
        apiPrintOpStatusInfo(I22, 0, 0);
        removeHistoryList();
    }
    else
    {
        if (g_CardStatusInfo[iCardNo] == CARD_VALID)
        {
            g_CardStatusInfo[iCardNo] = CARD_UNVAILD;
            apiPrintOpStatusInfo(I22, iCardNo, 0);
            removeNodeByCardNo(iCardNo);
        }
        else
        {
            apiPrintErrInfo(E22);
            return;
        }
    }
}


/*其他函數定義考生根據功能需要補充*/




void readFile(void)
{
STA_INFO_S *p1, *p2;
    FILE *pf  = NULL;
    char station[4];
    int distance;


    //打開讀取
    pf = fopen("d:\\station_info.txt", "r");
    pfWrite = fopen("d:\\SubwayCharge.txt", "w");


    if (NULL == pf)
    {
        printf("error");
        return;
    }


    while(EOF != fscanf(pf, "%s %d\n", station, &distance))
    {
p1 = (STA_INFO_S *)malloc(sizeof(STA_INFO_S));
strcpy(p1->sStation, station);
p1->dist = distance;
if (NULL == g_StationList)
{
g_StationList = p1;
p2 = p1;
}
else
{
p2->pNextStation = p1;
p2 = p1;
}
p2->pNextStation = NULL;
    }


/*q = g_StationList;
while (q)
{
printf("%s %d\n", q->sStation, q->dist);
q = q->pNextStation;
};*/


    fclose(pf);


}




void writeFile(HistoryItem *historyFile)
{
char text[100] = {"卡號:"};


    char nCardNo[3] = {" "};
    char nInHour[4];
    char nInMin[4];
    char nOutHour[4];
    char nOutMin[4];
    char nMoney[4];


    sprintf(nCardNo, "%d", historyFile->nCardNo);
    sprintf(nMoney, "%d", historyFile->nMoney);


    sprintf(nInHour, "%d", historyFile->nInHour);
    sprintf(nInMin, "%d", historyFile->nInMin);
    sprintf(nOutHour, "%d", historyFile->nOutHour);
    sprintf(nOutMin, "%d", historyFile->nOutMin);


    strcat(text, nCardNo);


    switch(historyFile->enCardType)
    {
        case CARDTYPE_A: strcat(text, " 卡類別:單程表 進站時間:"); break;


        case CARDTYPE_B: strcat(text, " 卡類別:老年卡 進站時間:"); break;


        case CARDTYPE_C: strcat(text, " 卡類別:普通卡 進站時間:"); break;
    }


    strcat(text, nInHour);
    strcat(text, ":");
    if ((historyFile->nInMin < 10) || ((historyFile->nInMin) == 0))
        strcat(text, "0");
    strcat(text, nInMin);
    strcat(text, " 進站名稱:");
    strcat(text, historyFile->sInStation);


    strcat(text, " 出站時間:");
    strcat(text, nOutHour);
    strcat(text, ":");
    if((historyFile->nOutMin < 10) || ((historyFile->nOutMin) == 0))
        strcat(text, "0");
    strcat(text, nInMin);
    strcat(text, " 出站名稱:");
    strcat(text, historyFile->sOutStation);
    strcat(text, "\n");


    printf("%d", strlen(text));


    fputs(text, pfWrite);


}




int IsValidTravel(TravelInfo_ST* pstTravelInfo)
{
int i = 0;
    STA_INFO_S *p1 = g_StationList;
    if (p1 == NULL)
    {
        apiPrintErrInfo(E99);
        return RET_ERROR;
    }
    for (p1 = g_StationList; p1 != NULL; p1 = p1->pNextStation)
    {
        if(!strcmp(p1->sStation, pstTravelInfo->sInStation))
{
i = 1;
break;
}
    }
for (p1 = g_StationList; p1 != NULL; p1 = p1->pNextStation)
{
if(!strcmp(p1->sStation, pstTravelInfo->sOutStation) && (i = 1))
{
return RET_OK;
}
}
    return RET_ERROR;
}






int opGetDistanceBetweenTwoStation(char* sStartStation, char* sObjectStation, int* pnDistance)
{
STA_INFO_S *p1 = NULL;
int startDis = 0, objDis = 0;


if (g_StationList == NULL)
{
        printf("error");
return RET_ERROR;
}


for (p1 = g_StationList; p1 != NULL; p1 = p1->pNextStation)
{
if (!strcmp(sStartStation, p1->sStation))
startDis = p1->dist;
if (!strcmp(sObjectStation, p1->sStation))
objDis = p1->dist;
}


*pnDistance = abs(startDis-objDis);


    return RET_OK;
}




//計算基本票價
int ComputeBasePrice(int distance)
{


if (0 >= distance)
{
return 0;
}
else if ((0 < distance) && (3 >= distance))
{
return 2;
}
else if ((3 < distance) && (5 >= distance))
{
return 3;
}
else if ((5 < distance) && (10 >= distance))
{
return 4;
}
else
{
return 5;
}


}


//計算扣費票價
int ComputeChargePrice(int baseprice, TravelInfo_ST* pstTravelInfo)
{
    int nInHour = 0;
    int nInMin = 0;


    int nCmpWith07_00 = 0;
    int nCmpWith09_00 = 0;
    int nCmpWith16_30 = 0;
    int nCmpWith18_30 = 0;


    int nCmpWith10_00 = 0;
    int nCmpWith11_00 = 0;
    int nCmpWith15_00 = 0;
    int nCmpWith16_00 = 0;
//同站進出
if(0 == strcmp(pstTravelInfo->sInStation, pstTravelInfo->sOutStation))
{
return GetSameStationChargePrice(pstTravelInfo);
}
//非同站進出
else
{
//票卡為單程票
if(CARDTYPE_A == pstTravelInfo->enCardType)
{
return (pstTravelInfo->nCardMoney > baseprice) ? pstTravelInfo->nCardMoney : baseprice;
}
//票卡為非單程票
else
{
nInHour = pstTravelInfo->nInHour;
nInMin = pstTravelInfo->nInMinute;
nCmpWith07_00 = apiTimeDiff(nInHour, nInMin, 7, 0);
nCmpWith09_00 = apiTimeDiff(nInHour, nInMin, 9, 0);
nCmpWith16_30 = apiTimeDiff(nInHour, nInMin, 16, 30);
nCmpWith18_30 = apiTimeDiff(nInHour, nInMin, 18, 30);
if (((0 <= nCmpWith07_00) && (0 > nCmpWith09_00))
                        || ((0 <= nCmpWith16_30) && (0 > nCmpWith18_30)))//處於非優惠時段
{
return baseprice;
}


else
{
   nCmpWith10_00 = apiTimeDiff(nInHour, nInMin, 10, 0);
nCmpWith11_00 = apiTimeDiff(nInHour, nInMin, 11, 0);
nCmpWith15_00 = apiTimeDiff(nInHour, nInMin, 15, 0);
nCmpWith16_00 = apiTimeDiff(nInHour, nInMin, 16, 0);
if (((0 <= nCmpWith10_00) && (0 > nCmpWith11_00))
                        || ((0 <= nCmpWith15_00) && (0 > nCmpWith16_00)))   // 處於優惠時段
{
return baseprice/2;
}
else
{
if(CARDTYPE_C == pstTravelInfo->enCardType)
{
return baseprice;
}
else if(CARDTYPE_B == pstTravelInfo->enCardType)
{
return (baseprice*9)/10;
}
}
}
}
}
return 0;
}


//計算同站進出的情況
int GetSameStationChargePrice(TravelInfo_ST* pstTravelInfo)
{
// if(NULL == pstTravelInfo)
    int nMoney = 0;
    int nTimeDiff = 0;
    CardType_EN nCardType;


nMoney = pstTravelInfo->nCardMoney;   //卡金額
nCardType= pstTravelInfo->enCardType;
nTimeDiff = apiTimeDiff(pstTravelInfo->nOutHour, pstTravelInfo->nOutMinute, pstTravelInfo->nInHour, pstTravelInfo->nInMinute);
if(nTimeDiff <= 30)
{
if(CARDTYPE_A == nCardType)  //單程票
return nMoney;
else
return 0;
}
else
{
if(CARDTYPE_A == nCardType)  //單程票
{
return (nMoney>3 ? nMoney:3);
}
else
{
return 3;
}
}


// return 0;
}


int ChargeProcess(int nChargePrice, TravelInfo_ST* pstTravelInfo)
{


int nCardID = pstTravelInfo->nCardNo;
int nLogItems = apiGetLogNum();
//判斷扣費票價是否大於卡上余額
if(nChargePrice > pstTravelInfo->nCardMoney)
{
apiPrintOpStatusInfo(I13,nCardID, pstTravelInfo->nCardMoney);


apiWriteLog(0,pstTravelInfo,RET_ERROR);


return RET_ERROR;
}


    //計算出消費完成之后的余額
pstTravelInfo->nCardMoney = pstTravelInfo->nCardMoney - nChargePrice;


    //如果是單程票
if(CARDTYPE_A == pstTravelInfo->enCardType)
{
apiPrintOpStatusInfo(I11, nCardID, pstTravelInfo->nCardMoney);
}


    //非單程票
else
{
if(pstTravelInfo->nCardMoney >= 20)
{
apiPrintOpStatusInfo(I11, pstTravelInfo->nCardNo, pstTravelInfo->nCardMoney);
}
        //若果卡內余額小於20的情況,做出提醒
else
{
apiPrintOpStatusInfo(I12, pstTravelInfo->nCardNo, pstTravelInfo->nCardMoney);
}
}


//寫日志
apiWriteLog(nChargePrice, pstTravelInfo, RET_OK);


//將扣費記錄添加到鏈表尾
if(RET_OK == AddHistoryItemOnListTail(nChargePrice,pstTravelInfo))
{
return RET_OK;
}
else
{
return RET_ERROR;
}


}




void queryLogInf(QueryCond_ST* pstQueryCond)
{
    LogItem_ST tmpLogItem[MAX_LOG_RECORD_NUM];
    LogItem_ST *pLogAddr;
    int i = 0, j = 0;
    int nItems = 0;
    int nLogItemCnt = 0;


    memset(tmpLogItem, 0, sizeof(LogItem_ST) * MAX_LOG_RECORD_NUM);
    pLogAddr = apiGetLogAddr();
    nItems = apiGetLogNum();


    if (0 == pstQueryCond->nCardNo)
    {
        for(i = 1; i < MAX_LOG_RECORD_NUM; i )
        {
            if(CARD_VALID == g_CardStatusInfo[i])
            {
                for(j = 0; j < nItems 1; j )
{


if((i == pLogAddr[j].nCardNo)
                                && (RET_OK == IsCheckTimeValid(pstQueryCond,pLogAddr j)))
{
memcpy(&(tmpLogItem[nLogItemCnt]),&(pLogAddr[j]),sizeof(LogItem_ST));
nLogItemCnt ;
}
}
            }
        }
    }
else
{
for(j = 0; j < nItems; j )
{
if((pstQueryCond->nCardNo == pLogAddr[j].nCardNo)
                    && (RET_OK == IsCheckTimeValid(pstQueryCond,pLogAddr j)))


{
memcpy(&(tmpLogItem[nLogItemCnt]), &(pLogAddr[j]), sizeof(LogItem_ST));
nLogItemCnt ;
}
}
}


if(nLogItemCnt <= 0)
{
apiPrintErrInfo(E21);
return;
}
else
{
//根據卡號進行排序
SortByCardID(tmpLogItem, nLogItemCnt);


apiPrintLog(tmpLogItem, nLogItemCnt);
}


    return;
}


int IsCheckTimeValid(QueryCond_ST* pstQueryCond, LogItem_ST *logAddr)
{


    int nQueryStartHour, nQueryStartMin, nQueryEndHour, nQueryEndMin;
    int nLogStartHour, nLogStartMin, nLogEndHour, nLogEndMin;


if(NULL == pstQueryCond || NULL == logAddr)
{
apiPrintErrInfo(E99);
return RET_ERROR;
}
nQueryStartHour = pstQueryCond->nStartHour;
nQueryStartMin = pstQueryCond->nStartMinute;
nQueryEndHour = pstQueryCond->nEndHour;
nQueryEndMin = pstQueryCond->nEndMinute;


nLogStartHour = logAddr->nInHour;
nLogStartMin = logAddr->nInMin;
nLogEndHour = logAddr->nOutHour;
nLogEndMin = logAddr->nOutMin;


if((apiTimeDiff(nQueryStartHour, nQueryStartMin, nLogEndHour, nLogEndMin) <= 0)
&& (apiTimeDiff(nLogEndHour,nLogEndMin,nQueryEndHour,nQueryEndMin) <= 0))
{
return RET_OK;
}
else
{
return RET_ERROR;
}


}




void Swap(LogItem_ST &logItemA, LogItem_ST &logItemB)
{
LogItem_ST tmp;
memcpy(&tmp, &logItemA, sizeof(LogItem_ST));
memcpy(&logItemA, &logItemB, sizeof(LogItem_ST));
memcpy(&logItemB, &tmp, sizeof(LogItem_ST));
}


//利用冒泡排序對卡號進行排序
void SortByCardID(LogItem_ST logItems[], int nItems)
{
if(NULL == logItems || nItems <= 0)
{
return;
}
int i = 0, k = nItems;
int flag = 1;
while(flag)
{
flag = 0;
for (i = 1; i < k; i )
{
if (logItems[i - 1].nCardNo > logItems[i].nCardNo)
{
Swap(logItems[i - 1], logItems[i]);
flag = 1;
}
}
k--;
}
}




int AddHistoryItemOnListTail(int nChargePrice, TravelInfo_ST* pstTravelInfo)
{
    HistoryItem *p1, *p2 = pHeadHistory;


p1 = (HistoryItem *)malloc(sizeof(HistoryItem));


    p1->enCardType = pstTravelInfo->enCardType;
p1->nCardNo = pstTravelInfo->nCardNo;
p1->nInHour = pstTravelInfo->nInHour;
p1->nInMin = pstTravelInfo->nInMinute;
    strcpy(p1->sInStation, pstTravelInfo->sInStation);
p1->nMoney = nChargePrice;
p1->nOutHour = pstTravelInfo->nOutHour;
p1->nOutMin = pstTravelInfo->nOutMinute;
    strcpy(p1->sOutStation, pstTravelInfo->sOutStation);


    if (NULL == p1)
    {
        printf("error");
        return RET_ERROR;
    }


    if (NULL == p2)
    {
        pHeadHistory = p1;
        p1->pNextHistory = NULL;
    }
    else
    {
        for (p2 = pHeadHistory; ; p2 = p2->pNextHistory)
        {
            if (p2->pNextHistory == NULL)
            {
                p2->pNextHistory = p1;
                p1->pNextHistory = NULL;
                break;
            }
        }
    }


return RET_OK;


}


HistoryItem *removeNodeByCardNo(int iCradNo)
{
    HistoryItem *pNode      = NULL;
    HistoryItem *pDelNode   = NULL;


    if ((NULL == pHeadHistory) || (iCradNo < 0))
    {
        //apiPrintErrInfo(E99);
        return NULL;
    }


    while((iCradNo == pHeadHistory->nCardNo))
    {
        pDelNode = pHeadHistory;
        pHeadHistory = pHeadHistory->pNextHistory;
free(pDelNode);
        if(pHeadHistory == NULL)
            return NULL;
    }


    for (pNode = pHeadHistory; pNode->pNextHistory!= NULL; )
    {
        pDelNode = pNode->pNextHistory;
        if (pNode->pNextHistory->nCardNo== iCradNo)
        {
            if (pNode->pNextHistory->pNextHistory == NULL)
{
pNode->pNextHistory = NULL;
pDelNode = pDelNode->pNextHistory;
free(pDelNode);
break;
}
else
{
pNode->pNextHistory = pDelNode->pNextHistory;
free(pDelNode);
}
        }
else
pNode = pNode->pNextHistory;
    }


    if (NULL == pDelNode)
        return NULL;


    free(pDelNode);
    return pHeadHistory;
}


void removeHistoryList(void)
{
    HistoryItem *pNode, *pTemp;
    if (NULL == pHeadHistory)
    {
        return;
    }


    pNode = pHeadHistory;
    pTemp = pNode->pNextHistory;


    if (pTemp == NULL)
    {
        free(pNode);
    }
    else
    {
        while(pTemp != NULL)
        {
            free(pNode);
            pNode = pTemp;
            pTemp = pTemp->pNextHistory;
        }
        free(pNode);
    }
    pNode = NULL;


    return;
}




void searchHistoryNode(int iCardNo)
{
    int i = 0;
    HistoryItem *p1;
if (NULL == pHeadHistory)
{
apiPrintErrInfo(E99);
return;
}
for (p1 = pHeadHistory; p1 != NULL; p1 = p1->pNextHistory)
{
if (p1->nCardNo == iCardNo)
{
            apiPrintHistoryChargeList(p1);
            writeFile(p1);
            i = 1;
}
}
    if (0 == i)
        apiPrintErrInfo(E21);
    return;
}



最佳答案:

本文经用户投稿或网站收集转载,如有侵权请联系本站。

发表评论

0条回复