工作中第一次用vc做项目,大家帮我看下代码风格,欢迎批评指正

疯魔症 2009-12-25 08:49:03
一个使用gsm modem发短信的模块,自己参看网上的资料做的pdu编码。
几天后看原来的代码,绝对写的太烂了,拿出来希望大家批评指针。
//参考资料
一、短信中心号码处理:用字符串 addr 表示
1、将短信息中心号码去掉+号,看看长度是否为偶数,如果不是,最后添加F
即 addr = "+8613800200500"
=> addr = "8613800200500F"
2、将奇数位和偶数位交换。
=> addr = "683108200005F0"
3、将短信息中心号码前面加上字符91,91是国际化的意思
=> addr = "91683108200005F0"
4、算出 addr 长度,结果除2,格式化成2位的16进制字符串,16 / 2 = 8 => "08"
=> addr = "0891683108200005F0"

二、手机号码处理:用字符串 phone
1、将手机号码去掉+号,看看长度是否为偶数,如果不是,最后添加F
即 phone = "+8613602433649"
=> phone = "8613602433649F"
2、将手机号码奇数位和偶数位交换。
=> phone = "683106423346F9"

三、短信息部分处理:用字符串 msg 表示
1、转字符串转换为Unicode代码,例如“工作愉快!”的unicode代码为 5DE54F5C61095FEBFF01,
(转换函数见最后附录)
2、将 msg 长度除2,保留两位16进制数,即 5DE54F5C61095FEBFF01 = 20 / 2 => "0A",再加上 msg
=> msg = "0A5DE54F5C61095FEBFF01"
四、组合
1、手机号码前加上字符串 11000D91(1100:固定,0D:手机号码的长度,不算+号,十六进制表示,91:发送到手机为91,发送到小灵通为81),
即 phone = "11000D91" + phone
=> 11000D91683106423346F9
2、手机号码后加上 000800 和刚才的短信息内容,000800也写死就可以了
即 phone = phone + "000800" + msg
即 11000D91683106423346F9 + 000800 + 0A5DE54F5C61095FEBFF01
=> phone = 11000D91683106423346F90008000A5DE54F5C61095FEBFF01
3、phone 长度除以2,格式化成2位的十进制数



