VC6的环境小结

安装:
现在主要有win7,win10,但后者还没听说可以装成功。不过好在有虚机嘛。所以,只聊下win7的VC6安装。
VC6的安装源你总应该拿到,最好是SP6的。
如果是英文版本,安装会少些步骤,有一个是overwrite JIT setting的对话框,网查后我选择了否。
如果是中文版本,请寻找帖子,名为:彻底解决兼容问题:Windows 7下载安装 Visual C++ 6_0(VC6) 全程图解
一步步安装即可,VSS和MSDN都可跳过不安装。
最重要的就是插件了,这个才是彰显尊贵的手段。
filetool,wndtab,VA,VC6lineNumber
一个都不能少,全破解版(自己搜吧)。
配置:
1,用标准库,要注意<>的内容两边加空格 ,并且#pragma   warning(disable:4786)来屏闭VC6中的使用标准库的警告。
2,用C++运行程序时总是出现这个错误BSCMAKE: error BK1510 : corrupt .SBR file ‘.\Debug\StdAfx.sbr’,在C/C++—>gernal中取消生成浏览信息的选项。
3,PROJECT->SETING->C/C++->PREPROCESSOR->定义 _AFXDLL,也就是C/C++选项中定义了宏  用_AFCDLL 取代 USERDLL 能解决很多nafxcwn.lib开头的链接错误。
4,Link选项中ignore default lib,根据方式设定,手工加/NODEFAULTLIB:或者填库名。
5,VC6下导出类中的静态成员需要“壳子”才可以调用,而在VS2012中,却直接可用。当不同的环境生成的dll或客户端相互调用时,要注意字符集问题,VC6并不是unicode的。
6,要声明通用函数时,可以不加;在{}后面,但应该声明为static,这样可以避免重复定义的报错。
7,string 的split算法,replace,trim需要自己写算法,最后找到使用模板的。
8,在有unicode的项目中,在循环中使用W2A()可能会有报错,或者提示为,run-time check fail #2 stack …,内存操作越界之类,在VS2012中项目–C\C++设置中,改掉一个设置,“基本运行时检查”从“两者(/RTC1,等同于 /RTCsu) (/RTC1)”换成默认值。其实出现它的问题,还是在于使用scanf时,“%02x”的操作数组应该至少是3,要包含个’\0’的。
9,项目是要供别人调用的dll,要在配置中使用/MD.
10,要通过exe来调度dll时,要配置debug session和work directory
11,当出现外部链接错误时,要先检查link中的lib文件,是否存在于项目目录中。并不需要dll,因为只是链接步骤。
12,字符集问题,VC6是基于MBCS的(有宏定义,当然可以强制成unicode),对于中文用两字节,而字母和数字用一个字节。而VS201X,都是用unicode默认的,所以也就存在于宽字符的结构了,和一系列转来转来的操作。

tinyxml使用技巧

实在是好用呀,优点比如:
1,一次装载到内存,其它地方全用引用即可,一个小指针可以是一个元素,也可是一个节(内部很多子元素)。
2,不用管理元素的内存回收,我是没看源码,号称管理的很好。一个父元素删除,它包含的所有子都释放了。
3,api较少并且,一目了然。
遍历时基本就用三个算法:
1)同级的循环(没用遍历以防会误解包括子节点处理)
//pParent当然是父了
for (TiXmlNode *pSTATE = pParent->FirstChild( “STATE” ); pSTATE; pSTATE = pSTATE->NextSibling(“STATE” ))
{}
注意:要用TiXmlNode *结构,不要用TiXmlElement*
2)当同级的到了最后一个,NextSibling()会返回个空。这时你可以用跳了。
pParent->IterateChildren( pSTATE )
3)以上两个掌握了,就可以玩遍历了。不过,要注意,走到叶子节点时,要跳级。但如果你手工跳了,可能遍历会有重复情况。这时可以使用函数的静态变量喽。可以用静态变量记住父结点。可以用静态list来存放处理过的节点,跳过重复情况。示例代码如下:
void handleExportMap(TiXmlNode * pSrc)
{
if (!pSrc ) return;

static TiXmlNode *bodyItem;

if (“FRAME_BODY” == pSrc->ValueTStr())
{
bodyItem = pSrc ;
}
static TiXmlNode *curpItem;
int t = pSrc ->Type();
printf( “type %d \n” , t);

switch (t)
{
case TiXmlNode :: TINYXML_DOCUMENT:
printf( “Document” );
break ;

case TiXmlNode :: TINYXML_ELEMENT:
printf( “Element [%s]” , pSrc ->Value());
//
if (“CONTENT” == pSrc->ValueTStr())
{
curpItem = pSrc ;
}
if (“MAP” == pSrc->ValueTStr())
{
//跳过MAP的处理
pSrc = curpItem->IterateChildren(pSrc ->Parent());

if (!pSrc )
return ;
else
printf( “Element [%s]” , pSrc ->Value());
}
if (“STATE” == pSrc->ValueTStr() && pSrc == pSrc ->Parent()->LastChild())
{
//跳过STATE的处理
//map中的state
pSrc = curpItem->IterateChildren(pSrc ->Parent()->Parent());

if (!pSrc )
return ;
else
printf( “Element [%s]” , pSrc ->Value());
}

if (“ITEM” == pSrc->ValueTStr())
{

printf( “Element [%s]” , pSrc ->Value());

if (!pSrc ->NoChildren())
{
if (!bMoveItems(pSrc ))
return ;
}

} //end if (!pSrc->NoChildren())
if (“MESSAGE” == pSrc->ValueTStr())
{
curpItem = pSrc ;
if (!bMoveItems(pSrc ))
return ;
}
break ;

case TiXmlNode :: TINYXML_COMMENT:
printf( “Comment: [%s]” , pSrc ->Value());
break ;

case TiXmlNode :: TINYXML_UNKNOWN:
printf( “Unknown” );
break ;

case TiXmlNode :: TINYXML_TEXT:
printf( “Text: [%s]\n” , pSrc ->ToText()->Value());
break ;

case TiXmlNode :: TINYXML_DECLARATION:
printf( “Declaration” );
break ;
default :
break ;
}

if (pSrc ->NoChildren())
{
pSrc = pSrc ->NextSibling();

handleExportMap( pSrc );
}
else
{
//过滤,直到合法
while (pSrc = pSrc->FirstChild())
{
handleExportMap( pSrc );

}

}
}
在这个遍历的框架基础上,可以变化和设计出你的需求了,注意,要分化任务,只做遍历,和只做节点的处理,不要混在一起,不然,一个bug两三天呀。上面的bMoveItems就是当定位到了ITEM节点时,我调用其它的业务处理。因为,人只关注ITEM节点,所以它有一些子节点MAP或子子节点STATE,都在上面一一跳过了。

