钢筋混凝土的UNIXC编程技巧(doc 29页).doc

上传人(卖家):欢乐马 文档编号:280458 上传时间:2020-02-23 格式:DOC 页数:29 大小:61.50KB
下载 相关 举报
钢筋混凝土的UNIXC编程技巧(doc 29页).doc_第1页
第1页 / 共29页
钢筋混凝土的UNIXC编程技巧(doc 29页).doc_第2页
第2页 / 共29页
钢筋混凝土的UNIXC编程技巧(doc 29页).doc_第3页
第3页 / 共29页
钢筋混凝土的UNIXC编程技巧(doc 29页).doc_第4页
第4页 / 共29页
钢筋混凝土的UNIXC编程技巧(doc 29页).doc_第5页
第5页 / 共29页
点击查看更多>>
资源描述

1、 钢筋混凝土的钢筋混凝土的 UNIX C 编程技巧(一、内存映射表)编程技巧(一、内存映射表) 前言: 大学毕业后从事 unix 上的银行综合业务系统开发工作已有一年半的时间,向众多前辈高手 学习了很多经验和技巧,自己也创新了些好的开发技术,特写出来与奋斗在一线的 unix 程 序员们共享。本人大学时专注于 windows 平台应用开发,工作后才转入 unix 平台,故沿 袭了不少 windows 编码风格。 - 正文: 在一个带有数据库的 unix 系统中进行 E-SQL 嵌入式开发, 必然用到很多混合式编程方式。 当系统对表的 SELECT 操作频繁时,会使数据库效率大幅下降。于是我们很当

2、然的这样设 计: 当应用开始运行时把数据库中需要频繁查询的表装载入共享内存, 通过编写一批共享内 存查询函数实现对表数据的快速查询、定位。这里借用 windows 的一些名词把这一技术命 名为“内存映射表”技术。 内存映射表的格式设计有很多方式, 下面介绍一下我设计的一种格式, 该格式已经应用于某 省级银行信用卡全省大前置系统,取得非常好的效果。 | | | | | | 内存映射表记录条数 | 第一条记录结构单元 | 第二条记录结构单元 | . | | 10 个字节 | 记录结构的大小 | 记录结构的大小 | | | | | | | 共享内存数据存放格式如上图所示。开头的 10 个字节存放内存

3、映射表的记录条数数值,由 于标准 c 的有符号长整数类型最大值约为 21 亿, 所以预留 10 个字节存放 ASCII 编码的记 录条数数值已绰绰有余且取得最大限度值了。 第 11 个字节开始存放数据库表第一条记录对 应的 c 语言结构体,称为一个结构单元。后面依次存放所有数据库表记录形成结构体数组。 一张数据库表装载入一块共享内存,可以通过表名给共享内存的 ipckey 取名。比如“公共 系统参数表”对应的内存映射表的 ipckey 在头文件里这样添加“#define SHMY_KEY_GGXTCS 0x00001138 /* 4408 */“,以便于在程序里引用。 内存映射表共占用共享内存

4、大小为该表记录对应的数据结构体大小乘以记录条数加上10个 字节。比如“公共系统参数表”记录条数为 10 条,表定义如下。那么总占用共享内存大小 =(20+30+40)*10+10=910 个字节。 字段名 字段属性 长度 空值标志 备注 包括中文注释和取值范围 csxh char 20 N.N 参数序号 csz char 30 N.N 参数值 cssm char 40 参数说明 索引 1 unique csxh 内存映射表的操作大致有装载和查询两种操作, 其它还可以有简单的更新操作。 考虑到每个 内存映射表的操作大致一样以及以某个关键字段查询、更新操作的相似性,再以“公共系统 参数表”我这样设

