C++动态配置的实现

先说一下需求,是在做录音系统中遇到的:录音文件名需要生成唯一的字符串,这个串一般由主叫号码、被叫号码、日期、时间等加上下划线作为分隔符组成,但出于兼容性考虑,某些用户希望能按他们自己的顺序来构成文件名。


除了文件名,录音文件存放路径也需要动态的配置,比如:

基础路径/日期/

或:

基础路径/被叫号码/日期/


我的解决方案是设计这样的配置文件:

// 配置项的值可使用变量,用中括号括起来的部分: [caller]-主叫号码, [callee]-被叫号码, [date]-日期(yyyymmdd), [time]-时间(hhmmss)
// 录音基础路径:
RecPath = d:\rec\[date]\[callee]\

// 文件名构成:
RecSessionFormat = [caller]_[callee]_[date]_[time]
// 连接线只可使用下划线,文件名只能使用关键字和下划线分隔符


实现一个类StringMaker,效果是这样的:

路径生成:

   StringMaker* _dirMaker = new StringMaker("d:\\rec\\[date]\\[callee]\\");
   string dir = _recFileMaker->Make("13902123456", "075583841234");
   printf("dir=%s\n", dir.c_str());  // 输出:dir=d:\rec\20161112\075583841234\

文件名生成:

   StringMaker* _sessionMaker = new StringMaker("[caller]_[callee]_[date]_[time]");
   file = _sessionMaker->Make("13902123456", "075583841234");
   printf("session=%s\n", file.c_str()); // 输出:13902123456_075583841234_20161112_132530
   file = _sessionMaker->Make("26766666", "10086");
   printf("session=%s\n", file.c_str());


还希望有个文件名反向分解的功能,即如果给定一个字符串,能够将各部份给分离出来,然后定位出文件的绝对路径。
比如,注意代码接上面部分:
   char caller[100];
   char callee[100];
   char date[100];
   char time[100];
   int ret = _sessionMaker->Resolve("13312345678_10010_20161115_090856", caller, callee, date, time);
   printf("Resolve: %d:\n", ret);
   if (ret > 0){
      printf(" caller=%s\n", caller);  // 输出:13312345678
      printf(" callee=%s\n", callee);  // 输出:10010
      printf(" date=%s\n", date);  // 输出:20161115
      printf(" time=%s\n", time);  // 输出:090856
   }

实现过程的完整代码如下,自认为还比较巧妙:
// StringMaker.cpp : C++动态配置实现。
//
# if defined(_MSC_VER)
# ifndef _CRT_SECURE_NO_DEPRECATE
# define _CRT_SECURE_NO_DEPRECATE (1)
# endif
# pragma warning(disable : 4996)
# endif

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

#include <windows.h>

#include <string>
#include <vector>
#include <mutex>

using namespace std;

class StringMaker
{
public:
   StringMaker(const char* cfgString);
   string Make(const string& pCaller, const string& pCallee);

   // 反向分解:将输入id分解为各部分并输出参数(C字符串格式)
   int Resolve(const char* id, char* pCaller, char* pCallee, char* pDate, char* pTime); 
private:
   vector<string*> items;
   mutex _mutex; // 锁,多线程操作时保证安全

   string caller;
   string callee;
   string date;
   string time;
};

// 反向分解:,约定:分隔符为'_',没有其他非关键字类型
int StringMaker::Resolve(const char* id, char* pCaller, char* pCallee, char* pDate, char* pTime)
{
   char ch;
   char item[200];
   int i = 0;
   int count = 0;
   _mutex.lock();
   while ((ch = *id++) != '\0'){
      if (ch == '_'){
         if (i){
            item[i] = '\0';
            i = 0;
            if (count + 1 > items.size()){
               return(-1);
            }            
            *items[count] = item;
            // printf("count=%d: '%s'\n", count, item);
            count++;
         }
         count++;  // 分隔符本身就是一项
      }
      else{
         item[i++] = ch;
      }
   }
   if (i){
      item[i] = '\0';
      if (count + 1 > items.size()){
         return(-2);
      }
      *items[count] = item;
      // printf("count=%d: '%s'\n", count, item);
      count++;
   }
   strcpy(pCaller, caller.c_str());
   strcpy(pCallee, callee.c_str());
   strcpy(pDate, date.c_str());
   strcpy(pTime, time.c_str());

   _mutex.unlock();
   return(count);
}