最后,附上“米”,好“下锅”,注意层次。
<?xml version=”1.0″ encoding=”UTF-8″ ?>
<!– edited with XMLSpy v2013 (http://www.altova.com) by () –>
<LINE ID=”11″ VERSION=”1″>
<FRAME_HEADER>
<ITEM ID=”system_id” LENGTH=”1″ CURPOS=”0″ />
<ITEM ID=”total_length” LENGTH=”2″ CURPOS=”1″ MAX_VALUE=”1025″ />
<ITEM ID=”multi_flag” LENGTH=”1″ CURPOS=”3″ DEFAULT=”0″ />
</FRAME_HEADER>
<FRAME_BODY>
<MESSAGE ID=”NETWORK_ALIVE_STATUS” TYPE=”1″ TRANS=”O2N”>
<ITEM ID=”message_length” LENGTH=”2″ CURPOS=”4″ DESC=”消息长度” MIN_VALUE=”13″ interal_index=”1″ />
<ITEM ID=”time” LENGTH=”4″ CURPOS=”6″ DESC=”时间” FORMAT=”HHMMSS” interal_index=”2″>
<MAP NID=”time” MODE=”1″ SAME=”Y” NINDEX=”2″ KEY=”time|6|4″ DESC=”时间” EX_CODE_KEY=”” />
</ITEM>
<ITEM ID=”version” LENGTH=”2″ CURPOS=”10″ DESC=”版本” DEFAULT=”01H” interal_index=”3″ />
<ITEM ID=”msg_id” LENGTH=”2″ CURPOS=”12″ DESC=”报文ID” interal_index=”4″ />
<CONTENT ID=”data0″ DEFAULT_LEN=”3″>
<ITEM ID=”line_id” LENGTH=”2″ CURPOS=”14″ DESC=”线路号” interal_index=”5″>
<MAP NID=”line_id” MODE=”1″ SAME=”Y” NINDEX=”5″ KEY=”line_id|14|2″ EX_CODE_KEY=”” />
</ITEM>
<ITEM ID=”status” LENGTH=”1″ CURPOS=”16″ DESC=”状态字节:1:代表与当前线路号的信息源(server)连接正常;0:代表断开。” interal_index=”6″>
<MAP NID=”xt_pkg” MODE=”1″ SAME=”N” NINDEX=”6″ KEY=”xt_pkg|16|1″ EX_CODE_KEY=””>
<STATE ID=”11_STATUS_CODE_1″ RAWVALUE=”0x00″ HINT=”通信中断” SAME=”Y”>0x80</STATE>
<STATE ID=”11_STATUS_CODE_2″ RAWVALUE=”0x01″ HINT=”通信正常” SAME=”Y”>0x02</STATE>
</MAP>
</ITEM>
</CONTENT>
</MESSAGE>
<MESSAGE ID=”LOAD_DEVICE_STATUS” TYPE=”1″ TRANS=”N2O”>
<ITEM ID=”message_length” LENGTH=”2″ CURPOS=”4″ DESC=”消息长度” MIN_VALUE=”12″ interal_index=”1″ />
<ITEM ID=”time” LENGTH=”4″ CURPOS=”6″ DESC=”时间” FORMAT=”HHMMSS” interal_index=”2″ />
<ITEM ID=”version” LENGTH=”2″ CURPOS=”10″ DESC=”版本” DEFAULT=”01H” interal_index=”3″ />
<ITEM ID=”msg_id” LENGTH=”2″ CURPOS=”12″ DESC=”报文ID” interal_index=”4″ />
<CONTENT ID=”data0″ DEFAULT_LEN=”2″>
<ITEM ID=”line_id” LENGTH=”2″ CURPOS=”14″ DESC=”线路号” interal_index=”5″ />
</CONTENT>
</MESSAGE>
</MESSAGE>
</FRAME_BODY>
</LINE>

保存和另存,一个TiXmlDocument的SaveFile()函数就搞定了。
生成新的XML时,会用一个api就成了。parent->LinkEndChild(TiXmlNode *);根据不用我解释了吧。加同级,用parent()找父指针嘛。

北京工作居住证攻略

朝阳区人才的位置:三元桥,凤凰城附近
海淀区人才的位置:北京市海淀区西四环北路73号中关村人才发展中心
办理:
首先,你要把自己的证件都复印好,不用等待网络上的信息注册后再准备,但完税证明不要提前,因为有效期只有一个月。
但办这事的入口,还是你公司为你注册了帐号,然后,你就可以登陆并看到办理居住证的链接了。
然后,就是材料最后的准备阶段了,去开完税证明和公司行政打交道完成各种手续。
最后,在提交时,想要办小孩上学要注意随迁问题。住址和居住证跨区的小孩上学问题,需要向学校搞清楚。

年检:
这其实是公司人力的动作,每年四月,他们应该用他们的企业帐号登陆系统,做操作。

续证:
工作居住证到期的前后一个月,要在网上先申请,然后,要去所在区人才,柜台办理。又要拿一大堆打印的申请。

变更:
分公司,住址,随迁等种类变更。但重要的是公司变更吧。
本人下家也具有工作居住证的资质,所以,变更准备材料如下:
(只针对海淀人才)
1)居住证原件(这不用说吧)
2)关于为XXX同志办理《北京市工作居住证》聘用单位变更的申请———-网找模板,加盖公司章
3)聘用单位变更申请———–网找模板,是个人申请,所以不用公章
4)营业执照复印副本
5)离职证明原件+复印件———-注意复印件也要盖章,经办人签字(附句话:经本人同意与原件内容一致)
6)新公司的劳动合同原件+复印件———-注意复印件也要盖章,经办人签字 (附句话: 经本人同意与原件内容一致)
不用每页都有章,最好公司有复印件专用的方章,可以在首页和签字页盖章即可。