//我用c++的实现
/* 短信预处理 */
class SplitMessage
{
public:
SplitMessage()
{

}
~SplitMessage()
{

}

SplitMessage(MessageStruct OneMessage)
{
m_Message = OneMessage;
SplitInit();
}

//用新的短信拼接
void SetMessage(MessageStruct OneMessage)
{
m_Message = OneMessage;
SplitInit();
}

public:

void doWork()
{
/* 1 */
SplitAddrStr(m_LpAddr,m_TempArr,m_iA,m_iA,m_Message.Addr);

/* 2 */
SplitPhoneStr(m_LpPhone,m_TempArr,m_iP,m_iP,m_Message.Phone);

/* 3 */
SplitMessageStr(m_LpMsg,m_TempArr,m_iM,m_iM,m_Message.Message);

/* 4 */
SplitAllPduStr(m_LpAddr,m_LpPhone,m_LpMsg,m_iA,m_iP,m_iM);

strcat(m_PduResult, "\x01a"); // 以Ctrl-Z结束

m_iPduLeng = m_iA + m_iP + m_iM+2;
}

//得到pdu串
const char * const getPduStr()
{
return m_PduResult;
}

int getpduLength()
{
return m_iPduLeng;
}


int getIntCMGS()
{
return m_AT_CMGS;
}

private:
const char * getAddr()
{
return m_LpAddr;
}
const char * getPhone()
{
return m_LpPhone;
}
const char * getMsg()
{
return m_LpMsg;
}

private:

//对象初始化
void SplitInit()
{

/* 赋值长度 */
m_iA = m_Message.iAddr;
m_iP = m_Message.iPhone;
m_iM = m_Message.iMessage;

assert(m_iA < MESSAGE_NUMBER_SIZE);
assert(m_iP < MESSAGE_NUMBER_SIZE);
assert(m_iM < MESSAGE_TEXT_SIZE);

/* 拷贝内存 */
memcpy(m_LpAddr,m_Message.Addr,m_Message.iAddr);
memcpy(m_LpPhone,m_Message.Phone,m_Message.iPhone);
memcpy(m_LpMsg,m_Message.Message,m_Message.iMessage);

memset(m_PduResult,'\0',MESSAGE_PDU_SIZE);
memset(m_TempArr,'\0',MESSAGE_PDU_SIZE);
/* 赋结束符 */
*(m_LpAddr + m_iA+1) ='\0';
*(m_LpPhone + m_iP+1)='\0';
*(m_LpMsg + m_iM+1)='\0';
}

private:
/* 第一部分 拼接 短信服务中心号码*/
//LpResultAddr 处理后得到的串
//LpAddr 短信服务中心号码 例8615800255000(需要使用at指令得到)
//iAlen 短信服务中心号码的长度
void SplitAddrStr(char * LpResultAddr,char * LpAddr,int iAlen,int & iUseLen,const char * Addr)
{
assert(NULL != LpAddr && NULL != LpResultAddr);
memcpy(LpAddr,Addr,iAlen+1);
assert(strlen(LpAddr) == 13);

if (strlen(LpAddr)%2 == 1)//1.不够偶数位加'F'
{
*(LpAddr+iAlen) = 'F';
*(LpAddr+iAlen+1) ='\0';
iAlen ++;
}

ReBackChar(LpAddr,iAlen);//2奇偶位调换

strcpy(LpResultAddr,LpAddr);

SwapMemoryArr(LpResultAddr,"91",LpAddr,MESSAGE_NUMBER_SIZE,2,iAlen);//3前面加"91"
iAlen += 2;
memcpy(LpAddr,LpResultAddr,iAlen);

int iResult= iAlen/2;
char tmp[32];
itoa(iResult,tmp,16);
if (strlen(tmp)<2)
{
char tt=tmp[0];
tmp[0]='0';
tmp[1]=tt;
tmp[2]='\0';
}

SwapMemoryArr(LpResultAddr,tmp,LpAddr,MESSAGE_NUMBER_SIZE,strlen(tmp),iAlen);//添加PDU串中的SMSC信息长度
iAlen +=2;
*(LpResultAddr + iAlen +1) ='\0';

iUseLen = iAlen;
}


/* 第二部分 拼接 目标地址号码 */
//LpResultPhone处理后的串
//LpPhone 目标电话号
//iPhoneLen电话号长度
//UseLen 处理后串长度
void SplitPhoneStr(char * LpReslutPhone,char * LpPhone,int iPhoneLen,int & iUseLen,const char * Phone)
{
assert(NULL != LpPhone && NULL != LpReslutPhone);
memcpy(LpPhone,Phone,iPhoneLen+1);
assert(strlen(LpPhone) == 13);

if (strlen(LpPhone)%2 == 1)//1.不够偶数位加'F'
{
*(LpPhone+iPhoneLen) = 'F';
*(LpPhone+iPhoneLen+1) = '\0';
iPhoneLen++;
}

ReBackChar(LpPhone,iPhoneLen);//2奇偶位调换

SwapMemoryArr(LpReslutPhone,"11000D91",LpPhone,MESSAGE_NUMBER_SIZE,8,iPhoneLen);//91为手机,此处写死只能发给手机
iPhoneLen += 8;
*(LpReslutPhone+iPhoneLen) = '\0';

memcpy(LpPhone,LpReslutPhone,iPhoneLen);

SwapMemoryArr(LpReslutPhone,LpPhone,"000800",MESSAGE_NUMBER_SIZE,iPhoneLen,6);
iPhoneLen +=6;
*(LpReslutPhone+iPhoneLen) = '\0';

iUseLen = iPhoneLen;
}

/* 第三部分 拼接 短信内容 */
//LpResultMessage 处理后的短信串
//LpMessage 原短信串
//iMessageLen
//UseLen处理后的长度
void SplitMessageStr(char * LpResultMessage,char * LpMessage,int iMessageLen,int & iUseLen,const char * Message)
{
memcpy(LpMessage,Message,iMessageLen+1);
//转为unicode码
unsigned char buf[256];
int iLength= gsmEncodeUcs2(LpMessage,buf,iMessageLen);

iMessageLen = gsmBytesString(buf,LpResultMessage,iLength);
*(LpResultMessage+iMessageLen+1) = '\0';

char CDivisor[32];
itoa(iMessageLen/2,CDivisor,16);

if (strlen(CDivisor) < 2)
{
char C = CDivisor[0];
CDivisor[0]='0';
CDivisor[1]=C;
CDivisor[2]='\0';

SwapMemoryArr(LpMessage,CDivisor,LpResultMessage,MESSAGE_PDU_SIZE,2,iMessageLen);//前两位短信长度
iMessageLen += 2;
memcpy(LpResultMessage,LpMessage,iMessageLen);

*(LpResultMessage+ iMessageLen +1) ='\0';
}
else
{
char temp[32];
memset(temp,'\0',32);
memcpy(temp,CDivisor,2);

SwapMemoryArr(LpMessage,temp,LpResultMessage,MESSAGE_PDU_SIZE,2,iMessageLen);//前两位短信长度

iMessageLen += 2;

memcpy(LpResultMessage,LpMessage,iMessageLen);

*(LpResultMessage+ iMessageLen +1) ='\0';
}

iUseLen =iMessageLen;

}



/* 第四部分 拼接 整个Pdu串 */
//
//
void SplitAllPduStr(char * LpAddr,char * LpPhone,char * LpMessage,int iA,int iP,int iM)
{
SwapMemoryArr(m_TempArr,LpPhone,LpMessage,MESSAGE_PDU_SIZE,iP,iM);//phone + msg

*(m_TempArr+ iP +iM) ='\0';

int iNo = strlen(m_TempArr)/2;
m_AT_CMGS = iNo;//地址和短信内容的长度

SwapMemoryArr(m_PduResult,LpAddr,m_TempArr,MESSAGE_PDU_SIZE,iA,(iP+iM));//addr + 上面的结果

*(m_PduResult + iA+iP +iM) ='\0';
}




private://辅助函数

//前后拼接两个串成为新串
void SwapMemoryArr(char * LpResult,const char * LpFront,const char * LpTarget,int iRLen,int iFLen,int iTLen)
{
assert(LpResult!=NULL && LpFront !=NULL && LpTarget!=NULL);
assert((iFLen+iTLen) < iRLen);

memcpy(LpResult,LpFront,iFLen);
memcpy((LpResult+iFLen),LpTarget,iTLen);
}

//奇偶交换
void ReBackChar(char * LpR,int iLen)
{
int iIndex=0;
for(int i=1;i<(iLen+1);i++)
{
iIndex = i-1;//数组索引下标
int x =i%2;
if (x == 1)//如果是奇数则交换
{
char lt = *(LpR+iIndex);
*(LpR+iIndex) = *(LpR+iIndex+1);
*(LpR+iIndex+1) = lt;
}
}
}
// UCS2编码
// 输入: pSrc - 源字符串指针
// nSrcLength - 源字符串长度
// 输出: pDst - 目标编码串指针
// 返回: 目标编码串长度
int gsmEncodeUcs2(const char* pSrc, unsigned char* pDst, int nSrcLength)
{
int nDstLength; // UNICODE宽字符数目
WCHAR wchar[128]; // UNICODE串缓冲区

// 字符串-->UNICODE串
nDstLength = MultiByteToWideChar(CP_ACP, 0, pSrc, nSrcLength, wchar, 128);

// 高低字节对调,输出
for(int i=0; i<nDstLength; i++)
{
*pDst++ = wchar[i] >> 8; // 先输出高位字节
*pDst++ = wchar[i] & 0xff; // 后输出低位字节
}

// 返回目标编码串长度
return nDstLength * 2;
}


// 字节数据转换为可打印字符串
// 如:{0xC8, 0x32, 0x9B, 0xFD, 0x0E, 0x01} --> "C8329BFD0E01"
// 输入: pSrc - 源数据指针
// nSrcLength - 源数据长度
// 输出: pDst - 目标字符串指针
// 返回: 目标字符串长度
int gsmBytesString(const unsigned char* pSrc, char* pDst, int nSrcLength)
{
const char tab[]="0123456789ABCDEF"; // 0x0-0xf的字符查找表

for (int i = 0; i < nSrcLength; i++)
{
*pDst++ = tab[*pSrc >> 4]; // 输出高4位
*pDst++ = tab[*pSrc & 0x0f]; // 输出低4位
pSrc++;
}

// 输出字符串加个结束符
*pDst = '\0';

// 返回目标字符串长度
return (nSrcLength * 2);
}

// UCS2解码
// 输入: pSrc - 源编码串指针
// nSrcLength - 源编码串长度
// 输出: pDst - 目标字符串指针
// 返回: 目标字符串长度
int gsmDecodeUcs2(const unsigned char* pSrc, char* pDst, int nSrcLength)
{
int nDstLength; // UNICODE宽字符数目
WCHAR wchar[128]; // UNICODE串缓冲区

// 高低字节对调,拼成UNICODE
for(int i=0; i<nSrcLength/2; i++)
{
wchar[i] = *pSrc++ << 8; // 先高位字节
wchar[i] |= *pSrc++; // 后低位字节
}

// UNICODE串-->字符串
nDstLength = WideCharToMultiByte(CP_ACP, 0, wchar, nSrcLength/2, pDst, 160, NULL, NULL);

// 输出字符串加个结束符
pDst[nDstLength] = '\0';

// 返回目标字符串长度
return nDstLength;
}

private :
MessageStruct m_Message;

char m_PduResult[MESSAGE_PDU_SIZE];//PDU串

int m_iPduLeng;

char m_TempArr[MESSAGE_PDU_SIZE];//中间变量缓冲区
private:
char m_LpAddr[MESSAGE_NUMBER_SIZE]; //缓冲,短信服务中心号码
char m_LpPhone[MESSAGE_NUMBER_SIZE]; //缓冲,目标手机号

char m_LpMsg[MESSAGE_PDU_SIZE];//缓冲,信息内容

int m_AT_CMGS;//AT指令参数

int m_iA;//短信中心号码长度
int m_iP;//手机号长度
int m_iM;//信息长度
};