StringMaker::StringMaker(const char* cfgString)
{
   char ch;
   char cmd[500];
   int i = 0;
   bool isCmd = false;
   while ((ch = *cfgString++) != '\0'){
      if (ch == '['){  // 命令开始
         if (i){
            cmd[i] = '\0';
            string* s = new string(cmd);
            i = 0;
            items.push_back(s);
         }
         isCmd = true;
      }
      else if (ch == ']'){  // 命令结束
         if (i && isCmd){
            cmd[i] = '\0';
            string* s = 0;
            if (stricmp(cmd, "date") == 0)
               s = &date;
            else if (stricmp(cmd, "time") == 0)
               s = &time;
            else if (stricmp(cmd, "caller") == 0)
               s = &caller;
            else if (stricmp(cmd, "callee") == 0)
               s = &callee;

            if (s){
               items.push_back(s);
            }
         }  // else ERROR...

         i = 0;
         isCmd = false;
      }
      else{
         cmd[i++] = ch;
      }
   }
   if (i){
      cmd[i] = '\0';
      string* s = 0;
      if (isCmd){
         if (stricmp(cmd, "date") == 0)
            s = &date;
         else if (stricmp(cmd, "time") == 0)
            s = &time;
         else if (stricmp(cmd, "caller") == 0)
            s = &caller;
         else if (stricmp(cmd, "callee") == 0)
            s = &callee;
      }
      else{
         s = new string(cmd);
      }

      if (s){
         items.push_back(s);
      }
   }
}

string StringMaker::Make(const string& pCaller, const string& pCallee)
{
   SYSTEMTIME st;
   GetLocalTime(&st);
   char sdate[50];
   sprintf(sdate, "%d%02d%02d", st.wYear, st.wMonth, st.wDay);
   
   char stime[200];
   sprintf(stime, "%02d%02d%02d", st.wHour, st.wMinute, st.wSecond);

   string r;
   _mutex.lock();

   date = sdate;
   time = stime;
   caller = pCaller;
   callee = pCallee;
   for (auto p : items){
      r += *p;
   }

   _mutex.unlock();
   return(r);
}


int main(int argc, char* argv[])
{
   StringMaker* _recFileMaker = new StringMaker("d:\\rec\\[date]\\[callee]\\");
   string file = _recFileMaker->Make("13902123456", "075583841234");
   printf("file=%s\n", file.c_str());  // 输出:dir=d:\rec\20161112\075583841234\
   file = _recFileMaker->Make("26766666", "10086");
   printf("file=%s\n", file.c_str());

   StringMaker* _sessionMaker = new StringMaker("[caller]_[callee]_[date]_[time]");
   file = _sessionMaker->Make("13902123456", "075583841234");
   printf("session=%s\n", file.c_str());
   file = _sessionMaker->Make("26766666", "10086");
   printf("session=%s\n", file.c_str());

   char caller[100];
   char callee[100];
   char date[100];
   char time[100];
   int ret = _sessionMaker->Resolve("13312345678_10010_20161115_090856", caller, callee, date, time);
   printf("Resolve: %d:\n", ret);
   if (ret > 0){
      printf(" caller=%s\n", caller);  // 输出:13312345678
      printf(" callee=%s\n", callee);  // 输出:10010
      printf(" date=%s\n", date);  // 输出:20161115
      printf(" time=%s\n", time);  // 输出:090856
   }
   return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值