说什么诚信声明和进入系统打印申请表,这两项并不需要。
当你的申请被受理后,海淀人才就告诉我,两个月左右,登录看一下系统中办理的状态,如果是完成,那么,你有两个方式来取回自己的居住证。一,让公司人事去办事时顺便取到,二,自己打印一个介绍信,模板不好找,但当时,我把柜台的模板照了下来。这样,可以自己起草一个,找公司盖章,注意只好盖章后,拿这个介绍信才能自己取到。
注销:
也是公司人力的动作,当你想在新公司变更或重新办新的,或其它业务时,前公司应该给你注销先。
注销后,两个月内个人如果没有延期注销的动作,那么你的居住证生命线就over了

延期注销:
当你换的新公司试用期较长,或者暂时没公司,或者工作忙时,可以在注销的两个月最后几天,申请延期注销。
那么你就有了6个月的机动时间。当然,你要登陆系统,自己填写申请并提交。如果你的新公司比较确定,要在备注的内容里体现。据说这样
会不仅有6个月,即使长一些,也能救起证的生命线。提交成功就行,不用去柜台了。

以Qtreeview为例介绍Qt的model/view/item框架

因为,Qtreeview是层次容器,所以会复杂。尤其是加子行的时候。
首先,要找到是哪里加子行。有两个思路:位置索引还是item
1)用model的位置索引方式,定位到要加子行的QModelIndex.
2)用item方式,即后台以批量的list加树时,找到item的位置。
3)用model,如果后台的批量item加完就释放,若无从找到,有一个神器就是Model->itemFromIndex(myparent);这是索引和后台item的桥。
后两种方式归纳来看,也算是从item入手了,而且推荐都使用Item方式加子行,不然,可能会陷入到后台model和view中的QModelIndex的不同步,那个问题会让你乱套的。
然后,找到了加子行的点,就是要找方法了。
1)item->appendRow(传入item的list);
2)Model->insertRows(0, 1, myparent); // 添加一行,注意参数是QModelIndex,要理解树模型中子节点的索引机制
虽然,model有自己的appendRow函数,但是,加一行是没问题,分层次加子行时还是不行的。
而且,在分别使用item对象和QModelIndex对象的Data()和setData()时要注意,默认的role参数,一个是0,一个是257.这是绝对的坑儿。
不然,你设置了,总感觉设置的数据为空,不显示。role是一个新维度的概念,使用很方便,只要传入和调出控制好了,是一大神器。
resizecolumncontent也是个不错的技巧,可以在你设置了model后重新调用,根据内容适应宽度。
代码有点乱:但可以上两棵树,并且都有子行。

  //测试绑定线路报文内容到树控件
  QList <QStandardItem *> items;
  QList <QStandardItem *> childItems;
  for (int i = 0; i < 4; ++i)
  {
  QStandardItem *item = new QStandardItem( QString (“item L%0” ).arg(i));
  if (0 == i)
  item->setCheckable( true );
  items.push_back(item);
  }
  lineModel->appendRow(items);
  for (int i = 0; i < 4; ++i)
  {
  for (int i = 0; i < 4; ++i)
  {
  QStandardItem *item = new QStandardItem( QString (“L%0” ).arg(i));
  if (0 == i)
  item->setCheckable( true );
  childItems.push_back(item);
  }
  items.at(i)->appendRow(childItems);
  //lineModel->setItem(i, 0, childItems.at(i));
  }
  items.clear();
  childItems.clear();
  int iRow = -1;
  for (int i = 0; i < 4; ++i)
  {
  for (int i = 0; i < 3; ++i)
  {
  QStandardItem *item = new QStandardItem( QString (“item R%0” ).arg(i));
  if (0 == i)
  item->setCheckable( true );
  items.push_back(item);
  }
  //items.at(i)->appendRow(items);
  //normalModel->setItem(i, items.at(0));
  normalModel->appendRow(items);
  items.clear();
  iRow++;
  }
  //方式一,以setdata方式加子行
  //QModelIndex myparent = normalModel->index(iRow,0);
  // //myparent = normalModel->index(0, 0, myparent);
  // normalModel->insertRows(0, 1, myparent); // 添加一行
  // normalModel->insertColumns(0, 3, myparent); // 添加三列
  // ui.treeView_normal->reset();
  // ui.treeView_normal->setModel(normalModel);
  // ui.treeView_normal->update();
  // emit ui.treeView_normal->dataChanged(normalModel->index(0, 0), normalModel->index(0, 3, myparent));
  ////for (int i = 0; i<3; i++)
  ////{
  // QModelIndex index = normalModel->index(0, 0, myparent);
  // normalModel->setData(index, “kk”);
  // ui.treeView_normal->reset();
  // ui.treeView_normal->setModel(normalModel);
  // ui.treeView_normal->update();
  // emit ui.treeView_normal->dataChanged(normalModel->index(0, 0), index);
  // normalModel->insertColumns(0, 1, myparent); // 添加一列
  // index = normalModel->index(0, 1, myparent);
  // normalModel->setData(index, “ll”);
  // emit ui.treeView_normal->dataChanged(normalModel->index(0, 0), index);
  // ui.treeView_normal->update();
  // ui.treeView_normal->setModel(normalModel);
  // normalModel->insertColumns(0, 1, myparent); // 添加一列
  // index = normalModel->index(0, 2, myparent);
  // normalModel->setData(index, “mm”);
  // ui.treeView_normal->setModel(normalModel);
  // ui.treeView_normal->update();
  // //ui.treeView_normal->paintEvent()
  // emit ui.treeView_normal->dataChanged(normalModel->index(0, 0), index);
  // ui.treeView_normal->reset();
  ////}
  //myparent = lineModel->index(0,0);
  //QModelIndex tmp = lineModel->index(0, 0,myparent);
  // ui.treeView_line->setCurrentIndex(tmp);
  //方式二,以model的setitem方式加行
  QModelIndex myparent = normalModel->index(iRow, 0);
  for (int i = 0; i < 3; ++i)
  {
  QStandardItem *item = new QStandardItem( QString (“R%0” ).arg(i));
  if (0 == i)
  item->setCheckable( true );
  childItems.push_back(item);
  }
  //items.at(i)->appendRow(childItems);
  QStandardItem * tmp = normalModel->itemFromIndex(myparent);
  tmp->appendRow(childItems);
  childItems.clear();
  //normalModel->setItem(iRow, 0, childItems.at(0));
  QStandardItem *item = new QStandardItem( QString (“RE%0” ).arg(0));
  childItems.push_back(item);
  item = new QStandardItem ( QString( “RE%0” ).arg(1));
  childItems.push_back(item);
  item = new QStandardItem ( QString( “RE%0” ).arg(2));
  childItems.push_back(item);
  normalModel->appendRow(childItems);