#define MESSAGE_PDU_SIZE 800 //编码后pdu串的最大长度
#define MESSAGE_NUMBER_SIZE 32 //号码的最大长度
#define MESSAGE_TEXT_SIZE 100 //短信最大长度

/* 短信基本内容 */
typedef struct {
char Addr[32]; //服务中心号码,服务中心号码是短消息的必有属性,系统通过at指令获得并赋值
//编辑短信时看不到,新的手机卡一般买到手都是设置好的,
char Phone[32];//对方号码
char Message[200];//短信内容
int iAddr;//串长
int iPhone;//串长
int iMessage;//串长
} MessageStruct;
...全文
267 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
疯魔症 2009-12-25
  • 打赏
  • 举报
回复
一年.net B/S工作经验,换工作现在做工控
[Quote=引用 17 楼 bsr2009 的回复:]
LZ原来是搞JAVA的?LZ在索爱机器上能发送成功吗?
[/Quote]
bsr2009 2009-12-25
  • 打赏
  • 举报
回复
LZ原来是搞JAVA的?LZ在索爱机器上能发送成功吗?
whs1980 2009-12-25
  • 打赏
  • 举报
回复
贵在坚持!
疯魔症 2009-12-25
  • 打赏
  • 举报
回复
没用new操作符,这个类存在内存泄露没,因为前几天调试时,出过内存报错的问题,不知道是不是这里的原因。