5、计内存映射表的操作函数原形: int LoadMapGGXTCS(); int FetchMapGGXTCS ( void *pvCondValue , struct REPLACE_STRUCT_TYPE *pREPLACE_STRUCT_ARG , int (* REPLACE_FUNCNAME_COMPARE_PROC) ( void *pvCondValue , struct REPLACE_STRUCT_TYPE *pREPLACE_STRUCT_ARG ) ); int UpdateMapGGXTCS ( void *pvCondValue , void *pvUpdateValu

6、e , int (* REPLACE_FUNCNAME_UPDATE_PROC) ( void *pvCondValue , void *pvUpdateValue , struct REPLACE_STRUCT_TYPE *pREPLACE_STRUCT_ARG ) ); 两个函数内所有涉及到具体表名、结构体名、回调函数名我都已宏的方式替换掉,这样做的 好处是可以形成代码模板, 如果以后要添加一张表的映射只要复制代码模板到实现文件的最 后面, 把代码模板最前面的宏定义成具体的值。 代码模板最后面把所有用过的宏都反定义掉, 不妨碍后面的程序使用。 装载表函数我不用多说了,即把表数据装载入共享内

7、存,不需要参数。 查询函数第一个参数为关键字段值,与 REPLACE_FUNCNAME_COMPARE_PROC 回调 函数配合使用。参数类型为 void*类型,这样就可以兼容所有类型的数据甚至是结构体、共 用体, 额外麻烦的只是把变量传入前强制传换成 void*, 在回调函数里再转换回具体的变量 类型。第二个参数是结构体宏,用于函数成功返回时把符合要求的记录结构体返回。第三个 参数是指向回调函数的指针, 其作用是针对某一关键字段, 分别取出共享内存里的每条记录 进行比较,当条件符合时,回调函数返回 0,否则返回 1,这样可以不改变外层遍历函数的 条件下,使用不同判断方式、不同的判断值对内存映

8、射表中所有记录进行遍历。 本文最后附件中附有装载、 查询和更新三个内存映射表的代码模板, 由于完全采用参数化宏 替换方式设计,甚至可以不加修改的立即应用到您的系统中去。 下面跳跃的介绍一下查询函数极其回调函数的操作原理。 更新函数原理与之相似, 结构稍稍 复杂一些,重点是回调函数。 查询函数 . 遍历内存映射表中所有结构记录 调用遍历函数最后一个参数即回调函数指针(条件值,当前结构记录); 如果回调函数返回 0,即条件符合且更新成功 复制内存映射表中当前结构记录内容到 pREPLACE_STRUCT_ARG 指针空间里,输出给 用户 跳出遍历; 偏移到内存映射表中下一条结构记录; . 返回回调