自由行泰国

自由行者干货吐血奉献:
感觉用倒叙的时间串起来可读性高。

行程章节:
健议,6-10天,选2-3地,6天以内,可以专注1城。很多老外一处一呆就是一个月。租车租房租泰妹已成文化,一盘水果一帮朋友喝到深夜。直到出行前,多看穷游攻略,锦囊啥的。没确定机票前,并不需要订太多景点的票和接机出租啥的,前者用app提前一天解决,点对点的接驳在当地解决吧,可以议价嘛。

首先,倒数半年吧,拿护照买亚航票赶打折是必须的,购时要额外去除保险的点选,因为那是默认选中的坑,不要在意big sort的积分,它是事后才积上去的。对于行李和机上餐可按需选择。注意因为是低价机票,所以不包含这些的。
确定了行程,可以细化你每一天的安排了。是一个城市,还是要飞来飞去?由于本人家人5人10天。所以,舍弃了久仰的清迈。因为,考虑到小孩和老人,不能以旅行团一样的安排,所以,曼谷+芭提雅+泰南的苏梅+涛岛,事实证明大家很满意。

曼谷是购物之都,大皇宫父母只呆了不到半小时,就吵着要逛街。所以,在最后两天在曼谷购物,不然,提着大小包去玩可是很辛苦。
芭提雅离曼谷近,大巴2小时,方便随时,并且沿海热闹。并不细说,我老婆最钟爱此地。但并不上岛,因为后面有好戏。
苏梅+岛,四天的深度感受,才能让大家忘记北方的寒冷和帝都的#¥¥%#。

飞前倒数一个半月,去搞定签证,在网上找可信的旅行社带办,一人花费2百多吧。

倒数一周时,换外币,因为换币要提前预约的,不然,很可能白跑一趟,我是在中国银行柜台办理的,据说汇率低。
不用换太多美金,真用不上。甚至不用换。我在华夏卡里存了6K(号称每天第一次取钱免手续费,但好像至少会有50铢会被当地ATM扣)
具体的安排:
华夏存入6K
换美金1K(本人中间有马来西亚的transit,出关玩了半天,所以,其实应该直接换马币)
换泰铢4K
当然,要带信用卡喽

倒数第四天时,下淘宝单,买电话卡,happy-7day卡。虽然,电话功能只用了不超过五次,但随时上网帮了很多的忙。因为,要收发订单邮件的和各种app的使用。7天过期后本人找到服务点,加了两天的上网约110铢

倒数第三天,网上值机,打印登机牌,打印各种订单确认(住宿酒店确认,地址信息等)和地图资源(一般酒店大堂都提供)。把手机的旅行app整理到一个文件夹,下载最新版本,先登陆上所有出游app帐号,以防到时找不到帐号,影响大事。
本人的app介绍如下:(重要程度,由上至下)
google maps
booking.com
面包自由行
穷游
私人邮箱设置
亚航

途牛
携程
蚂蜂窝自由行

前四位很强大,他们会互相配合,这里要赞一下面包。我在面包上订了一个安通海洋公园和一个人妖秀,都是质量很高,前一天下单,第二天享受,当然,要拿确认邮件去享受了。当然有条件的话,可以打印出来。泰国的IT水平不高,找到愿意让你使用的打印机很难的。酒店的服务人员不会同意,因为上网有风险,并且电脑都为公用。而没有像中国一样的打印复印店的。所以,你只能找office了,幸好有好心的人帮助。我转发邮件给他,他打印出来。面包上的景点也都可以关联google导航定位。这样,离的近或打车前去,大可尽在掌握。
再有就是booking.com了,的确专业,对订单反应速度巨快,可以结合苹果的passbook。

文化章节:
喝白酒的人注意,泰国找不到白酒,并且,早餐很难找,因为,上午开店的很少。在寺庙不要吵,也不用交门票。

详细行程一览表:

地点/时间/逗留 源–目标机场 景点 事后总结(有血的教训)
北京/马来西亚 PEK—KUL 马来西亚–双子塔–central park–机场商圈 事实上到了central market玩了半天,吃了个饭。有一个30分钟的快轨klia2直达central.
马来西亚/曼谷 KUL–DMK 体验美食,然后休息 到达天黑了,入住,准备第二天一早出发芭提雅
曼谷/芭提雅 坐BTS至下面站之一:1)victoryment station|胜利纪念碑(阿怒烧瓦里拆)2)E7|曼谷市东站|Ekkamai|Eastern Bus Terminal,2号口出就是东站。注:租用面包车.汽车北站(Mo chit) 四方水上市场另一个响亮名字是杜拉拉水上市场(最好提前网购票)可以坐香蕉船,照相,购物,看表演。中午后人开始多,我们去早了。 事实上,酒店前台安排了前往芭提雅的家庭型车,5人一共2000铢
巴堤雅 原路返曼谷 东芭乐园,室内民俗表演,大象表演,骑大象,旅游车参观等。到当地后订房两晚,200人民币一晚,有游泳池,比较舒适。 在著名的红灯区街walking street的西北部找了个性价比很高的酒店,记往在海滩的外圈找,那里会便宜。吃海鲜,游泳,逛街(晚上去,你懂的)
芭提雅/曼谷 当地订房一晚,19,200人民币一晚 大巴车,坐到离廊曼机场近的站,在那里现找酒店,因为要赶飞机去苏梅,到曼后晚间逛了跳蚤市场,咋都咋(东西很多,但必须狠讲价,比MBK的价水份还大)
苏梅岛/20-22 DMK–NST车船联:大巴–>–
Donsak码头->—
Lipa Noi Pier(苏梅亚航集合地)–>-面包车->-酒店
查汶海滩(Chaweng Beach)、波普海滩(Borphut Beach)、拉迈海滩(Lamai Beach)和湄南海滩(Maenam Beach)。 海岛的房间紧张,所以用booking.com早下手了。海难上很热闹,水果很便宜。用面包app订了安通海洋公园,做快艇,浮潜,皮划艇,自助,实在是印象深刻,非常推荐。
龟岛(TAO)/23-24 nakhon si thammarat(NST) –bangkok-Don mueang(DMK)车船联:
酒店–>–Seatran pier->–Donsak pier–>–大巴->-机场-16:10->-FD3187–>-17:30-
潜水,南苑岛,mahead bea(海滩),购物街很多 岛上出租车很贵,要由酒店前台来叫。并且,按地图规划好下车地和游览路线。由于有孩子,不能去南苑岛和潜水。有几个购物区路线。逛的同时,看到了离岛的码头Seatran pier 那里有亚航的接待点,车船联票的入口。
龟岛/曼谷/24-26 DMK–KUL 大船–7座小巴–飞机 一天用来赶路,做大船不用很颠婆。有钱的可以从苏梅飞。
曼谷/北京 KUL–PEK 唐人街,泰拳,nana街 找到大皇宫附近的宾馆住下,第二天路线是,大皇宫,考山路,王权免税店,MBK,克里索普人妖秀。注意,去王权要拿两样东东,护照(本人全程随身)还有是打折地图(免费领于酒店前台,上面有打折卡的)。买的东东可以在机场退税。还有就是湄南河边的人妖秀了。风景和文化大餐。人妖秀很艺术,每个位子送一种自选饮品。第二天,飞京略

囧点:
1)买了个超标的箱子,只能托运,而又没买20kg的行李托运,在机场又要登机了,结果高价买了托运–600银子。
2)爸有个小军刀,老婆有些化妆品被安检拦了,幸好,有免费的寄存,等回来北京后,从机场拿走。
3)爸妈先抵泰国机场,对于入境卡拒填,他以为那个是落地签,语言又不通,真是难为他们了。 汇合后出了机场,打不到taxi,因为,机场很规范,有专门的打的通道,要排队,就一定有打表的taxi。
4)上了车,老爸习惯的往副驾驶一座,可是,司机就站在旁边,比划了半天,老爸往前一看,原来有方向盘。
5)注意,泰铢纸币的1K和100的特别相近,本人就大方的给了1K的小费。
6)由于经停马来西亚,本人换了马币,可返程时赶飞机,没有消费掉剩下的钱,结果,回国后发现中国银行不能换马币。结果,留做纪念了。还有若干泰铢硬币。

VS2013字符集小结

VS新版本打开旧项目,即当升级一个vcproject文件时,可能会涉及从“多字节字符集”(可能是utf-8)到unicode字符集的转换。
所以总结一下,代码端如何适应转换。

unicode字符集下,微软引入了一个宽字符集的概念(多讨厌)
所以,有些winapi就是以宽字符集来传参的。

第一类问题:messagebox()函数
所以字符串常量前,加一个L,即L“原来的字符串”;
L的意思是小端序。当为unicode时,长度要么1要么2(汉字),所以,再加上小端序,不会有歧义了。

第二类问题:strcpy()函数要求多字符集,事实此时的CSting已经入乡随俗了用了宽字符集,而直接强制转换就会出现让你头大的提示,
居然const char * 和 CString不等价了。

char SendBuf[512] = {0};
strcpy(SendBuf,strEdit); //CString参数strEdit,报错说不能转换CString到const char *
——————————–
办法一:用新的缓冲区放置,并且必须再转换一下。
char SendBuf[512] = {0};
strcpy(SendBuf,( const char *)strEdit.GetBuffer());
办法二:复杂,此时要做的是把“变质的”CString给救回来。

char SendBuf[512] = {0};
wchar_t temp[512];
MultiByteToWideChar(CP_ACP, NULL, (LPCCH)strEdit.GetBuffer(), 512, temp, 512);
strcpy(SendBuf,(const char *)temp);
m_Conn.Send(SendBuf,strlen(SendBuf));

第三类问题,atoi转int:
把atoi换成_ttoi即可,这是神器,在啥字符集下,都可编译。

第四类问题,CString->std::string 举例如下:
CString strMfc=“test“;
std::string strStl;

#ifdef _UNICODE

USES_CONVERSION
strStl=W2A(strMfc.LockBuffer());

