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

简介: 需求描述 编写程序实现限制程序中某类操作的执行次数的需求。为了便于说明,要求程序每天创建一个与上一天不同的文件目录。

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

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

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

目录
相关文章
|
30天前
|
存储 算法 C语言
"揭秘C语言中的王者之树——红黑树:一场数据结构与算法的华丽舞蹈,让你的程序效率飙升,直击性能巅峰!"
【8月更文挑战第20天】红黑树是自平衡二叉查找树,通过旋转和重着色保持平衡,确保高效执行插入、删除和查找操作,时间复杂度为O(log n)。本文介绍红黑树的基本属性、存储结构及其C语言实现。红黑树遵循五项基本规则以保持平衡状态。在C语言中,节点包含数据、颜色、父节点和子节点指针。文章提供了一个示例代码框架,用于创建节点、插入节点并执行必要的修复操作以维护红黑树的特性。
47 1
|
1月前
|
机器学习/深度学习 人工智能 自然语言处理
【自然语言处理】TF-IDF算法在人工智能方面的应用,附带代码
TF-IDF算法在人工智能领域,特别是自然语言处理(NLP)和信息检索中,被广泛用于特征提取和文本表示。以下是一个使用Python的scikit-learn库实现TF-IDF算法的简单示例,并展示如何将其应用于文本数据。
190 65
|
11天前
|
机器学习/深度学习 存储 算法
经典算法代码
这段代码展示了多个经典算法,包括:穷举法解决“百钱买百鸡”问题;递推法计算“猴子吃桃”问题;迭代法求解斐波那契数列及折纸高度超越珠峰的问题。同时,还提供了希尔排序算法实现及披萨票务订购系统和汉诺塔问题的链表存储解决方案。每部分通过具体案例解释了算法的应用场景与实现方法。
17 3
|
1月前
|
搜索推荐 算法 Java
现有一个接口DataOperation定义了排序方法sort(int[])和查找方法search(int[],int),已知类QuickSort的quickSort(int[])方法实现了快速排序算法
该博客文章通过UML类图和Java源码示例,展示了如何使用适配器模式将QuickSort类和BinarySearch类的排序和查找功能适配到DataOperation接口中,实现算法的解耦和复用。
17 1
现有一个接口DataOperation定义了排序方法sort(int[])和查找方法search(int[],int),已知类QuickSort的quickSort(int[])方法实现了快速排序算法
|
1月前
|
机器学习/深度学习 人工智能 算法
【人工智能】传统语音识别算法概述,应用场景,项目实践及案例分析,附带代码示例
传统语音识别算法是将语音信号转化为文本形式的技术,它主要基于模式识别理论和数学统计学方法。以下是传统语音识别算法的基本概述
46 2
|
1月前
|
搜索推荐 算法 Java
|
1月前
|
机器学习/深度学习 运维 算法
深入探索机器学习中的支持向量机(SVM)算法:原理、应用与Python代码示例全面解析
【8月更文挑战第6天】在机器学习领域,支持向量机(SVM)犹如璀璨明珠。它是一种强大的监督学习算法,在分类、回归及异常检测中表现出色。SVM通过在高维空间寻找最大间隔超平面来分隔不同类别的数据,提升模型泛化能力。为处理非线性问题,引入了核函数将数据映射到高维空间。SVM在文本分类、图像识别等多个领域有广泛应用,展现出高度灵活性和适应性。
88 2
|
22天前
|
人工智能 算法 数据可视化
DBSCAN密度聚类算法(理论+图解+python代码)
DBSCAN密度聚类算法(理论+图解+python代码)
|
1月前
|
数据采集 算法 数据可视化
基于K-Means聚类算法对球员数据的聚类分析,可以自主寻找最优聚类数进行聚类
本文介绍了一个基于K-Means聚类算法的NBA球员数据分析项目,该项目通过采集和分析球员的得分、篮板、助攻等统计数据,使用轮廓系数法和拐点法确定最优聚类数,将球员分为不同群组,并提供了一个可视化界面以便直观比较不同群组的球员表现。
基于K-Means聚类算法对球员数据的聚类分析,可以自主寻找最优聚类数进行聚类
|
29天前
|
数据采集 搜索推荐 算法
【高手进阶】Java排序算法:从零到精通——揭秘冒泡、快速、归并排序的原理与实战应用,让你的代码效率飙升!
【8月更文挑战第21天】Java排序算法是编程基础的重要部分,在算法设计与分析及实际开发中不可或缺。本文介绍内部排序算法,包括简单的冒泡排序及其逐步优化至高效的快速排序和稳定的归并排序,并提供了每种算法的Java实现示例。此外,还探讨了排序算法在电子商务、搜索引擎和数据分析等领域的广泛应用,帮助读者更好地理解和应用这些算法。
19 0