9、函数的返回值 查询回调函数(条件值,内存映射表中当前结构记录) 把便利函数传入的条件值强制转换成 char*类型; 与内存映射表中当前结构记录的 csxh 进行比较,如果相等即找到 返回 0; 否则 返回 1; 查询函数的使用示例 . /* 获取 对帐场次 */ iRt = FetchMapGGXTCS( (void *)“dzcc“ , if( iRt != 0 ) printf( “获取对帐场次 失败“ ); else printf( “当前对帐场次为%s“ , stGgxtcs.csz ); . 使用该设计通过创建与数据库表映射的共享内存数据提高对数据库静态表 (运行时数据内容 不改变或

10、者只做少量更新的表)的查询访问速度,而不需要额外占用数据库宝贵的效率,尤 其在一个对数据库操作频繁的系统中能很大程度的提高整个系统的运行效率。 本设计也有不 足之处,主要是只能代替数据库简单的 SELECT 操作和 UPDATE 操作,不支持 INSERT、 DELETE 操作,不过对于一些静态表的查询使用已经足够了,不是吗 _ - 附件一、内存映射表 代码模块(以“公共系统参数表”为例) /* * 获取 公共系统参数表 内存映射表 相应记录 * */ #define REPLACE_STRUCT_TYPE ggxtcs #define REPLACE_STRUCT_ARG stGgxtcs

11、#define REPLACE_SHEKEY SHMY_KEY_GGXTCS #define REPLACE_TABLENAME ggxtcs #define REPLACE_TABLEDESC “公共系统参数表“ #define REPLACE_CURSORNAME curGGXTCS #define REPLACE_DBVAR R_GGXTCS #define REPLACE_DBVARFUNC pubVtoSGgxtcs #define REPLACE_FUNCNAME_FETCH “FetchMapGGXTCS“ #define REPLACE_FUNCNAME_LOAD “LoadM

12、apGGXTCS“ #define REPLACE_FUNCNAME_COMPARE_PROC CompareKeyFromGGXTCSProc #define REPLACE_FUNCNAME_UPDATE_PROC UpdateValueFromGGXTCSProc int FetchMapGGXTCS ( void *pvCondValue , struct REPLACE_STRUCT_TYPE *pREPLACE_STRUCT_ARG , int (* REPLACE_FUNCNAME_COMPARE_PROC) ( void *pvCondValue , struct REPLAC

13、E_STRUCT_TYPE *pREPLACE_STRUCT_ARG ) ); int iReturnValue; struct REPLACE_STRUCT_TYPE *pmpREPLACE_STRUCT_ARG; char *pmp; char acRecordAmount11; long lRecordAmount; long l; _IPC_ID_T ipcid; /* 判断 内存映射表 是否存在 */ iReturnValue = IPCIsShareMemoryExist( REPLACE_SHEKEY ); if( iReturnValue = IPC_SHAREMEMORY_R

14、ETURN_ISNT_EXIST ) /* 若不存在 则创建之 */ iReturnValue = LoadMapGGXTCS(); if( iReturnValue != 0 ) WriteLog( gacLogFilename, “%s | “REPLACE_FUNCNAME_FETCH“ | “LOG_LINELEN“ | 创建 内存映射表 “REPLACE_TABLEDESC“ 失败 错误码%d errno%d,请重启应用n“, GetLocalTimeString( gacTimeStringBuffer , 256 , “%Y-%m-%d %H:%M:%S“ ), _LINE_,

15、iReturnValue, errno ); return -1; /* 打开 内存映射表 */ ipcid = IPCOpenShareMemory( REPLACE_SHEKEY ); if( ipcid 0 ) /* 打开失败,写出错日志,函数返回 */ WriteLog( gacLogFilename, “%s | “REPLACE_FUNCNAME_FETCH“ | “LOG_LINELEN“ | 打开 内存映射表 “REPLACE_TABLEDESC“ 失败 errno%d,请重启应用n“, GetLocalTimeString( gacTimeStringBuffer , 256

16、 , “%Y-%m-%d %H:%M:%S“ ), _LINE_, errno ); return -2; /* 连接 内存映射表 地址 */ pmp = IPCAttachShareMemory( ipcid ); if( pmp = NULL ) /* 连接失败,写出错日志,函数返回 */ WriteLog( gacLogFilename, “%s | “REPLACE_FUNCNAME_FETCH“ | “LOG_LINELEN“ | 连接 内存映射表 “REPLACE_TABLEDESC“ 失败 errno%d,请重启应用n“, GetLocalTimeString( gacTimeS

17、tringBuffer , 256 , “%Y-%m-%d %H:%M:%S“ ), _LINE_, errno ); return -3; memset( acRecordAmount , 0x00 , sizeof( acRecordAmount ) ); strncpy( acRecordAmount , pmp , 10 ); lRecordAmount = atol( acRecordAmount ); pmpREPLACE_STRUCT_ARG = (struct REPLACE_STRUCT_TYPE *)( pmp + 10 ) ; /* 搜寻 内存映射表 */ for( l=

18、0 ; llRecordAmount ; l+ ) /* 调用搜寻回调函数 */ iReturnValue = REPLACE_FUNCNAME_COMPARE_PROC( pvCondValue , pmpREPLACE_STRUCT_ARG ) ; if( iReturnValue != 1 ) memset( pREPLACE_STRUCT_ARG , 0x00 , sizeof( struct REPLACE_STRUCT_TYPE ) ); memcpy( pREPLACE_STRUCT_ARG , pmpREPLACE_STRUCT_ARG , sizeof(struct REPL

19、ACE_STRUCT_TYPE) ); break; pmpREPLACE_STRUCT_ARG + ; /* 断开 内存映射表 地址连接 */ IPCDetachShareMemory( pmp ); return iReturnValue; /* * 更新 公共系统参数表 内存映射表 * */ int UpdateMapGGXTCS ( void *pvCondValue , void *pvUpdateValue , int (* REPLACE_FUNCNAME_UPDATE_PROC) ( void *pvCondValue , void *pvUpdateValue , struc

20、t REPLACE_STRUCT_TYPE *pREPLACE_STRUCT_ARG ) ); int iReturnValue; struct REPLACE_STRUCT_TYPE *pmpREPLACE_STRUCT_ARG; char *pmp; char acRecordAmount11; long lRecordAmount; long l; _IPC_ID_T ipcid; /* 判断 内存映射表 是否存在 */ iReturnValue = IPCIsShareMemoryExist( REPLACE_SHEKEY ); if( iReturnValue = IPC_SHARE

21、MEMORY_RETURN_ISNT_EXIST ) /* 若不存在 则创建之 */ iReturnValue = LoadMapGGXTCS(); if( iReturnValue != 0 ) WriteLog( gacLogFilename, “%s | “REPLACE_FUNCNAME_FETCH“ | “LOG_LINELEN“ | 创建 内存映射表 “REPLACE_TABLEDESC“ 失败 错误码%d errno%d,请重启应用n“, GetLocalTimeString( gacTimeStringBuffer , 256 , “%Y-%m-%d %H:%M:%S“ ),

22、_LINE_, iReturnValue, errno ); return -1; /* 打开 内存映射表 */ ipcid = IPCOpenShareMemory( REPLACE_SHEKEY ); if( ipcid 0 ) /* 打开失败,写出错日志,函数返回 */ WriteLog( gacLogFilename, “%s | “REPLACE_FUNCNAME_FETCH“ | “LOG_LINELEN“ | 打开 内存映射表 “REPLACE_TABLEDESC“ 失败 errno%d,请重启应用n“, GetLocalTimeString( gacTimeStringBuff

23、er , 256 , “%Y-%m-%d %H:%M:%S“ ), _LINE_, errno ); return -2; /* 连接 内存映射表 地址 */ pmp = IPCAttachShareMemory( ipcid ); if( pmp = NULL ) /* 连接失败,写出错日志,函数返回 */ WriteLog( gacLogFilename, “%s | “REPLACE_FUNCNAME_FETCH“ | “LOG_LINELEN“ | 连接 内存映射表 “REPLACE_TABLEDESC“ 失败 errno%d,请重启应用n“, GetLocalTimeString(

24、gacTimeStringBuffer , 256 , “%Y-%m-%d %H:%M:%S“ ), _LINE_, errno ); return -3; memset( acRecordAmount , 0x00 , sizeof( acRecordAmount ) ); strncpy( acRecordAmount , pmp , 10 ); lRecordAmount = atol( acRecordAmount ); pmpREPLACE_STRUCT_ARG = (struct REPLACE_STRUCT_TYPE *)( pmp + 10 ) ; /* 搜寻 内存映射表 */

