打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
关于字符串常用操作的总结

 

 

最近仔细研读了肖舸先生写的《0 Bug C/C++商用工程之道》一书,感触颇深,相信作者具备较深厚的技术背景与个人见解。其中的C/C++无错化程序设计一栏给我留下了深刻印象,总结了一下,如下:

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
安全的字符串拷贝函数
//
参数按顺序排:目的地址,源地址,拷贝的最大字节数
void SafeStrcpy(char *pDest, char *pSource, int nCount)
{
 int nLen = (int)strlen(pSource) + 1;  //
获得源字符串长度,+1保证'\0';
 if (!pDest) goto SafeStrcpy_END_PROCESS; //
保护措施,如果目标地址非法
 if (!pSource) goto SafeStrcpy_END_PROCESS; //
则放弃服务,跳到结束点
 if (nLen > nCount) nLen = nCount;  //
避免读写出界的设计
 memcpy (pDest, pSource, nLen);   //
实施拷贝
 *(pDest+nLen-1) = '\0';    //
手工添加\'0'
SafeStrcpy_END_PROCESS:     //
这是结束点
 return;
}

/****************************
 *
以下为常用函数命名示例
 ***************************/
//
一个弹出式缓冲区的清空函数
void CTonyPopBuffer::Clean(void);
//
弹出式缓冲区的服务函数,以bool量表示内部的各种资源申请是否完成,是否可以服务。
bool CTonyPopBuffer::ICanWork(void);
//
安全的字符串拷贝函数
void SafeStrcpy(char *pDest, char *pSource, int nCount);
//
安全的字符串缓冲区打印函数,需要输入缓冲区指针,限制长度,变参打印机
int SafePrint(char *szBuf, int nMaxLength, char *szFormat, ...);

////////////////////////////////////////////////////////////////////////////////////////////
//
//
安全的字符串拷贝函数二
//
参数按顺序排:目的地址,源地址,目标地址空间大小(必须输入)
void xg_strncpy(char *pD, char *pS, int nDestSize)
{
 int nLen = strlen(pS) + 1;
 if (nLen > nDestSize) nLen = nDestSize; //
目标地址和拷贝地址取小
 memcpy (pD, pS, nLen); //
强行以二进制定长拷贝
 *(pD + nLen - 1) = '\0'; //
强行进行\'0'修饰
}

//安全的字符串构造函数(For WIN32)
//
用以取代有BugCsprintf.
//
参数按顺序排:目的缓冲区,写入的字符串长度,格式化输出字符串(变参)
int xg_printf(char *szBuf, int nDestSize, char *szFormat, ...)
{
 int nListCount = 0; //
计数器
 va_list pArgList;
 va_start(pArgList, szFormat); //
变参处理循环
 nListCount += _vsnprintf(szBuf+nListCount, //
处理每一个变参参数
   nDestSize-nListCount,szFormat,pArgList);
 va_end(pArgList);
 *(szBuf+nDestSize-1) = '\0'; //
人工补充'\0'
 return strlen(szBuf);  //
返回真实的字符串长度
}

#ifdef WIN32
 #define Linux_Win_vsnprintf _vsnprintf
#else // not WIN32
 #define Linux_Win_vsnprintf vsnprintf
#endif

//安全的变参输出函数
//szBuf
:用户指定的输出缓冲区
//nMaxLength
:用户指定的输出缓冲区尺寸
//szFormat
:格式化输出字符串(变参,可以是多个)
//
返回输出的字符总数(strlen的长度,不包括最后的'\0')
int SafePrintf(char *szBuf, int nMaxLength, char *szFormat, ...)
{
 int nListCount = 0;
 va_list pArgList;
 //
此处做安全性防护,防止用户输入非法的缓冲区,导致程序在此崩溃。
 if (!szBuf) goto SafePrintf_END_PROCESS;
 //
此处开启系统循环,解析每条格式化输出字符串
 va_start(pArgList, szFormat);
 nListCount += Linux_Win_vsnprintf(szBuf+nListCount,
   nMaxLength-nListCount, szFormat, pArgList);
 va_end(pArgList);
 //
实现缓冲区超限保护
 if (nListCount > (nMaxLength-1)) nListCount = nMaxLength-1;
 //
人工添加'\0',确保输出100%标准C字符串
 *(szBuf + nListCount) = '\0';
SafePrintf_END_PROCESS:
 return nListCount;
}

//向指定的缓冲区输出一个时间戳字符串
//szBuf
:用户指定输出缓冲区
//nMaxLength
:用户指定的输出缓冲区尺寸
//
返回输出的字符串总数(strlen的长度,不包括最后的'\0')
static int GetATimeStamp(char *szBuf, int nMaxLength)
{
 time_t t;
 struct tm *pTM = NULL;
 int nLength = 0;
 time(&t);
 pTM = localtime(&t);
 nLength = SafePrintf(szBuf, nMaxLength, "%s", asctime(pTM));
 //
这里是个重要的技巧,asctime(pTM)产生的字符串最后会自动带上回车符,
 //
这给后面很多的格式化输出带来不便
 //
此处退格结束字符串,目的是过滤掉这个回车符
 szBuf[nLength-1] = '\0';

 return strlen(szBuf); //返回字符串长度
}

/////////////////////////////////////////////////////////////////////////////////

 

 

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
CStdioFile.ReadString读取中文产生乱码解决方法
【C++】实现UTF_8编码字符串转换成GB2312编码char类型字符串的代码
关于Tcp封包
C语言详解——文件读取
浅析C语言中关于字符串的操作 - C/C++ - 课堂 - 话题 - 张剑 - CSDN学...
【转】Android JNI开发入门篇
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服