//开了一个线程处理发短信的,合理么,运行一段时间后系统非常慢
//短信工作线程
void SmsWorkThread(void * t)
{
//串口操作类,全局
wchar_t * strCom = L"COM1";
BOOL bIsOpen = UseComm.OpenComm(strCom,9600,NOPARITY,8,ONESTOPBIT);
if (!bIsOpen)
{
printf("串口打开失败!短信报警启动失败!\n");
return;
}

while (true)
{
//PushMessage();//加一条短信


if (m_MessageDeque.size()!=0)//队列中是否还有短信
{
MessageStruct MyMessage = m_MessageDeque.front();
m_MessageDeque.pop_front();

SplitMessage * MessWork = new SplitMessage(MyMessage);

//MessWork->SetMessage();
MessWork->doWork();

char cmd[16];
char ans[50];
memset(ans,'\0',50);

UseComm.WriteComm("at\r",3);

int nnLength =UseComm.ReadComm(ans,128);

// 命令中的长度,不包括SMSC信息长度,以数据字节计
sprintf(cmd, "AT+CMGS=%d\r", MessWork->getIntCMGS()); // 生成命令

UseComm.WriteComm("AT+CMGF=0\r",strlen("AT+CMGF=0\r"));

int nLength =UseComm.ReadComm(ans,128);

UseComm.WriteComm(cmd, strlen(cmd)); // 先输出命令串

nLength =UseComm.ReadComm(ans,50);

// 根据能否找到"\r\n> "决定成功与否

if(strstr(ans, "> ") != NULL && strstr(ans,"ERROR") == NULL)
{
char SendContent[200];
memcpy(SendContent,MessWork->getPduStr(),MessWork->getpduLength());

UseComm.WriteComm(SendContent,strlen(SendContent));

Sleep(3000);

nLength = UseComm.ReadComm(ans,128);

if (strstr(ans,"OK") != NULL && strstr(ans,"ERROR") ==NULL)
{
printf("发送成功一条短信!\n");
}

UseComm.WriteComm("ATE\r",4);
nLength = UseComm.ReadComm(ans,50);

UseComm.WriteComm("\x01a\r",2);
nLength = UseComm.ReadComm(ans,50);


UseComm.WriteComm("AT\r",3);
nLength = UseComm.ReadComm(ans,50);
}
else
{
UseComm.WriteComm("\x01a",2);
UseComm.WriteComm("AT\r",3);
UseComm.WriteComm("ATE\r",4);
nLength = UseComm.ReadComm(ans,50);

}

}


}

BOOL bIsClose = UseComm.CloseComm();
if (!bIsClose)
{
printf("串口关闭失败\n");
}

return ;
}