25、 for( l=0 ; llRecordAmount ; l+ ) /* 调用搜寻回调函数 */ iReturnValue = REPLACE_FUNCNAME_UPDATE_PROC( pvCondValue , pvUpdateValue , pmpREPLACE_STRUCT_ARG ) ; if( iReturnValue != 1 ) break; pmpREPLACE_STRUCT_ARG + ; /* 断开 内存映射表 地址连接 */ IPCDetachShareMemory( pmp ); return iReturnValue; /* * 装载 公共系统参数表 内存映射表 *

26、 */ int LoadMapGGXTCS() int iReturnValue; struct REPLACE_STRUCT_TYPE REPLACE_STRUCT_ARG; struct REPLACE_STRUCT_TYPE *pmpREPLACE_STRUCT_ARG; char *pmp; _IPC_ID_T ipcid; long lMapSize; memset( /* 获取表记录总条数 */ EXEC SQL SELECT count(*) INTO :dlRecordAmount FROM REPLACE_TABLENAME ; if( sqlca.sqlcode ) Wri

27、teLog( gacLogFilename, “%s | “REPLACE_FUNCNAME_LOAD“ | “LOG_LINELEN“ | 获取 “REPLACE_TABLEDESC“ 总记录数 失败 sqlcode%dn“, GetLocalTimeString( gacTimeStringBuffer , 256 , “%Y-%m-%d %H:%M:%S“ ), _LINE_, sqlca.sqlcode ); return -1; /* 计算内存映射表大小 */ /* 前十个字节为储存头,存放储存单元的个数 */ lMapSize = dlRecordAmount * sizeof(

28、struct REPLACE_STRUCT_TYPE ) + 10 ; /* 创建 内存映射表 */ ipcid = IPCCreateShareMemory( REPLACE_SHEKEY , lMapSize ); if( ipcid 0 ) if( errno = EEXIST ) return 0; WriteLog( gacLogFilename, “%s | “REPLACE_FUNCNAME_LOAD“ | “LOG_LINELEN“ | 创建 内存映射表 “REPLACE_TABLEDESC“ 失败 errno%d,请重启应用n“, GetLocalTimeString( ga

29、cTimeStringBuffer , 256 , “%Y-%m-%d %H:%M:%S“ ), _LINE_, errno ); return -2; /* 定义游标 */ EXEC SQL DECLARE REPLACE_CURSORNAME CURSOR FOR SELECT * FROM REPLACE_TABLENAME ; /* 打开游标 */ EXEC SQL OPEN REPLACE_CURSORNAME ; /* 打开游标 失败 */ if( sqlca.sqlcode ) WriteLog( gacLogFilename, “%s | “REPLACE_FUNCNAME_L

30、OAD“ | “LOG_LINELEN“ | 打开 游标 “REPLACE_TABLEDESC“ 失败 sqlcode%dn“, GetLocalTimeString( gacTimeStringBuffer , 256 , “%Y-%m-%d %H:%M:%S“ ), _LINE_, sqlca.sqlcode ); return -3; /* 连接 内存映射表 地址 */ pmp = IPCAttachShareMemory( ipcid ); if( pmp = NULL ) /* 连接失败,写出错日志,函数返回 */ WriteLog( gacLogFilename, “%s | “R

31、EPLACE_FUNCNAME_LOAD“ | “LOG_LINELEN“ | 连接 内存映射表 “REPLACE_TABLEDESC“ 失败 errno%d,请重启应用n“, GetLocalTimeString( gacTimeStringBuffer , 256 , “%Y-%m-%d %H:%M:%S“ ), _LINE_, errno ); return -4; sprintf( pmp , “%-010d“ , dlRecordAmount ); pmpREPLACE_STRUCT_ARG = (struct REPLACE_STRUCT_TYPE *)( pmp + 10 ) ;

32、 while(1) /* 获取游标 */ EXEC SQL FETCH REPLACE_CURSORNAME INTO REPLACE_DBVAR; /* 如果记录已取完,跳出循环 */ if( sqlca.sqlcode = 100 ) break; /* 获取游标 失败 */ if( sqlca.sqlcode != 0 ) WriteLog( gacLogFilename, “%s | “REPLACE_FUNCNAME_LOAD“ | “LOG_LINELEN“ | 获取游标 “REPLACE_TABLEDESC“ 失败 sqlcode%d,请重启应用n“, GetLocalTimeS

33、tring( gacTimeStringBuffer , 256 , “%Y-%m-%d %H:%M:%S“ ), _LINE_, sqlca.sqlcode ); /* 断开 内存映射表 地址连接 */ IPCDetachShareMemory( pmp ); /* 关闭游标 */ EXEC SQL CLOSE REPLACE_CURSORNAME; return -5; REPLACE_DBVARFUNC( memcpy( pmpREPLACE_STRUCT_ARG , pmpREPLACE_STRUCT_ARG + ; /* 断开 内存映射表 地址连接 */ IPCDetachShare

34、Memory( pmp ); /* 关闭游标 */ EXEC SQL CLOSE REPLACE_CURSORNAME; WriteLog( gacLogFilename, “%s | “REPLACE_FUNCNAME_LOAD“ | “LOG_LINELEN“ | %ld 条记录进入 内存映 射表 “REPLACE_TABLEDESC“ n“, GetLocalTimeString( gacTimeStringBuffer , 256 , “%Y-%m-%d %H:%M:%S“ ), _LINE_, dlRecordAmount ); return 0; #undef REPLACE_ST

35、RUCT_TYPE #undef REPLACE_STRUCT_ARG #undef REPLACE_SHEKEY #undef REPLACE_TABLENAME #undef REPLACE_TABLEDESC #undef REPLACE_CURSORNAME #undef REPLACE_DBVAR #undef REPLACE_DBVARFUNC #undef REPLACE_FUNCNAME_FETCH #undef REPLACE_FUNCNAME_LOAD #undef REPLACE_FUNCNAME_COMPARE_PROC #undef REPLACE_FUNCNAME_

36、UPDATE_PROC 附件二、下面这些函数被上面的程序调用过,代码存放在本人设计的 iIPC、iLibX 基础函数 库中。 /* * 函数名 : IPCIsShareMemoryExist * 函数描述 : 判断共享存储块存在 * 输入参数说明 : _IPC_ID_T ipckey 共享存储块的 id * 返回值 : 存在 返回 IPC_SHAREMEMORY_RETURN_EXIST * 不存在 返回 IPC_SHAREMEMORY_RETURN_ISNT_EXIST */ int IPCIsShareMemoryExist( _IPC_KEY_T ipckey ) _IPC_ID_T i

37、pcid; ipcid=shmget( ipckey , 1 , IPC_CREAT | IPC_EXCL | _giIPCPermission ); if( ipcid = -1 ) return IPC_SHAREMEMORY_RETURN_EXIST; IPCDestroyShareMemory( ipcid ); return IPC_SHAREMEMORY_RETURN_ISNT_EXIST; /* * 函数名 : IPCOpenShareMemory * 函数描述 : 打开共享存储块 * 输入参数说明 : _IPC_KEY_T ipckey 共享存储块的 key * 返回值 : 成

38、功,返回 共享存储块的 id * 失败,返回 错误代码 */ _IPC_ID_T IPCOpenShareMemory( _IPC_KEY_T ipckey ) int iReturnValue; _IPC_ID_T ipcid; iReturnValue = IPCIsShareMemoryExist( ipckey ) ; if( iReturnValue = IPC_SHAREMEMORY_RETURN_ISNT_EXIST ) return IPC_SHAREMEMORY_RETURN_ISNT_EXIST; ipcid = shmget( ipckey , 0 , IPC_CREAT

39、 | _giIPCPermission ); if( ipcid = -1 ) return IPC_SHAREMEMORY_ERROR_CANT_OPEN; return ipcid; /* * 函数名 : IPCAttachShareMemory * 函数描述 : 连接共享存储块首地址 * 输入参数说明 : _IPC_ID_T ipcid 共享存储块的 id * 返回值 : 存在 返回 首地址 * 不存在 返回 NULL */ void *IPCAttachShareMemory( _IPC_ID_T ipcid ) void *pvAttach; pvAttach = shmat( ip

40、cid , NULL , 0 ); if( pvAttach = (void *)-1 ) return NULL; else return pvAttach; /* * 函数名 : IPCDetachShareMemory * 函数描述 : 断开共享存储块首地址 * 输入参数说明 : void *pvDetach 共享存储块连接首地址 * 返回值 : 存在 返回 IPC_SHAREMEMORY_RETURN_SUCCESS * 不存在 返回 IPC_SHAREMEMORY_ERROR_CANT_DETACH */ int IPCDetachShareMemory( void *pvDetac

41、h ) int i; i = shmdt( pvDetach ); if( i = -1 ) return IPC_SHAREMEMORY_ERROR_CANT_DETACH; else return IPC_SHAREMEMORY_RETURN_SUCCESS; /* * 函数名 : WriteLog * 函数描述 : 正常写日志函数 * 输入参数说明 : char *pcLogFileName 日志文件名 * char *pcFormatString 日志格式串 * . 日志参数列表 * 返回值 : 成功,返回 TRUE * 失败,返回 FALSE * 更新日志 : 2003/10/18

42、创建 */ BOOL WriteLog( char *pcLogFileName, char *pcFormatString, . ) va_list valist; BOOL ret; va_start( valist, pcFormatString ); ret=DoLog(pcLogFileName, LOG_WRITE_APPEND, LOG_MODE_RETURN, pcFormatString, valist ); va_end( valist ); return ret; /* * 函数名 : DoLog * 函数描述 : 日志记录原始函数 * 输入参数说明 : char *pc

43、LogFileName 日志文件名 * int iWriteFlag 日志写标志 * int iModeFlag 日志写完后操作标志 * char *pcFormatString 日志格式串 * va_list valist 日志参数列表 * 返回值 : 成功,返回 TRUE * 失败,返回 FALSE * 更新日志 : 2003/10/18 创建 */ BOOL DoLog( char *pcLogFileName, int iWriteFlag, int iModeFlag, char *pcFormatString, va_list valist ) FILE *fpLogFile=NU

44、LL; if( iWriteFlag = LOG_WRITE_NEW ) fpLogFile=fopen(pcLogFileName,“w“); else if( iWriteFlag = LOG_WRITE_APPEND ) fpLogFile=fopen(pcLogFileName,“a“); if( fpLogFile = NULL ) return FALSE; if( vfprintf( fpLogFile, pcFormatString, valist ) 0 ) return FALSE; fflush(fpLogFile); fclose(fpLogFile); if( iMo

45、deFlag = LOG_MODE_RETURN ) return TRUE; else if( iModeFlag = LOG_MODE_EXIT ) exit(0); return TRUE; /* * 函数名 : GetLocalTimeString * 函数描述 : 格式化时间字符串(本地时间) * 输入参数说明 : size_t bufsize 用于存放格式化后字符串的缓冲区大小 * const char *format 格式化串 * 输出参数说明 char *buf 用于存放格式化后字符串的缓冲区首地址(建议预分配 256 字节) * 返回值 : 成功,返回 TRUE * 失败,返回 FALSE * 更新日志 : 2003/10/18 创建 * 2004/3/3 修改 格式化后字符串的缓冲区首地址 原型 */ char *GetLocalTimeString(char *buf,size_t bufsize,const char *format) struct tm *time_tm; time_tm=GetLocalTimeStruct(); if( strftime(buf,bufsize,format,time_tm) != 0 ) retu

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 办公、行业 > 建筑工程类
版权提示 | 免责声明

1,本文(钢筋混凝土的UNIXC编程技巧(doc 29页).doc)为本站会员(欢乐马)主动上传,163文库仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。
2,用户下载本文档,所消耗的文币(积分)将全额增加到上传者的账号。
3, 若此文所含内容侵犯了您的版权或隐私,请立即通知163文库(发送邮件至3464097650@qq.com或直接QQ联系客服),我们立即给予删除!


侵权处理QQ:3464097650--上传资料QQ:3464097650

【声明】本站为“文档C2C交易模式”,即用户上传的文档直接卖给(下载)用户,本站只是网络空间服务平台,本站所有原创文档下载所得归上传人所有,如您发现上传作品侵犯了您的版权,请立刻联系我们并提供证据,我们将在3个工作日内予以改正。


163文库-Www.163Wenku.Com |网站地图|