1. 字符串报文分类: 固定长度字符串报文, 固定分隔符字符串报文。
2. 字符串报文组包
3. 字符串报文解析
字符串报文结构体:
typedef struct STRRESVARstu
{
int nAmount; //数据域总数
int nFlag; //报文类型 0定长域 1分割域
int *filedlen; //每个数据域的长度
int nCompartlen; //分割符号的长度
char szCompart[10]; //分隔符符串
char **filedaddr; //指向每个数据域首地址的指针
} STRRESVAR;
4. 示例一
#include <iostream>
#include <string.h>
#include <assert.h>
#include <stdlib.h>
using namespace std;
#define STRSTR 0
#define STRINT 1
#define STRDOUBLE 2
typedef struct STRRESVARstu //字符串报文结构体
{
int nAmount;
int nFlag;
int *filedlen;
int nCompartlen;
char szCompart[10];
char **filedaddr;
} STRRESVAR;
typedef STRRESVAR * PSTRRESVAR;
int strrespre(char *buf, PSTRRESVAR pStrstu) //解析报文,报文先存储在buf中, pStrstu 为报文结构指针
{
int i = 0, j = 0;
char *p1, *p2;
assert(buf != NULL && pStrstu != NULL && pStrstu->filedlen != NULL);
assert(pStrstu->filedaddr != NULL);
if (pStrstu->nFlag == 0)
{
for (i=0; i<pStrstu->nAmount; i++)
{
pStrstu->filedaddr[i] = buf + j;
j = j + pStrstu->filedlen[i] + pStrstu->nCompartlen;
}
}
else
{
p1 = buf;
p2 = p1;
while (p1 != NULL && i<= pStrstu->nAmount)
{
pStrstu->filedaddr[i] = p1;
p2 = strstr(p1, pStrstu->szCompart);
if (p2 == NULL)
{
pStrstu->filedlen[i] = strlen(p1);
p1 = NULL;
}
else
{
pStrstu->filedlen[i] = p2 - p1;
p1 = p2 + pStrstu->nCompartlen;
}
i++;
}
}
return 0;
}
char * TrimString(char* szDest) //去字符串 首尾 空白
{
int n, nLen;
if (szDest != NULL)
{
for (n = strlen(szDest); n > 0; n--)
{
if (!isblank(szDest[n - 1])) break;
}
szDest[n] = '\0';
nLen = strlen(szDest);
for (n = 0; n < nLen; n++)
{
if (!isblank(szDest[n])) break;
}
strcpy(szDest, szDest + n);
}
return szDest;
}
int strresvalue(char *buf, STRRESVAR Strstu, int nIndex, void *pValue, int nType) //报文数据域 读取
{
char szStrbuf[1024];
assert(buf != NULL && pValue != NULL);
assert(Strstu.filedlen != NULL && Strstu.filedaddr != NULL);
assert(nIndex >=0 && nIndex < Strstu.nAmount);
memset(szStrbuf, 0, sizeof(szStrbuf));
strncpy(szStrbuf, Strstu.filedaddr[nIndex],Strstu.filedlen[nIndex]);
TrimString(szStrbuf);
switch (nType)
{
case STRINT :
*(int *)pValue = atoi(szStrbuf);
break ;
case STRDOUBLE:
*(double *)pValue = atoi(szStrbuf);
break;
default:
strcpy((char *)pValue, szStrbuf);
break;
}
return 0;
}
/*
int main()
{
cout << "Test Message!" << endl;
char szCestr[] = "0019999999999999999999kevinX 1234567.89"; //定长报文
int nCelen[4] = {3, 19, 6, 12};
int nIndex;
char *nCeAddr[4], szAccno[20], szName[20];
double fAmt;
STRRESVAR stuStr;
stuStr.nAmount = 4;
stuStr.nFlag = 0;
stuStr.filedlen = nCelen;
stuStr.nCompartlen = 0;
stuStr.szCompart[0] = 0;
stuStr.filedaddr = nCeAddr;
strrespre(szCestr, &stuStr);
strresvalue(szCestr, stuStr, 0, &nIndex, STRINT);
strresvalue(szCestr, stuStr, 1, szAccno, STRSTR);
strresvalue(szCestr, stuStr, 2, szName, STRSTR);
strresvalue(szCestr, stuStr, 3, &fAmt, STRDOUBLE);
cout << "id = " << nIndex << endl;
cout << "accno = " << szAccno << endl;
cout << "name = " << szName << endl;
cout << "amt = " << showpoint << fAmt << endl;
return 0;
}
*/
int main()
{
cout << "Test Message!" << endl;
char szCestr[] = "2|!88888888|!kevin_xiang|!1234567.89"; //定分割域报文
int nIndex, nCeLen[4];
char *nCeAddr[4], szAccno[20], szName[20];
double fAmt;
STRRESVAR stuStr;
stuStr.nAmount = 4;
stuStr.nFlag = 1;
stuStr.filedlen = nCeLen;
stuStr.nCompartlen = 2;
strcpy(stuStr.szCompart, "|!");
stuStr.filedaddr = nCeAddr;
strrespre(szCestr, &stuStr);
strresvalue(szCestr, stuStr, 0, &nIndex, STRINT);
strresvalue(szCestr, stuStr, 1, szAccno, STRSTR);
strresvalue(szCestr, stuStr, 2, szName, STRSTR);
strresvalue(szCestr, stuStr, 3, &fAmt, STRDOUBLE);
cout << "id = " << nIndex << endl;
cout << "accno = " << szAccno << endl;
cout << "name = " << szName << endl;
cout << "amt = " << showpoint << fAmt << endl;
return 0;
}
5. 示例二: linux下C读取 ini配置文档
需要上面例一 申明的结构体与函数
config.ini文件内容
[SERVER]
NUM=2
[SERVER1]
IP=192.168.0.1
PORT=8888
[SERVER2]
IP=192.168.0.2
PORT=5555
int GetConfigStrValue(char *buf, void *pValue, int nType) //配置项字符串读写
{
char *nCeAddr[2];
int nCeLen[2];
STRRESVAR stuStr;
stuStr.nAmount = 2;
stuStr.nFlag = 1;
stuStr.filedlen = nCeLen;
stuStr.nCompartlen = 1;
strcpy(stuStr.szCompart, "=");
stuStr.filedaddr = nCeAddr;
strrespre(buf, &stuStr);
assert(strresvalue(buf, stuStr, 1, pValue, nType) == 0);
return 0;
}
int GetConfigValue(char *szPath, char *szRoot, char *szName, void *pValue, int nType) //配置文件读取
{
FILE *fp;
int nFlag = 0;
char buf[1024], szRootExt[100], szNameExt[100];
assert( (fp = fopen(szPath, "r")) != NULL);
sprintf(szRootExt, "[%s]", szRoot);
sprintf(szNameExt, "%s=", szName);
while (feof(fp) == 0)
{
memset(buf, 0, sizeof(buf));
fgets(buf, sizeof(buf), fp);
if (buf[0] == '#') continue;
if (nFlag == 0 && buf[0] != '[') continue;
else if (nFlag == 0 && buf[0] == '[')
{
if (strncmp(buf, szRootExt, strlen(szRootExt)) == 0) nFlag = 1;
}
else if (nFlag == 1 && buf[0] == '[')
{
break;
}
else
{
if (strncmp(buf, szNameExt, strlen(szNameExt)) == 0)
{
assert(GetConfigStrValue(buf, pValue, nType) == 0);
fclose(fp);
return 0;
}
}
}
fclose(fp);
return -1;
}
int main()
{
int nNumber, i, nPort;
char szRoot[100], szIP[100];
assert( GetConfigValue("./config.ini", "SERVER", "NUM", &nNumber, STRINT)==0 );
cout << "No. = " << nNumber << endl;
for( i=0; i<nNumber; i++ )
{
sprintf(szRoot, "SERVER%d", i+1);
memset(szIP, 0, sizeof(szIP));
GetConfigValue("./config.ini", szRoot, "IP", szIP, STRSTR);
GetConfigValue("./config.ini", szRoot, "PORT", &nPort, STRINT);
cout << "SERVER" << i+1 << " IP-->" << szIP << " PORT-->" << nPort << endl;
}
return 0;
}