strMfc.UnlockBuffer();

#else

strStl = strMfc.GetBuffer(0);

strMfc.ReleaseBuffer();

#endif
—————-
有时,CString可以做为桥梁,把乱码的UTF-8字符串转成string打印正确。思路是先用下面的函数转换乱码,再把返回的CString转string.
CString UTF8toUnicode(const char* utf8Str, UINT length)
{
CString unicodeStr;
unicodeStr = _T(“”);
if (!utf8Str)
return unicodeStr;

if (length == 0)
return unicodeStr;

//转换
WCHAR chr = 0;

for (UINT i = 0; i std::string 举例如下
BSTR bstrTest = ::SysAllocString(L”Test”);

_bstr_t bstr_t(bstrTest);

std::strStl = bstr_t;

SysFreeString(bstrTest );

std::string -> BSTR 举例如下

std::string name = “nisb”;

_bstr_t bstr_t(name.c_str());

BSTR ret_val = bstr_t.GetBSTR();

————————————————-
转来一篇原理编码的原理:

1:使用CString,要包含文件afx.h,比如在Win32 Console Application中Alt+F7选择Use MFC in a Static Liberary,然后再添加#include就可以使用CString了。

2:WCHAR ch = L’中’;与CHAR ch = ’中’;的区别是第一种使用UNICODE编码,第二种方式一般不经常用到,比如:
WCHAR strA [ 2 ] = { L’中’ , 0 } ;//打开VC的Options菜单,选中Debug选项卡中的Display unicode strings后,可以看到strA的值。
WCHAR strB [ 2 ] = { ‘中’ , 0 } ;

CString strC ;

strC+ = ( ( char * ) strB ) [ 1 ] ;
strC+ = ( ( char * ) strB ) [ 0 ] ;//strC==”中”

3:CString的AllocSysString ( )成员函数;可以方便的把一个字符串转换成UNICODE形式。记得使用完该UNICODE字符串后要调用::SysFreeString()函数释放字符串。

4: CString::AllocSysString ( )或者::SysAllocString得到的字符串并不是普通的UNICODE字符串,它之前的四个字节会存放申请的字符串的长度:

CString strD = ”asdf”;
BSTR strD = strC.AllocSysString( ) ;
long i =* ( ( long * ) strD – 1 ) ; // i == 8;一个UNICDE字符的长度是2字节,所以strD的长度为8个字节。

4:UTF-8码转换为一般的字符串:

#include ” Windows.h ”

int main(void)
{
char str [ 256 ] = {( char )0xE4, ( char ) 0xBD, ( char ) 0xA0, ( char ) 0xE5 ,
( char)0xA5 ,(char)0xBD, (char)0x61, (char)0x62 ,(char)0x63,(char)0} ; //一段UTF-8编码
WCHAR* strA;
int i= MultiByteToWideChar ( CP_UTF8 , 0 ,(char*) str ,-1 ,NULL,0);
strA = new WCHAR[i];
MultiByteToWideChar ( CP_UTF8 , 0 ,( char * ) str, -1, strA , i );
i= WideCharToMultiByte(CP_ACP,0,strA,-1,NULL,0,NULL,NULL);
char *strB=new char[i];
WideCharToMultiByte (CP_ACP,0,strA,-1,strB,i,NULL,NULL);
//strB即为所求
delete []strA;
delete []strB;
return 0;
}

5:在转换方面_bstr_t是最最灵活的,他提供了UNICODE到一般字符串的直接转换:
#include
_bstr_t strA;
char *strB=”中国人”;
strA=strB;
WCHAR *strC=strA;
long i =* ( ( long * ) strC – 1 ) ;// i 亦是字符串的字节长度
char *strD=strA;
return 0;

宽窄字串转换!
两种方法:1、CString 2、_bstr_t

#include “comutil.h”
//注意在Project-》Setting-》Link中加入comsupp.lib,从而使_bstr_t可用

void CAaaDlg::OnButton1()
{
// TODO: Add extra cleanup here
_bstr_t a(L”sdfsafds”);
a+=”zzz”;
char * b = (char *)a;//获得内部BSTR的char*指针,勿做修改和释放
WCHAR *c=(WCHAR *)a;//获得内部BSTR的WCHARr*指针,勿做修改和释放
CString p = L”asdfsa”;
p+=”ppp”;
WCHAR *y =p.AllocSysString(); //获得WCHAR*指针,使用完请释放,否则有内存泄漏。
char *z = p.GetBuffer(p.GetLength()+1);//内部Buffer指针,z不要释放

::SysFreeString(y);
}

.net应用odp.net小记

一,下载ODAC112040Xcopy_64bit并解压,在OTP里找。
在cmd中执行>install.bat odp.net4 d:\driver4oracle11.2 odac

odp.net4————你想部署的driver,本人使用.netframework4,不是asp.net和.net2,所以,没用使用All和指定的其它选项。
d:\driver4oracle11.2————你要部署的目标客户机的oracle_home,当然在windows下就加入它到系统环境变量path中。
odac————当在同目录有多个driver时,可以区别吧,反正,因为加了它,可能会报错。但不影响使用。
[true]———-可选的,默认值,即把odp.net依赖的instantclient安装,当你加false时,不装依赖且考虑和已经存在的新版本oracle或现有的环境配合。

当执行了上面的命令后,instantclient(即被odp.net依赖的)也一并从压缩包中被抽取,拷安装到了oracle_home目录中。

二,然后就是设置tnsnames.ora文件。从服务端上相应位置拷过来,放置到home目录中。顺便执行下*access.dll同目录中的oraprovcfg.exe,它是用于注册系统环境变量的。虽然上面已经配置好了,多来一次也无妨。

三,开始客户端程序的开发吧,把home路径中的Oracle.DataAccess.dll拷到项目的debug,和exe同级下面,并在VS中引用,加入using行:
using Oracle.DataAccess.Client;
using Oracle.DataAccess.Types;
代码示例:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Oracle.DataAccess.Client;
using Oracle.DataAccess.Types;

namespace odp
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();

}

private string strConn = “Data Source=(DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = ohala-PC)(PORT = 1521))(CONNECT_DATA = (SERVER = DEDICATED)(SERVICE_NAME = XE)));”+
“User id=JINGHU;Password=JINGHU;” ;
public void initDBConn()
{
try
{
using(OracleConnection objConn = new OracleConnection(strConn))
{
objConn.Open();
string strSQL = “select * from V_TM_SEGMENT_CFG where SEGMENT_CODE=10 order by STATION_SEQUENCE,TRACK_CODE”;

using(OracleDataAdapter objAdapter = new OracleDataAdapter(strSQL,objConn))
{
//
DataSet ds = new DataSet();
objAdapter.Fill(ds);
dataGridView1.DataSource = ds.Tables[0];
//dataGridView1.
dataGridView1.Show();
}

//using (OracleCommand objCommand = new OracleCommand(strSQL, objConn))
//{
// using(OracleDataReader objReader = objCommand.ExecuteReader())
// {
// while (objReader.Read())
// {
// Console.WriteLine(“segment_code is :” + objReader[0].ToString() + “;station_code is :” + objReader[1].ToString());
// //dataGridView1.DataSource
// }

// }
//}//command
}
} catch(Exception ex)
{

}
}

