自定义协议头。扩展通过协议版本来扩展协议头。
#pragma pack (1)
struct comPrtcV0Head
{
u8 fixedHead[COMPRTC_FIX_HEAD_LEN];//固定0XC6B796
u32 datalen;//数据长度
u8 protocVer;//协议版本
u8 encodeType;//加密类型
u8 compressType;//压缩标志
u16 crc;//求和校验
};
#pragma pack()
右值
class myc
{
public:
myc()
{
logwdbg("myc");
}
myc(myc&& ot) noexcept
: val(ot.val)
{
ot.val = 0;
logwdbg("myc1");
}
~myc()
{
logwdbg("~myc");
}
int val;
};
myc tmcc;
int main()
{
logv4OperateClassV2::instance().logv4init();
int a = 10, b = 20;
int &&c = a + b;
int &&rr1 = 10;
rr1 = 20;
const int &d = a;
logwdbg("%p,%p,%p,%p", &a, &b, &c, &d);
rr1 = std::move(a);
logwdbg("%d,%d", rr1, a);
std::string s1 = "123";
std::string &&s2 = "345";
logwdbg("%s,%s", s2.c_str(), s1.c_str());
std::string&& s3 = std::move(s1);
logwdbg("%s,%s", s3.c_str(), s1.c_str());
myc tmc;
tmc.val = 1;
myc tmpc1 = std::move(tmc);
tmpc1.val = 2;
tmc.val = 3;
logwdbg("%d,%d", tmpc1.val, tmc.val);
return 0;
}
25.关于多线程类编程;如果类函数正在运行,其他线程释放该类,会导致类数据被释放而出错!
24.总结,项目的一些坑。
a。TCP长连接,HTTP短连接,UDP各有好处,看如何运用。
b。不用FTP来实现文件传输,其实TCP已经能做到连续发送,而FTP没有加密或服务器屏蔽了21端口就很麻烦
c。不用telnet,而移植ssh。主要是因为加密。
d。我们很喜欢json数据,为了防止数据的冗余可以使用如下方式修身:json-压缩-加密-(base64编码)<--->(base64解码)-解密-解压-json。压缩和解压会浪费时间,json太大也费时间。有测试过:PC电脑制作下面格式的JSON,10万条10列的表格,用了2秒左右。
{
"tableName":{
"cols":[
"col1",
"col2",
"col3",
"col4",
"col5"
],
"rows":[
[
"lxin0",
"surp0",
"\u5e9f\u4e86",
"\u5f850",
"\u98de\u673a"
],
[
"lxin1",
"surp1",
"\u5e9f\u4e86",
"\u5f851",
"\u98de\u673a"
]
]
}
}
e。protocolbuffer还是要更快。
f.锁包含的内容尽可能短,不要出现锁中还有锁的情况,不然容易出现互锁。
g.libevent读回调,多线程情况下,回调时已经上锁了,所以读取保存,数据放到其他线程处理。防止连环锁。
h.数据,执行任务分离。一个类,经常释放和创建,并且执行任务时间长,释放时可能会出现锁死(如果类添加了锁)或崩溃(没有添加锁,数据被释放,任务又在执行)。
23.c++设计问题,用c++就是为了分配空间和释放空间在内部进行。这样可以尽可能的解决内存泄露(遗忘释放)。所以写类的时候,尽可能的把分配放在class内部,释放时一起释放。
22.undefined reference to xxx问题。明明添加了.so 或.o但是提示该问题。可能是因为g++链接gcc编译的.o文件。需要对gcc编译的头文件进行处理:
extern "C" {
#include "sample_comm.h"
#include "acodec.h"
#include "audio_aac_adp.h"
#include "audio_dl_adp.h"
#include "audio_mp3_adp.h"
}
参考:
g++链接gcc编译的库报错“undefined reference to xxx”
当用extern “c”编译库函数之后,在c++代码中调用时,出现标题错误。
解决方法:
在包含头文件时,告诉编译器这个是c函数。
//假定动态库的头文件为 tools.h
extern “C”{
#include “tools.h”
}
这样在使用g++编译c++代码时,编译动态库中的函数使用C的编译方式。而不会处理函数名导致在库中无法找到函数。
21.静态编译出错问题:参考mysql静态编译_静态编译mysql库到程序中遇到的问题_AslrDep的博客-CSDN博客
g++ -o test.cgi test.cpp -static -lsqlite3 -llog4cplus -ljsoncpp -lpthread -ldl -lm
报错:Using 'dlopen' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
这个运行时需要动态库,而我程序必须用静态编译。折中:-Wl,-dn跟静态编译..-Wl,-dy接动态编译。
g++ -o test.cgi test.cpp -Wl,-dn -lsqlite3 -llog4cplus -ljsoncpp -Wl,-dy -lpthread -ldl -lm
$(CXX) -o $@ $^ $(COM_SRC) -Wl,-dn $(CFLAGS) $(COMPILE_USR_FLAGS) -lcgicc -Wno-write-strings -ljsoncpp -lsqlite3 -Wl,-dy -lpthread -ldl -lm
20.异常情况
long tmpval = 0;
string tmpstr = "";
tmpval = atol(tmpstr.c_str());
logwdbg("%d", tmpval);
try
{
tmpval = stol(tmpstr);//对空字符串进行转换。这里会出现异常
}
catch(...)
{
logwdbg("err");
}
logwdbg("%d", tmpval);
note:应用层程序设计模式:
Z1.分模块:
A控制模块-核心模块;
B检测状态模块:硬件接口异常。比如网络,串口,I2C通讯,输入信号异常,其他模块工作异常等
C参数管理模块
D数据储存模块,如sql数据库,文件操作
Ehttps通讯模块
F自定义协议模块
G其他工作用到的模块
参考手册cppreference.com
1、虚函数占有对象空间,而普通成员函数不会。估计是为了指向子类的函数地址
2、多线程操作同一个容器、迭代器会导致出错,因此加锁。
3、下面代码有问题:条件变量会出现不正常唤醒!!!需要使用lambda来加强控制。 如if (myconvar.wait_for(waitLock, 200 * 1ms, [a]{return *a;})){}。参考std::condition_variable::wait_for - cppreference.com
std::mutex mymutex;
condition_variable myconvar;
atomic_int myatoval = 0;
void threadfunc()
{
while (1)
{
Sleep(50);
if (myatoval % 5 == 0)
{
myconvar.notify_all();
}
}
}
void convarWait()
{
myatoval = (myatoval + 1) % 100;
int retrycount = 2;
while (retrycount-- > 0)
{
{
std::unique_lock<std::mutex> waitLock(mymutex);
if (myconvar.wait_for(waitLock, 200 * 1ms) == cv_status::no_timeout)
{
cout << "condition is weakuped! atoval = " << myatoval << endl;
break;
}
else
{
cout << "condition timeout! ato = " << myatoval << endl;
}
}
}
}
int main()
{
thread tmpthread = thread(threadfunc);
while (1)
{
Sleep(10);
convarWait();
}
return 0;
}
4、模板类写在头文件,不要成员函数与类分离写。不然会很麻烦。
5、c++成员函数不能实现每个对象都有空间,需要回调成员函数时,把对象也放到回调的参数中即可。
6、类的构造函数不能是虚函数,是因为我们new一定是子类,会调用父类和子类构造函数。析构函数为虚函数主要应用在指针情况,在释放父类指针就相当于直接释放子类。如果不是虚函数,只会释放父类。如果不是指针情况,释放子类,会调用子类析构和父类析构。
7、字符串流得到4位补0的字符串:需头文件:#include <iomanip>
stringstream strinput;
strinput << setw(4) << setfill('0') << count;
8、c++11才支持to_string,如:
string mys = "hello world!" + to_string(100) + ",finish!";
如果<c++11这样写,或者用stringstream(例7)来处理:
string mys = "hello world!";
mys += 100;
mys += ",finish!";
9、stringstream的坑:
stringstream getcmd;
getcmd << "id1=" << id1<< "sid1=" << id2 << ";";
tmpstr = getcmd.str();//这里还没有问题
getcmd.str("");//如果没有这一句,下面的内容会和上面内容组成一个字符串的。getcmd.clear();也是没有删除流缓存的
getcmd << "id3=" << id3<< "sid4=" << id4 << ";";
tmpstr = getcmd.str();
10、延时,睡眠函数:
std::this_thread::sleep_for(std::chrono::milliseconds(1000)); //单位是毫秒
11.new 错误时不是返回null,而是抛出异常,可以使用:new (std::nothrow)来关闭一场,然后判断null。如:
int* p = new (std::nothrow) int[100000];
if ( p == nullptr ){}
12.cout << 是根据数据类型进行输出的,int输出数字,而char输出字符,如果你要输出char为数字,可以转为int
13.扩展cout,用方法1会出现我要屏蔽打印就想不到更好的办法了,而方法2直接使用空宏定义即可屏蔽
//#define coutdbg cout << "[cxxdbg:" << __func__ << "," << __LINE__ << "]"//方法1
#define coutdbg(fmt) //cout << "[cxxdbg:" << __func__ << "," << __LINE__ << "]" << fmt << endl;//方法二
使用:coutdbg("abc=" << abc);
printf参考:
#define PRINTF_DEF(lev, fmt, lprt, ...) do {\
if(DEBUG_LEVEL_DEF >= lev) {\
struct timeb tnow;\
struct tm *tmnow;\
ftime(&tnow);\
tmnow = localtime(&tnow.time);\
printf("[%d-%d-%d %d:%d:%d.%3d][%s][%s,%d]" fmt "\n", tmnow->tm_year + 1900, tmnow->tm_mon + 1, \
tmnow->tm_mday, tmnow->tm_hour, tmnow->tm_min, tmnow->tm_sec, tnow.millitm, \
lprt, __func__, __LINE__, ##__VA_ARGS__);\
}\
}while(0);
#define printfdbg(fmt, ...) do {\
struct timeb tnow;\
struct tm *tmnow;\
ftime(&tnow);\
tmnow = localtime(&tnow.time);\
printf("[%d-%d-%d %d:%d:%d.%3d][%s,%d]" fmt "\n", tmnow->tm_year + 1900, tmnow->tm_mon + 1, \
tmnow->tm_mday, tmnow->tm_hour, tmnow->tm_min, tmnow->tm_sec, tnow.millitm, \
__func__, __LINE__, ##__VA_ARGS__);\
}while(0);
cout参考:
#define cout_base(lev, fmt) do {\
if(DEBUG_LEVEL_DEF >= lev) {\
struct timeb tnow;\
struct tm *tmnow;\
ftime(&tnow);\
tmnow = localtime(&tnow.time);\
cout << "[" << tmnow->tm_year + 1900 << "-" << tmnow->tm_mon + 1 << "-" << tmnow->tm_mday \
<< " " << tmnow->tm_hour << ":" << tmnow->tm_min << ":" << tmnow->tm_sec << "." \
<< setw(3) << setfill('0') << tnow.millitm << "]" << fmt << endl;\
}\
}while(0);
14.高内聚低耦合:高内聚低耦合_百度百科
15.boost 的json:参考 boost json生成和解析用法 - doutu - 博客园
--> boost json不支持空数组,在本例中空数组对应的格式为"列表":"";
--> 空的字符串字段转换为数字会抛异常。
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <boost/foreach.hpp>
#include <sys/timeb.h>
#include <vector>
#include <iostream>
using namespace boost::property_tree;
using namespace std;
#define cout_base(lev, fmt) \
do \
{ \
if (4 >= lev) \
{ \
struct timeb tnow; \
struct tm *tmnow; \
ftime(&tnow); \
tmnow = localtime(&tnow.time); \
cout << "[" << tmnow->tm_year + 1900 << "-" << tmnow->tm_mon + 1 << "-" << tmnow->tm_mday \
<< " " << tmnow->tm_hour << ":" << tmnow->tm_min << ":" << tmnow->tm_sec << "." \
<< setw(3) << setfill('0') << tnow.millitm << "]" << fmt << endl; \
} \
} while (0);
#define coutdbg(fmt) cout_base(4, "dbg[" << __func__ << "," << __LINE__ << "]" << fmt)
#define MY_ROW_NUMBER 20
bool CreateJson(string &str)
{
stringstream tmpstream;
int i;
try
{
ptree boot;
boot.put<string>("table", "人物表格");
boot.put<string>("rows", to_string(MY_ROW_NUMBER));
ptree rowlist;
ptree columnList;
for (i = 0; i < MY_ROW_NUMBER; i++)
{
columnList.clear();
columnList.put<string>("name", "sheng-" + to_string(i));
columnList.put<int>("体重", rand() % 1000);
columnList.put<string>("升高", to_string(random() % 1000));
columnList.put<string>("外号", "外号" + to_string(i));
rowlist.push_back(ptree::value_type("", columnList));
}
boot.put_child("列表", rowlist);
write_json(tmpstream, boot);
}
catch (ptree_error e)
{
coutdbg(e.what());
return false;
}
str = tmpstream.str();
cout << str << endl;
return true;
}
struct peopleinformDef
{
string name;
int height;
int weight;
string uname;
};
bool ParseJson(string &str)
{
try
{
ptree boot;
stringstream tmpstream(str);
read_json(tmpstream, boot);
if (boot.find("体重") != boot.not_found())
{
coutdbg(boot.get<string>("table"));
coutdbg(boot.get<string>("rows"));
}
else
{
coutdbg("err");
}
ptree plist = boot.get_child("列表");
vector<peopleinformDef> pilist;
BOOST_FOREACH (auto val, plist)
{
peopleinformDef tmpif;
tmpif.name = val.second.get<string>("name");
tmpif.weight = val.second.get<int>("体重");//atof(val.second.get<string>("体重").c_str());
tmpif.height = atof(val.second.get<string>("升高").c_str());
tmpif.uname = val.second.get<string>("外号");
pilist.push_back(tmpif);
}
for (int i = 0; i < pilist.size(); i++)
{
coutdbg(pilist[i].name << "|" << pilist[i].weight << "|" << pilist[i].height << "|" << pilist[i].uname);
}
}
catch (ptree_error pt)
{
coutdbg(pt.what());
return false;
}
return true;
}
int main(int argc, char *argv[])
{
string tmpstr;
CreateJson(tmpstr);
ParseJson(tmpstr);
return 0;
}
16.jsoncpp,我们去json-cpp download | SourceForge.net下载源码,编译我们只需要:json(头文件夹) json_reader.cpp json_tool.h json_value.cpp json_valueiterator.inl json_writer.cpp Makefile文件即可编译,自己写makefile。测试代码:其中root["错误的名字"].asString()不会异常,比boost好一些拉!
#include <types.h>
#include <json/json.h>
void writeToJsonStr(string &outjson)
{
Json::Value root;
root["rootflag"] = Json::Value(1);
root["rootname"] = Json::Value("root");
Json::Value rootinf;
rootinf["childNumber"] = Json::Value(2);
rootinf["age"] = Json::Value(33);
rootinf["favor"] = Json::Value("lxin");
root["inform"] = rootinf;
for (int i = 0; i < 2; i++)
{
Json::Value child;
child["name"] = Json::Value("child" + to_string(i));
child["age"] = Json::Value(i + 10);
child["sex"] = Json::Value(i % 2);
root["childs"].append(child);
}
for (int i = 0; i < 5; i++)
{
root["gospace"].append("place_" + to_string(i));
}
//直接输出
cout << "FastWriter:" << endl;
Json::FastWriter fw;
cout << fw.write(root) << endl
<< endl;
//缩进输出
cout << "StyledWriter:" << endl;
Json::StyledWriter sw;
cout << sw.write(root) << endl
<< endl;
outjson = sw.write(root);
}
void parseJsonStr(string injson)
{
Json::Reader tmpreader;
Json::Value root;
if (!tmpreader.parse(injson, root))
{
couterr("err");
}
Json::FastWriter fw;
cout << fw.write(root) << endl;
coutdbg(root["rootname"].asString());
coutdbg(root.isMember("noname") << "," << root.isMember("rootname"));
coutdbg(root["childs"].isArray() << "," << root["gospace"].isArray());
for (auto a = root.begin(); a != root.end(); a++)
{
printfdbg("key=%s,type=%d", a.memberName(), a->type());
if (a->type() == Json::arrayValue)
{
for (auto b = a->begin(); b != a->end(); b++)
{
printfdbg("key=%s,type=%d", b.memberName(), b->type());
}
}
}
}
int main()
{
string tmpstr;
writeToJsonStr(tmpstr);
parseJsonStr(tmpstr);
}
17.json传输二进制数据参考:把二进制数据压缩后使用Base64编码(每6bit组成一个字符,数据大1/3,比2倍好吧)为字符串。接收到数据时解码解压即可
18.zlib库:Index of /fossils
编译:cd $(OPENSOURCE_LIB_BUILD_PWD) && export gcc=$(CROSS_COMPILE)-gcc && ./configure --prefix=$(OPENSOURCE_INSTALL_PWD) && make clean && make && make install
使用需注意的地方:
1.压缩数组如果是随即数组,压缩效果低,甚至比原属组还大一点。
2.数组小压缩率低
3.压缩时可以用compressBound来获得最大的压缩后的长度。
4.解压数组长度我们不好确定,个人觉得使用固定大小,与压缩前的进行协商最大值即可。
#include <types.h>
#include <ctimer.h>
#include <json/json.h>
#include <base64.h>
#include <zlib.h>
void printstrbuf(string sin)
{
coutdbg("the string len is : " << sin.length());
for (int i = 0; i < (int)sin.length(); i++)
{
printf("%02X ", (u8)sin[i]);
if (i % 16 == 15)
{
printf("\n");
}
}
printf("\n");
}
int mycompress(string in, string &out, int level = 9)
{
Bytef *tmpcomp;
uLong tmpcompLen;
int comperr;
tmpcompLen = compressBound(in.length());
tmpcomp = newwork Bytef[tmpcompLen];
out.clear();
if (!tmpcomp)
{
couterr("err");
return -10;
}
//comperr = compress(tmpcomp, &tmpcompLen, (const Bytef*)in.c_str(), in.length());
comperr = compress2(tmpcomp, &tmpcompLen, (const Bytef *)in.c_str(), in.length(), level);
if (comperr != Z_OK)
{
printferr("err:%d", comperr);
goto freeOut;
}
out.append((char *)tmpcomp, tmpcompLen);
freeOut:
delete[] tmpcomp;
return comperr;
}
int myumcompress(string in, string &out)
{
Bytef *tmpuncomp;
uLong tmpuncompLen;
int comperr;
tmpuncompLen = 10 * 1024 * 1024; //use fixed uncompress max len = 10M, in.length() * 30;
tmpuncomp = newwork Bytef[tmpuncompLen];
out.clear();
if (!tmpuncomp)
{
couterr("err");
return -10;
}
//comperr = uncompress(tmpuncomp, &tmpuncompLen, (const Bytef*)in.c_str(), in.length());
uLong inlen = in.length();
comperr = uncompress2(tmpuncomp, &tmpuncompLen, (const Bytef *)in.c_str(), &inlen);
if (comperr != Z_OK)
{
printferr("err:%d", comperr);
goto freeOut;
}
out.append((char *)tmpuncomp, tmpuncompLen);
freeOut:
delete[] tmpuncomp;
return comperr;
}
// string getPhotoStr(void)
// {
// string tmps, tmpsout;
// for (int i = 0; i < 1024; i++)
// {
// tmps += rand() % 256;
// }
// base64Encode(tmps, tmpsout);
// return tmpsout;
// }
string getPhotoStr(void)
{
string tmps, tmpsout;
for (int i = 0; i < 1024; i++)
{
tmps += i % 256;
}
base64Encode(tmps, tmpsout);
return tmpsout;
}
void getJsonStr(string &outjson, int arraylen)
{
Json::Value root;
root["table"] = Json::Value("testtable");
for (int i = 0; i < arraylen; i++)
{
Json::Value child;
child["name"] = Json::Value("childmy" + to_string(i));
child["age"] = Json::Value(i + 10);
child["sex"] = Json::Value(i % 2);
child["addr"] = Json::Value("中南达到123345中国" + to_string(i));
child["photo"] = Json::Value(getPhotoStr());
root["childs"].append(child);
}
// for (int i = 0; i < 5; i++)
// {
// root["gospace"].append("place_" + to_string(i));
// }
// //直接输出
// cout << "FastWriter:" << endl;
Json::FastWriter sw;
// cout << fw.write(root) << endl
// << endl;
//缩进输出
//cout << "StyledWriter:" << endl;
//Json::StyledWriter sw;
// cout << sw.write(root) << endl
// << endl;
outjson = sw.write(root);
}
void parseJson(string jsonstr)
{
Json::Reader tmpreader;
Json::Value root;
if (!tmpreader.parse(jsonstr, root))
{
couterr("err");
return;
}
coutdbg(root["table"].asString());
coutdbg(root["childs"].size())
}
int main()
{
string strorigin, strencode, strdecode;
int compressCout = 1;
coutdbg("test rand value!");
timerc myt;
while (compressCout++ < 5000)
{
strorigin.clear();
for (int i = 0; i < compressCout; i++)
{
strorigin += rand() % 256;
}
if (mycompress(strorigin, strencode))
{
break;
}
//printfdbg("compress: %lu->%lu", strorigin.length(), strencode.length());
if (myumcompress(strencode, strdecode))
{
break;
}
//printfdbg("uncompress: %lu->%lu", strencode.length(), strdecode.length());
if (strdecode.compare(strorigin) != 0)
{
couterr("err");
printstrbuf(strorigin);
printstrbuf(strdecode);
}
}
coutdbg("used time:" << myt.ints());
myt.begin();
for (compressCout = 1; compressCout < 500; compressCout++)
{
getJsonStr(strorigin, compressCout);
if (mycompress(strorigin, strencode))
{
break;
}
//printfdbg("compress: %lu->%lu", strorigin.length(), strencode.length());
if (myumcompress(strencode, strdecode))
{
break;
}
printfdbg("count=%d, uncompress: %lu->%lu", compressCout, strencode.length(), strdecode.length());
if (strdecode.compare(strorigin) != 0)
{
couterr("err");
printstrbuf(strorigin);
printstrbuf(strdecode);
}
parseJson(strdecode);
}
coutdbg("used time:" << myt.ints());
}
json传输二进制的方案_xingty的博客-CSDN博客_json 二进制
19. 如果父类析构函数为虚函数,释放父类对象,会先调用子类的析构函数,再释放父类!如果不是,则只释放父类。
20. new一个结构体: myinfo *abc = new myinfo;和myinfo *abc = new myinfo();是有差异的,加了()后,初始化为0!
21.base64参考:根据java.util.Base64中Base64.getEncoder().encode和Base64.getDecoder().decode样例。
备注:java.util.Base64中还有getUrlEncoder(特殊字节不是+/而是-_)和getMimeEncoder(74字节添加\r\n)
编解码与网页保持一致:Base64 编码/解码 | 菜鸟工具
#ifndef __BASE64_ENC_DEC_H__
#define __BASE64_ENC_DEC_H__
#include <types.h>
class base64Class
{
public:
static string Encode(const unsigned char *Data, int DataByte)
{
if(!Data)
{
return "";
}
//编码表
const char EncodeTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
//返回值
string strEncode;
unsigned char Tmp[4] = {0};
// int LineLength = 0;
for (int i = 0; i < (int)(DataByte / 3); i++)
{
Tmp[1] = *Data++;
Tmp[2] = *Data++;
Tmp[3] = *Data++;
strEncode += EncodeTable[Tmp[1] >> 2];
strEncode += EncodeTable[((Tmp[1] << 4) | (Tmp[2] >> 4)) & 0x3F];
strEncode += EncodeTable[((Tmp[2] << 2) | (Tmp[3] >> 6)) & 0x3F];
strEncode += EncodeTable[Tmp[3] & 0x3F];
// if(LineLength+=4,LineLength==76) {strEncode+="\r\n";LineLength=0;}
}
//对剩余数据进行编码
int Mod = DataByte % 3;
if (Mod == 1)
{
Tmp[1] = *Data++;
strEncode += EncodeTable[(Tmp[1] & 0xFC) >> 2];
strEncode += EncodeTable[((Tmp[1] & 0x03) << 4)];
strEncode += "==";
}
else if (Mod == 2)
{
Tmp[1] = *Data++;
Tmp[2] = *Data++;
strEncode += EncodeTable[(Tmp[1] & 0xFC) >> 2];
strEncode += EncodeTable[((Tmp[1] & 0x03) << 4) | ((Tmp[2] & 0xF0) >> 4)];
strEncode += EncodeTable[((Tmp[2] & 0x0F) << 2)];
strEncode += "=";
}
return strEncode;
}
static string Decode(const unsigned char *Data, int DataByte)
{
if(!Data)
{
return "";
}
char const DecodeTable[256] =
{
(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,
(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,
(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,
(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,
(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,
(char)0XFF,(char)0XFF,(char)0XFF,(char)0X3E,(char)0XFF,(char)0XFF,(char)0XFF,(char)0X3F,
(char)0X34,(char)0X35,(char)0X36,(char)0X37,(char)0X38,(char)0X39,(char)0X3A,(char)0X3B,
(char)0X3C,(char)0X3D,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,
(char)0XFF,(char)0X00,(char)0X01,(char)0X02,(char)0X03,(char)0X04,(char)0X05,(char)0X06,
(char)0X07,(char)0X08,(char)0X09,(char)0X0A,(char)0X0B,(char)0X0C,(char)0X0D,(char)0X0E,
(char)0X0F,(char)0X10,(char)0X11,(char)0X12,(char)0X13,(char)0X14,(char)0X15,(char)0X16,
(char)0X17,(char)0X18,(char)0X19,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,
(char)0XFF,(char)0X1A,(char)0X1B,(char)0X1C,(char)0X1D,(char)0X1E,(char)0X1F,(char)0X20,
(char)0X21,(char)0X22,(char)0X23,(char)0X24,(char)0X25,(char)0X26,(char)0X27,(char)0X28,
(char)0X29,(char)0X2A,(char)0X2B,(char)0X2C,(char)0X2D,(char)0X2E,(char)0X2F,(char)0X30,
(char)0X31,(char)0X32,(char)0X33,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,
(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,
(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,
(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,
(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,
(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,
(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,
(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,
(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,
(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,
(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,
(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,
(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,
(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,
(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,
(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,
(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,(char)0XFF,
};
//返回值
string strDecode;
int nValue;
int i = 0;
DataByte = DataByte / 4 * 4;
while (i < DataByte)
{
if (*Data != '\r' && *Data != '\n')
{
nValue = DecodeTable[*Data++] << 18;
nValue += DecodeTable[*Data++] << 12;
strDecode += (nValue & 0x00FF0000) >> 16;
if (*Data != '=')
{
nValue += DecodeTable[*Data++] << 6;
strDecode += (nValue & 0x0000FF00) >> 8;
if (*Data != '=')
{
nValue += DecodeTable[*Data++];
strDecode += nValue & 0x000000FF;
}
}
i += 4;
}
else // 回车换行,跳过
{
Data++;
i++;
}
}
return strDecode;
}
};
#endif
22.做字符串分割:
std::vector<std::string> splitStrWithPat(const std::string &str, const std::string pattern)
{
std::vector<std::string> ret;
if (pattern.empty())
{
return ret;
}
size_t start = 0, index = str.find_first_of(pattern, 0);
while (index != str.npos)
{
if (start != index)
{
ret.push_back(str.substr(start, index - start));
}
start = index + pattern.length();
index = str.find_first_of(pattern, start);
}
if (!str.substr(start).empty())
{
ret.push_back(str.substr(start));
}
return ret;
}
std::string linkStrWithPat(const std::vector<std::string> &vecstr, const std::string pat)
{
std::string ret;
for (size_t i = 0; i < vecstr.size(); i++)
{
ret.append(vecstr[i]);
if (i < vecstr.size() - 1)
{
ret.append(pat);
}
}
return ret;
}