IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    [原]限制程序中某类操作的执行次数的算法设计及C代码实现

    zhouzxi发表于 2016-08-31 20:40:32
    love 0

    需求描述
    编写程序实现限制程序中某类操作的执行次数的需求。为了便于说明,要求程序每天创建一个与上一天不同的文件目录。如果欲创建的文件目录已存在,则不用再创建。文件目录的命名格式为:FileDir_YYYYMMDD,如:FileDir_20160830。

    程序流程
    对于此类需求,最关键的问题是要设定一个标识来限制操作的执行次数。也就是说,当程序执行完一次操作之后,要有机制来限制它执行第二次操作。

    因为本需求要求每天执行一次操作,所有我们自然想到了用日期来限制程序的执行次数。我们可以用一个全局时间变量来存放每次创建文件目录的日期,如果当前日期和全局时间变量中的日期相等,就表示当天已经执行过操作了,不用再次执行。

    基于上面的分析,我们可以画出如下的程序流程图:
    这里写图片描述

    C代码

    /**********************************************************************
    * 版权所有 (C)2016, Zhou Zhaoxiong
    *
    * 文件名称:DirCreateControl.c
    * 文件标识:无
    * 内容摘要:限制创建目录操作的执行次数的C代码实现
    * 其它说明:无
    * 当前版本:V1.0
    * 作   者:ZhouZhaoxiong
    * 完成日期:20160830
    *
    **********************************************************************/
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <dirent.h>
    #include <unistd.h>
    #include <time.h>
    
    
    // 重定义数据类型
    typedef signed  int         INT32;
    typedef unsigned int        UINT32;
    typedef unsigned char       UINT8;
    typedef unsigned short int  UINT16;
    typedef long     int        LONG;
    
    // 全局变量
    UINT8 g_szLastExecDate[10] = {0};       // 上一次执行操作的日期, 格式为: 年月日(YYYYMMDD)
    
    // 时间结构体
    typedef struct
    {
        UINT8   second;    /* 0-59 */
        UINT8   minute;    /* 0-59 */
        UINT8   hour;      /* 0-23 */
        UINT8   day;       /* 1-31 */
        UINT8   month;     /* 1-12 */
        UINT16  year;      /* 1994-2099 */
        UINT8   week;      /* 1-7 */
        UINT8   Count10ms; /* 0-99 */
    } ClockStruc;
    
    // 函数声明
    void GetCurrentTime(ClockStruc *ptTime);
    INT32 JudgeIfExecOper(ClockStruc *ptTime);
    void CreateFileDir(UINT8 *pszFileDir);
    void Sleep(UINT32 iCountMs);
    
    
    /****************************************************************
    * 功能描述: 主函数
    * 输入参数: 无
    * 输出参数: 无
    * 返 回 值: 0-执行完成
    * 其他说明: 无
    * 修改日期         版本号        修改人         修改内容
    *-------------------------------------------------------------
    * 20160830        V1.0     Zhou Zhaoxiong      创建
    ****************************************************************/
    INT32 main(void)
    {
        ClockStruc tTimeNow       = {0};      // 当前时间结构体
        UINT8      szFileDir[100] = {0};      // 文件路径变量
        INT32      iRetVal        = 0;        // 执行函数之后的返回值
    
        while (1)      // 循环执行创建目录的操作
        {
            Sleep(10 *1000);    // 程序执行间隔为10s
    
            // 首先判断当天是否已执行过操作
            iRetVal = JudgeIfExecOper(&tTimeNow);
            if (iRetVal != 0)    // 不用执行创建目录的操作
            {
                continue;
            }
    
            // 构造目录
           snprintf(szFileDir, sizeof(szFileDir)-1,"%s/zhouzx/Test/FileDir_%04d%02d%02d/", getenv("HOME"),                             tTimeNow.year, tTimeNow.month, tTimeNow.day);
    
            // 接着创建目录
           CreateFileDir(szFileDir);
        }
    
        return 0;
    }
    
    
    /**********************************************************************
    * 功能描述:获取当前时间
    * 输入参数:ptTime-当前时间结构体
    * 输出参数:ptTime-当前时间结构体
    * 返 回 值:无
    * 其它说明:无
    * 修改日期        版本号          修改人         修改内容
    *-------------------------------------------------------------------
    * 20160830       V1.0       Zhou Zhaoxiong     创建
    ***********************************************************************/
    void GetCurrentTime(ClockStruc *ptTime)
    {
        LONG     dt           = 0;
        struct   tm     *tm1  = NULL;
        struct   timeval tp   = {0};
    
        // 获取系统时间
        gettimeofday(&tp, NULL);
        dt  = tp.tv_sec;
        tm1 = localtime(&dt);
    
        ptTime->Count10ms = tp.tv_usec / 10000;
        ptTime->year      = (UINT16)(tm1->tm_year + 1900);
        ptTime->month     = (UINT8)tm1->tm_mon + 1;
        ptTime->day       = (UINT8)tm1->tm_mday;
        ptTime->hour      = (UINT8)tm1->tm_hour;
        ptTime->minute    = (UINT8)tm1->tm_min;
        ptTime->second    = (UINT8)tm1->tm_sec;
        ptTime->week      = (UINT8)tm1->tm_wday;
    
        if (ptTime->week == 0)   // 星期天
        {
            ptTime->week = 7;
        }
    }
    
    
    /**********************************************************************
    * 功能描述:判断当天是否已执行过操作
    * 输入参数:ptTime-当前时间结构体
    * 输出参数:ptTime-当前时间结构体
    * 返 回 值:1-已执行  0-未执行  -1-程序异常
    * 其它说明:无
    * 修改日期        版本号          修改人          修改内容
    * -------------------------------------------------------------------
    * 20160830       V1.0       Zhou Zhaoxiong       创建
    ***********************************************************************/
    INT32 JudgeIfExecOper(ClockStruc *ptTime)
    {
        UINT8szCurrentDate[10] = {0};
    
        if (ptTime == NULL)
        {
           printf("JudgeIfExecOper: ptTime is NULL!\n");
    
            return -1;
        }
    
       GetCurrentTime(ptTime);     // 获取当前时间
    
       snprintf(szCurrentDate, sizeof(szCurrentDate)-1,"%04d%02d%02d", ptTime->year, ptTime->month, ptTime->day);
    
        // 判断当前日期和上次执行日期是否相等, 如果相等, 则不用再执行操作了
        if (strcmp(szCurrentDate, g_szLastExecDate) != 0)  // 两者不相等
        {
           printf("JudgeIfExecOper: CurrentDate is not equal to LastExecDate,so go ahead!\n");
    
           memset(g_szLastExecDate, 0x00, sizeof(g_szLastExecDate));
           memcpy(g_szLastExecDate, szCurrentDate, strlen(szCurrentDate));   // 将上次执行日期更新为当前日期
    
            return 0;
        }
        else
        {
           printf("JudgeIfExecOper: CurrentDate is %s, LastExecDate is %s,they are equal, so do not go ahead!\n", szCurrentDate, g_szLastExecDate);
    
            return 1;
        }
    }
    
    /****************************************************************
    * 功能描述: 创建目录
    * 输入参数: pszFileDir-目录
    * 输出参数: 无
    * 返 回 值: 无
    * 其他说明: 无
    * 修改日期         版本号        修改人       修改内容
    * -------------------------------------------------------------
    * 20160830        V1.0   Zhou Zhaoxiong     创建
    ****************************************************************/
    void CreateFileDir(UINT8 *pszFileDir)
    {
        UINT8 szCmdbuf[100] = {0};
    
        if (pszFileDir ==NULL)
        {
            printf("CreateFileDir: pszFileDir is NULL!\n");
    
            return;
        }
    
        // 下面执行目录创建操作
        // 第一步判断目录是否存在
        // 第二步创建目录
        if (0 != access(pszFileDir, F_OK))   // 目录不存在
        {
            // 创建目录
            memset(szCmdbuf,0x00, sizeof(szCmdbuf));
            snprintf(szCmdbuf, sizeof(szCmdbuf)-1, "mkdir -p %s",pszFileDir);
            system(szCmdbuf);
    
            printf("CreateFileDir: %s has created successfully!\n",pszFileDir);
        }
        else        // 目录存在
        {
            printf("CreateFileDir:%s has already existed!\n", pszFileDir);
        }
    }
    
    
    /**********************************************************************
    * 功能描述:程序休眠
    * 输入参数:iCountMs-休眠时间(单位:ms)
    * 输出参数:无
    * 返 回 值:无
    * 其它说明:无
    * 修改日期         版本号         修改人       修改内容
    * ------------------------------------------------------------------
    * 20160830        V1.0     Zhou Zhaoxiong     创建
    ********************************************************************/
    void Sleep(UINT32 iCountMs)
    {
        struct timevalt_timeout = {0};
    
    
        if (iCountMs <1000)
        {
           t_timeout.tv_sec  = 0;
           t_timeout.tv_usec = iCountMs * 1000;
        }
        else
        {
           t_timeout.tv_sec  = iCountMs /1000;
           t_timeout.tv_usec = (iCountMs % 1000) * 1000;
        }
        select(0, NULL,NULL, NULL, &t_timeout);    // 调用select函数阻塞程序
    }

    程序编译及执行
    我们把上面编写好的DirCreateControl.c文件上传到Linux机器上,使用“gcc -g -o DirCreateControlDirCreateControl.c”命令编译之后,生成DirCreateControl文件,然后执行“DirCreateControl”命令,可对程序进行测试。
    1)当被创建的目录不存在时,程序执行结果如下:

    > DirCreateControl
    JudgeIfExecOper: CurrentDate is not equal to LastExecDate, sogo ahead!
    CreateFileDir: /home/zhou/zhouzx/Test/FileDir_20160830/ hascreated successfully!
    JudgeIfExecOper: CurrentDate is 20160830, LastExecDate is20160830, they are equal, so do not go ahead!
    JudgeIfExecOper: CurrentDate is 20160830, LastExecDate is20160830, they are equal, so do not go ahead!
    JudgeIfExecOper: CurrentDate is 20160830, LastExecDate is20160830, they are equal, so do not go ahead!
    JudgeIfExecOper: CurrentDate is 20160830, LastExecDate is20160830, they are equal, so do not go ahead!
    JudgeIfExecOper: CurrentDate is 20160830, LastExecDate is20160830, they are equal, so do not go ahead!

    2)当被创建的目录已经存在时,程序执行结果如下:

    > DirCreateControl
    JudgeIfExecOper: CurrentDate is not equal to LastExecDate, sogo ahead!
    CreateFileDir: /home/zhou/zhouzx/Test/FileDir_20160830/ hasalready existed!
    JudgeIfExecOper: CurrentDate is 20160830, LastExecDate is20160830, they are equal, so do not go ahead!
    JudgeIfExecOper: CurrentDate is 20160830, LastExecDate is20160830, they are equal, so do not go ahead!
    JudgeIfExecOper: CurrentDate is 20160830, LastExecDate is20160830, they are equal, so do not go ahead!
    JudgeIfExecOper: CurrentDate is 20160830, LastExecDate is20160830, they are equal, so do not go ahead!
    JudgeIfExecOper: CurrentDate is 20160830, LastExecDate is20160830, they are equal, so do not go ahead!
    JudgeIfExecOper: CurrentDate is 20160830, LastExecDate is20160830, they are equal, so do not go ahead!
    JudgeIfExecOper: CurrentDate is 20160830, LastExecDate is20160830, they are equal, so do not go ahead!
    JudgeIfExecOper: CurrentDate is 20160830, LastExecDate is20160830, they are equal, so do not go ahead!

    可以看到,不管被创建的目录是否存在,程序在一天当中都只执行一次创建目录的操作,而当天剩下的大部分时间都是在检查第二天是否来到,如果没有来到,则继续等待;如果已经来到,则再次重复昨天的操作。

    总结
    在实际的软件开发项目中,我们经常遇到需要限制程序中某类操作的执行次数的情况,本文只是给出了其中的一种解决办法。在实际编写代码的时候,大家要根据程序的特点及需求要求采用合理的实现方法。



沪ICP备19023445号-2号
友情链接