private void button1_Click(object sender, EventArgs e)
{
initDBConn();
}
}
}

升级win10备忘

首先,接手电脑为win8.1,高兴去在线升级结果发现将会升级成win10家庭版,果断拒绝换路。
然后,策略再选择成把win8.1变成专业版,再online升级,如果再不行,就使用ISO了,( VK7JG-NPHTM-C97JM-9MPGT-3V66T)win10密钥吧。

1)升8再升10
保守治疗先,继续玩win8.1,右键“这台电脑”,在系统属性界面,选 择“获取新版本的Windows的更多功能”或者在控制面板中应该不难找到“向windows8.1添加功能”,然后,又是要输入产品密钥。
在这一步输入专业版的零售密钥,如果是升级到win8专业版,就输入8GDW2-NHD3Y-C79G4-B82C4-6Q4DH,(用的这个)
如果是升级到win8.1专业版,就输入 29NQY-3TDJ2-CPXXD-CHDMY-CWD2Y。
然后,漫长的等待windows update进度。注意,要确认本机是已经被激活的不然会升级不成功,并且是最后才给你结果,说不成功。当然如果是激活的,那么就关闭360,再重启。(本人采用方式)

2)ISO升10
直接点击ISO,win10不用虚拟光驱了,又一群要下岗的同行。但这样安装上的win10可能会出现问题。

3)ISO装10(或者用老毛桃啥的做个U盘,引导安装)
过程中选择不保留原有应用和个人文件夹等,那就没有以前版本的windows,回退都没有路子。

程序员的自我修养

四大神器,解决依赖:

ldd是用来查看执行文件或.a,.so的依赖关系利器(从链接的角度)。
nm———————查看静态符号表,观察依赖关系
-sD *.so
objdump -p t_sql.o | grep NEEDED

库命令:
file *.o—————看ELF信息
objdump -[看列表] *.o——看目标文件的结构和内容
基本信息(-h)
更多信息(-x)
依赖信息(-p)objdump -p t_sql.o | grep NEEDED

动态链接的可执行文件中包括got,有时有调用别模块时的共享对象也存在此段。

查看一个so是否PIC(地址无关性)编译的:
readelf -d .so | grep TEXTREL
如果有输出,用的是装载时重定位(虽多进程调用可以,但牺牲了效率),否则,证明编译时加了-fPIC,是地址无关。

readelf—————-看elf详细信息,包括(系统位,大小端,是否可执行)
文件头信息(-h)
详细的信息(-S)较权威的段表信息
从linker角度来查看链接器使用的dynamic段的信息(-d *.so)链接库的elf信息,同于ldd(宏观模块体现)。
-sD *.so查看动态符号表(从库提供服务或使用的角度),针对段.dynsym观察依赖关系
-l ../bin/devcomm | grep interpreter(链接器使用的段)查看生成它的链接器(可执行文件)
-r *.so查看重定向符号表

链接的秘密:

目标文件静态重定向—动态链接文件重定向——可执行动态链接文件重定向
rel.text——————rel.dyn———–针对数据引用,修正位于数据段中的got(全局变量的引用地址)
rel.data——————rel.plt————针对函数引用,修正got.plt

全局符号表

二元信号量:

信号量(多元):

互斥量:不同于二元信号量:哪线程存得,哪线程释放
相同二元信号量:都是约束线程排队的

临界区:在一点处与互斥量不同:其它进程不可见。(和内核对象名称不太相符)

条件变量:同时阻塞和唤醒多个线程

静态编译Qt5.5并应用成果

一直为打包Qt开发的东东依赖库发愁。只好研究下静态编译,当然选个最新的版本。
环境如下:
win7 x86
VS2012
perl5.16.2
python34(32bit)
ruby21
Qt5addin1.2.4

说明:ruby安装时要把三个都选择上,QT5addin插件安装要特有耐心,不然总会觉得,程序假死了。(后来发现是装集成help文档时占时间,可以不装它的)

以上安装在一个独立的虚机,方便以后改造,重要的一点是,一编译就2-3个小时,你对着屏发呆嘛?
下载Qt5.5的源码,进入其目录,需要改的有两处:
<src目录>\qtbase\mkspecs\win32-msvc2012\qmake.conf.

将以下三处 -MD修改为 -MT

QMAKE_CFLAGS_RELEASE = -O2 -MT
QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO += -O2 -MT -Zi
QMAKE_CFLAGS_DEBUG = -Zi -MTd
当环境不同,聪明的你会找到需要更改的位置。5.5源码包是mkspecs/comon/msvc-desktop.conf里面改。