疯魔症 2009-12-25
  • 打赏
  • 举报
回复
恩 好的 谢谢
[Quote=引用 13 楼 rebecca_zjy 的回复:]
可以参考《高质量C/C++编程》(貌似是这个名字),上面编码风格和一些易出的问题说得很详细
[/Quote]
rebecca_zjy 2009-12-25
  • 打赏
  • 举报
回复
可以参考《高质量C/C++编程》(貌似是这个名字),上面编码风格和一些易出的问题说得很详细
疯魔症 2009-12-25
  • 打赏
  • 举报
回复
我是这样想的,pdu编码是比较小的辅助性,没分开单独写,除了发短信的方法调用外,别的地方不会使用,这样合理没
[Quote=引用 8 楼 lpr_pro 的回复:]
类中函数声明和实现分开,分别放入.h和.cpp文件中.
[/Quote]
疯魔症 2009-12-25
  • 打赏
  • 举报
回复
用new的时候要很小心的,不能在函数里随便一个地方就new,不知道别人怎么处理的
[Quote=引用 9 楼 bragi523 的回复:]
引用 5 楼 zwb0540822 的回复:
内存空间都用数组给分配好了,不知道vc中怎么做内存管理,比较好的处理方式吧。

可以每次用的时候new出来
[/Quote]
疯魔症 2009-12-25
  • 打赏
  • 举报
回复
最好的提高方式还是多写代码,和看别人的代码,看别人的代码很重要,很多时候都是突然发现,原来可以这样,还有这样的函数。
bragi523 2009-12-25
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 zwb0540822 的回复:]
内存空间都用数组给分配好了,不知道vc中怎么做内存管理,比较好的处理方式吧。

[/Quote]可以每次用的时候new出来
LPR_Pro 2009-12-25
  • 打赏
  • 举报
回复
类中函数声明和实现分开,分别放入.h和.cpp文件中.
enter333 2009-12-25
  • 打赏
  • 举报
回复
帮顶了。
bragi523 2009-12-25
  • 打赏
  • 举报
回复
还不错
我习惯把函数都实现在CPP里面
疯魔症 2009-12-25
  • 打赏
  • 举报
回复
内存空间都用数组给分配好了,不知道vc中怎么做内存管理,比较好的处理方式吧。
sandyandy 2009-12-25
  • 打赏
  • 举报
回复
风格不错
ljz888666555 2009-12-25
  • 打赏
  • 举报
回复
再试一次。
疯魔症 2009-12-25
  • 打赏
  • 举报
回复
我把短消息分成三个内容,服务中心号码,对方号码,消息内容,以此定义了一个结构体
不完善的地方,代码上没使用动态分配内存,自己掌握不好。
大量使用memcpy 内存操作太频繁了,也不太合理。
定义的变量太多,有些可以不用。

最后编码出来的串可以正常发出去,处理没问题。
Wenxy1 2009-12-25
  • 打赏
  • 举报
回复
总的来说还可以。
建议还可以改进:

// 服务中心号码 /* 加个空格式 */
unsigned char *pSrc; int *pN /* 这样更好 */
// VC编程网络就参考微软的MSDN就OK

18,356

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 网络编程
c++c语言开发语言 技术论坛(原bbs)
社区管理员
  • 网络编程
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