建立个批处理文件,如vs2012.build.bat
内容如下:

::配置路径
set QT5_DIR=C:\qt_tool\qt-everywhere-opensource-src-5.5.0-alpha
set THIRDPARTY_DIR=C:\qt_tool\Build
::如果您用mingw可以在这儿设置下您的mingw目录
set PATH=%PATH%;C:\Perl\site\bin;C:\Perl\bin;C:\Python34;C:\Ruby21\bin;
set PATH=%PATH%;%QT5_DIR%\bin;%QT5_DIR%\qtbase\bin;%QT5_DIR%\gnuwin32\bin;

::配置依赖,mingw的可能需要您手动加上库和头文件位置,vs的话您可以打开相应的VS* X86/64 本机命令提示符
::set SQLITE3SRCDIR=%THIRDPARTY_DIR%\sqlite
::set LIB=%LIB%;%THIRDPARTY_DIR%\icu\win32\lib;%THIRDPARTY_DIR%\icu\win32\libs;%THIRDPARTY_DIR%\openssl\openssl32\lib
::set INCLUDE=%INCLUDE%;%THIRDPARTY_DIR%\icu\win32\include;%THIRDPARTY_DIR%\openssl\openssl32\include
::set PATH=%PATH%;%THIRDPARTY_DIR%\icu\win32\bin;%THIRDPARTY_DIR%\openssl\openssl32\bin

::配置QT,为了在输入configure配置qt编译选项,我就直接写到bat了、、、
cd %QT5_DIR%
configure -prefix C:\QtSdk\Win32_static -opensource -confirm-license -static -platform win32-msvc2012 -release -c++11 -qt-sql-sqlite -qt-zlib -qt-libpng -qt-libjpeg -qt-freetype -no-angle -no-icu -opengl desktop -nomake examples -nomake tests -no-compile-examples -skip qtwebkit
把它保存。不提倡改那个bat文件,因为,webkit是不能静态编译的,并且它很耗时,并且很多选项都是经验之谈。
然后,找nmake去。在开始菜单里找”vs2012 x86本机工具命令指示行“,
打开,进入源码目录,执行批处理。

你的环境一致,定能configure过。注意,要清除前一次的垃圾,需要用nmake distclean
后面的事就是敲nmake,泡杯茶了。

有时,你真的nmake成功了,但是不一定能nmake install正常。但我坚信install只是一系列拷贝操作。你要的那些lib已经OK了,你可以部署的时候再用他们。

当然,你可以坚持找原因,nmake install成功。

注意,不要轻易改变源码的位置,或节省空间删除它。否则,上帝保佑你。

后记:
以为装了Qt5addin,打开就可以看到Qt5的菜单,错了,还要真的装个Qt sdk才行。
Qtcreator静态编译了一下,的确可用,但是无法部署到同为32的xp下。可能是因为,Qt使用的编译器仍然是VS2012的,所以,再用VS2012+Qt5addin试一次,何况这是我们目标。
不过,我发现一个坑,Qt5addin1.2.4根本和VS2012不兼容,而且这不会提示你。
1.2.3装后,开始真正的应用静态编译的成果了。

项目设置:

为了让exe能跑在xp上,需要设置在工程—-属性—配置属性–常规–平台工具集v110_xp

因为,我编译的lib都是realse的,所以把项目设成realse
改成(release为MT,debug为MTD)
在工程—-属性—配置属性—c/c++—代码生成—-运行库
选择为“多线程(/MT)”
这样设置可能是约定了对lib的调用方式。
否则,编译时报错:runtimelibrary
error LNK2038: 检测到“RuntimeLibrary”的不匹配项: 值“MT_StaticRelease”不匹配值“MD_DynamicRelease”

在工程—-属性—配置属性—链接器
本人的附加依赖项(备忘):$(QTDIR)\lib\Qt5Core.lib;$(QTDIR)\lib\Qt5Gui.lib;$(QTDIR)\lib\qtmain.lib;$(QTDIR)\lib\Qt5Widgets.lib;$(QTDIR)\plugins\platforms\qwindows.lib;$(QTDIR)\lib\Qt5PlatformSupport.lib;$(QTDIR)\plugins\platforms\qminimal.lib;$(QTDIR)\plugins\platforms\qoffscreen.lib;$(QTDIR)\lib\Qt5OpenGL.lib;$(QTDIR)\lib\Qt5OpenGLExtensions.lib;$(QTDIR)\lib\Qt5Sql.lib;winspool.lib;shlwapi.lib;rpcrt4.lib;$(QTDIR)\plugins\imageformats\qico.lib;$(QTDIR)\plugins\imageformats\qsvg.lib;$(QTDIR)\lib\Qt5Qml.lib;$(QTDIR)\lib\Qt5Quick.lib;comdlg32.lib;oleaut32.lib;imm32.lib;winmm.lib;glu32.lib;opengl32.lib;gdi32.lib;$(QTDIR)\lib\qtharfbuzzng.lib;kernel32.lib;user32.lib;shell32.lib;uuid.lib;ole32.lib;advapi32.lib;ws2_32.lib;mpr.lib;%(AdditionalDependencies)

上面配置解决了一个ub_buffer_create……destroy啥的编译错误。

QT5设置:
VS中设置好Qt versions为静态的sdk,然后在Qt project setting—–properties页的最后一个设置上。
即version属性选择下拉中的静态sdk(有时忘记它,其实主要开关在这里)

最后构建你的程序吧。不过还是有坑的。虽然没有报error了,但当你运行它会提示你:
……Failed to load platform plugin windows……

这次改main.cpp吧

#include
Q_IMPORT_PLUGIN (QWindowsIntegrationPlugin);

编译通过,这次把exe放到没有Qt5安装的xp下,都如愿运行,出画面了。

大胆的写Qt吧,一次编写,到处部署(很方便)