完美主义

QQ:418104681 上帝要你死在追求完美的道路上

置顶随笔

为了更好地学习交流C++技术,虎子同学创建了CPP茶馆,欢迎大家聊天发贴

QQ群一号:35660860
QQ群二号:40790936

点这里:CPP茶馆总论坛

@英语已经不仅仅是一门语言,它可以改变一个人的视野。
************************************************************
目录与摘要
************************************************************
################
常用库的学习使用
################

1.[STL学习摘要之序列式容器]

##########
Project
##########
1.[俄罗斯方块][未完善]

2.[俄罗斯方块V1.0]

3.[俄罗斯方块V1.2]

3.[MD5计算工具]

4.[BMP位图操作类][基于LSB的数字图像水印]

#######
x86ASM
#######
1.[汇编学习测试例子]

#######
Tips:
#######
1.[GCC编译选项和GDB的使用

2.[如何自己写Win32控件 ]

3.[typedef用法小结] 
*************************************************************

posted @ 2008-09-15 09:03 沈臻豪(foxtail) 阅读(91) | 评论 (0)编辑 收藏

2008年11月16日

  继续上个版本修改了一些bug,然后美化了一下。

发现自己的审美观不咋的,俺觉得漂亮的人家觉得不漂亮。还是照着大家要求的画一个。

主要解决的问题是,这次行列都用宏表示,这样可以修改行列,窗口大小也动态改变。

另外长条旋转变成Z型问题也解决,主要是取模的时候绕回去了。

其中最重要的要算是解决了刷新闪烁问题,尽管HAM2008指点过,始终没做成,这次vczh说了一句话就点醒了我。根本不应该使用InvalidateRect函数,直接画,然后用缓冲DC就可以了。

VOID OnPaint()
{
    HDC hdc 
= GetDC(hWnd);
    HDC bitmap_dc 
= CreateCompatibleDC(hdc);
    HBITMAP bitmap 
= CreateCompatibleBitmap(hdc,1024,768);
    SelectObject(bitmap_dc,bitmap);
    
   
/********************************************
   DrawBlock
   ********************************************
*/

   
int x = tetris.GetX();
   
int y = tetris.GetY();

   
for(int i=0; i<4++i)
   
{
       
for(int j=0; j<4++j)
       
{
           
if(current_block[i][j] == 1)
           
{
               DrawBlock(bitmap_dc,y
+i+1,x+j+1,3,3,tetris.GetColor(),RGB(0,0,0));
           }

       }

   }


   
/*****************************************
   *DrawContainer
   *****************************************
*/

   
for(int i=0; i<ROWS; ++i)
   
{
       
for(int j=0; j<COLS; ++j)
       
{
           
if(Container[i][j] == 1)
           
{
               DrawBlock(bitmap_dc,i
+1,j+1,3,3,ColorTable[i][j],RGB(0,0,0));
           }

       }

   }


   BitBlt(hdc,
0,0,1024,768,bitmap_dc,0,0,SRCCOPY);
   DeleteDC(bitmap_dc);
   DeleteObject(bitmap);
   ReleaseDC(hWnd,hdc);
}

以上就是GDI缓冲的主要实现代码。


可执行文件下载
代码还是等全部完善后上传吧。Redist请自行下载。
代码估计要有大的改动,感觉现在的代码没一点C++的味道。
有点简单,用陈坤的话说就是扩展性不好。
posted @ 2008-11-16 00:22 沈臻豪(foxtail) 阅读(58) | 评论 (0)编辑 收藏

2008年11月9日

 

记得8月份写过俄罗斯方块,那会全是用坐标表示的。包括所有方块的变换,甚至方块的表示。导致程序内部许多的case语句,甚为麻烦。代码量也有近1800行左右。而且写完后bug很多,修正也修正不完,异常头痛便放弃了。

现在看看《编程之美》的俄罗斯方块的思路,又想起vczh用脚本的写的俄罗斯方块,就又起了兴趣。便重新设计完成了,这次基本没什么bug了。只不过操作习惯上和QQ的俄罗斯方块还有些不同。

1.       在底部的时候,如果按住旋转不放,则会停留原地旋转。原因是为了检测接触底部时旋转不插入墙壁,就同接触左右墙壁一样,做了调整方块坐标处理。处理方法是根据旋转后方块的坐标加上(减去)最大列(最小列)在减去(左)右边界得到。底部也是这样计算的。当然有了这样的检测便出现了这样的小小的bug,不过我相信没人会在底部按住不放的。

2.       这次方块全部存储在一个一维数组中,通过指针的变换来改变方块种类与旋转状态,但是为了方便操作,就拷贝到了一个二维数组中。起初设计是一个四维数组,这样就方便多了,但是VS2008的编译器却不能编译通过,int[4][4]int **p的转换不成功,朋友说是编译器问题。后来经Lend3d说,很多项目都是不用大于二维的数组的,于是干脆就用了一维数组,本来要听从他意见用结构表示一个低二位的数组元素,但是初始化和使用都不是很方便。

3.       另外关于GDI缓冲,试用了一下,但是作用貌似不大,不知道原因。关于这方面的知识援助还是要感谢HAM2008的帮助。



贴个头文件出来就可以知道大致做法了。
#ifndef TETRIS_H
#define TETRIS_H

#pragma once

extern int Container[18][10];//容纳方块的空间
extern int current_block[4][4];

/****************************
* 方块的主要行为
****************************
*/

class Tetris
{
public:
    Tetris();
    
~Tetris();
    
void GenerateBlock();
    
void StepLeft();
    
void StepRight();
    
void StepDown();
    
void Rotate();
    
void CaculateScore();
    
void IsOver();
public:
    
bool lost;
    
int score;//得分
    int GetX();
    
int GetY();
private:
    inline 
int CaculateMinCol();
    inline 
int CaculateMinRow();
    inline 
int CaculateMaxCol();
    inline 
int CaculateMaxRow();

    
void CaculateBlockBoundary();
    
bool DetectCollision();
    
void CopyToContainer();
    
void CopyToBlock();

    
int *block;
    
int total_rotate;
    
int kind;

    
int offset_x;
    
int offset_y;

    
int min_col,max_col;
    
int min_row,max_row;
}
;

#endif //TETRIS_H

可能自己设计上的能力还是不足吧,有些函数是不得以写的,比如四个inline函数,因为计算的时候用的是四个循环,计算完就要跳出两层循环。
难道用goto,如果直接return则后面的代码执行不到了,不得以做了四个辅助函数。

源代码下载:TetrisV1.0
可执行文件下载:TetrisV1.0.exe 如果不能运行可到微软下载VS2008的 redist_x86
posted @ 2008-11-09 00:06 沈臻豪(foxtail) 阅读(84) | 评论 (2)编辑 收藏

2008年10月26日

C++博客上的蚂蚁终结者的文章都写的不错,它写了个MD5的算法,我就用他的算法写了个小程序。
简单的计算文件的MD5,支持拖拽文件。现在还只是简单的计算。
目前打算改进的是
1添加进度条。
2美化界面。
3解决大文件计算时界面僵死问题。

个人写程序喜欢不断改进,也就是偶然突发奇想写个程序。以后想起来就改进一下。嘎嘎。
要是忘记了,就作罢。代码可点击这里下载

posted @ 2008-10-26 01:50 沈臻豪(foxtail) 阅读(66) | 评论 (0)编辑 收藏

2008年10月3日

脑袋里没有点API的储量,想写什么东西还是很困难的。厚积薄发才是硬道理。所以先看看别人的代码,偷学几个API的用法。

SetClipData proc lpData:LPSTR,dwSize:dword
    LOCAL    hMem:HANDLE ;
==>内存块句柄
    LOCAL    pMem:dword  ;
==>内存块指针

    mov        eax,dwSize
    shr        eax,
3
    inc        eax
    shl        eax,
3 ;==>(dwSize/8 + 1)*8 不满8的倍数则补全
    invoke xGlobalAlloc, GHND or GMEM_DDESHARE, eax
    test    eax,eax       ;
==>申请成功则继续否则跳转到@exit2
    je        @exit2
    mov        hMem,eax
    invoke GlobalLock,eax    ;hGlob ;
==>锁定申请的内存块返回内存块指针
    test    eax,eax
    je        @exit1
    mov        pMem,eax
    invoke RtlMoveMemory,eax,lpData,dwSize  ;
==>复制lpData的内容到申请的内存块中
    mov        eax,pMem
    add        eax,dwSize
    mov        
byte ptr [eax],0 ;==>在内存块最后添0结束
    invoke GlobalUnlock,hMem ;
==>解锁,使内存块指针无效
    invoke OpenClipboard,NULL
    .
if eax
        invoke EmptyClipboard
        invoke SetClipboardData,CF_TEXT,hMem ;
==>将数据关联到剪贴板
        invoke CloseClipboard
        xor        eax,eax        ;
0 - Ok
        jmp        @exit3
    .endif
  @exit1:
    invoke  GlobalFree, hMem ;
==>未锁定成功则释放该内存块
    xor     eax, eax
  @exit2:
    dec     eax          ; 
-1 - error
  @exit3:
    ret

SetClipData endp

看完这段代码我有一个疑问,这里是将lpData的数据拷贝到一个内存块,然后与剪贴板关联,我这里解释为关联,我就认为剪贴板不应该是一个内存区域,我猜测是一个链表之类的结构,然后链表每一个节点存储一个内存区域的指针还有其他的信息,然后根据信息来管理。

否则应该可以直接将lpData来跟剪贴板关联。另一个原因是lpData是局部的随时会被释放的。如有不正确还望指正。

posted @ 2008-10-03 16:27 沈臻豪(foxtail) 阅读(67) | 评论 (1)编辑 收藏

2008年10月2日

通常我们在调用DLL时所需的DLL文件必须位于以下三个目录之一:
  (1)Windows的系统目录:\windows\system;
  (2)DOS中path所指出的任何目录;
  (3)程序所在的目录。
  一、动态链接库的结构

  动态链接库中定义有两种函数:导出函数(export function)和内部函数(internal function),
导出函数可以被其它模块调用,内部函数只能在库内部使用。我们在用C++定制动态库文件时,
需要编写的就是包含导出函数表的模块定义文件(.DEF)和实现导出函数功能的C++文件。下面以
Sample.dll为例介绍DEF文件和实现文件的结构。
  1.模块定义文件(.DEF)是一个或多个用于描述DLL属性的模块语句组成的文本文件,每个DEF文
件至少必须包含以下模块定义语句:
  ·第一个语句必须是LIBRARY语句,指出DLL的名字;
  ·EXPORTS语句列出被导出函数的名字;
  ·可以使用DESCRIPTION语句描述DLL的用途(此句可选);
  ·";"对一行进行注释(可选)。
  2.实现文件
  实现入口表函数的cpp文件中,包含DLL入口点处理的API函数和导出函数的代码。
  二、创建Sample.dll
   1.首先创建Sample.dll的工程,启动VC++5.0按以下步骤生成DLL工程:
  ·在选单中选择File\New\Project;
  ·在工程列表中选择Win32 Dynamic-Link Library;
  ·在Project Name中输入工程名:Sample;
  ·单击Location右边按钮,选择c:\sample目录;
  ·单击OK完成,至此已创建了Sample.dll的工程文件。
  2.创建Sample.def文件:
  ·在选单中选择File\New\Text File;
  ·输入以下代码后保存文件名"Sample.def":
   ;Sample.def
   ;指出DLL的名字Sample,链接器将这个名字放到DLL导入库中
   LIBRARY Sample
   ;定义导出函数ShowMe()为例

   EXPORTS
   ShowMe
   ;def文件结束
  3.创建Sample.cpp
   .在选单中选择File\New\C++ Source File项
   .输入以下代码后保存文件名"Sample.cpp"
   //Sample.cpp
   #include 〈windows.h〉
   int ShowMe(void);
   //DllEntryPoint为DLL入口点函数,负责初试化并终止DLL
   BOOL WINAPI DllEntryPoint(HINSTANCE hDLL,DWORD dwReason,LPVOID Reserved)
   { switch(dwReason)
   { case DLL-PROCESS-ATTACH:
   { break; }
   case DLL-PROCESS-DETACH:
   { break; } }
   return TRUE; }
   int ShowMe(void)
   { //蜂鸣器响一下
   MessageBeep((WORD)-1);
   MessageBox("你好!");
   return 1; }
  4.编译DLL文件
  从Build选单中选择Build Sample.DLL,产生Sample.DLL文件,以后就可以随时调用了。
  三、在应用程序中调用DLL文件
  在应用程序中要首先装入DLL后才能调用导出表中的函数,例如用MFC创建基于对话框的工
程Test,并在对话框上放置"Load"按钮,你就必须添加装载代码。
  1.首先在TestDlg.cpp的首部添加变量设置代码:
  //设置全局变量gLibSample用于存储DLL句柄
  HINSTANCE gLibSample=NULL;
  //第二个变量ShowMe是指向DLL库中ShowMe()函数的指针
  typedef int( SHOWME)(void);

  SHOWME ShowMe;
  2.利用ClassWizard为"Load"按钮添加装载DLL的代码:
  Void CTestDlg::OnLoadButton()
  { //要添加的代码如下
   if(gLibMyDLL!=NULL)
   { MessageBox("The Sample.DLL has already been load.");
   return; }
   //装载Sample.dll,未加路径,将在三个默认路径中寻找
   gLibSample=LoadLibrary("SAMPLE.DLL");
   //返回DLL中ShowMe()函数的地址
   ShowMe=(SHOWME)GetProcAddress(gLibSample,"ShowMe"); }
  3.只要DLL装载成功,在应用程序中就可以直接调用ShowMe()函数(本程序在Windows 95,VC++5.0中运行通过)。

posted @ 2008-10-02 23:19 沈臻豪(foxtail) 阅读(81) | 评论 (0)编辑 收藏

2008年9月29日

“又是一年毕业时”,看到一批批学子离开人生的象牙塔,走上各自的工作岗位;想想自己也曾经意气风发、踌躇满志,不觉感叹万千……本文是自己工作6年的经历沉淀或者经验提炼,希望对所有的软件工程师们有所帮助,早日实现自己的人生目标。本文主要是关于软件开发人员如何提高自己的软件专业技术方面的具体建议。

  1、 分享第一条经验:“学历代表过去、能力代表现在、学习力代表未来。”其实这是一个来自国外教育领域的一个研究结果。相信工作过几年、十几年的朋友对这个道理有些体会吧。但我相信这一点也很重要:“重要的道理明白太晚将抱憾终生!”所以放在每一条,让刚刚毕业的朋友们早点看到哈!

  2、 一定要确定自己的发展方向,并为此目的制定可行的计划。不要说什么,“我刚毕业,还不知道将来可能做什么?”,“跟着感觉走,先做做看”。因为,这样的观点会通过你的潜意识去暗示你的行为无所事事、碌碌无为。一直做技术,将来成为专家级人物?向管理方向走,成为职业经理人?先熟悉行业和领域,将来自立门户?还是先在行业里面混混,过几年转行做点别的?这很重要,它将决定你近几年、十年内“做什么事情才是在做正确的事情!”。

  3、 软件开发团队中,技术不是万能的,但没有技术是万万不能的!在技术型团队中,技术与人品同等重要,当然长相也比较重要哈,尤其在MM比较多的团队中。在软件项目团队中,技术水平是受人重视和尊重的重要砝码。无论你是做管理、系统分析、设计、编码,还是产品管理、测试、文档、实施、维护,多少你都要有技术基础。算我孤陋寡闻,我还真没有亲眼看到过一个外行带领一个软件开发团队成功地完成过软件开发项目,哪怕就一个,也没有看到。倒是曾经看到过一个“高学历的牛人”(非技术型)带一堆人做完过一个项目,项目交付的第二天,项目组成员扔下一句“再也受不了啦!”四分五裂、各奔东西。那个项目的“成功度”大家可想而知了。

  4、 详细制定自己软件开发专业知识学习计划,并注意及时修正和调整(软件开发技术变化实在太快)。请牢记:“如果一个软件开发人员在1、2年内都没有更新过自己的知识,那么,其实他已经不再属于这个行业了。”不要告诉自己没有时间。来自时间管理领域的著名的“三八原则”告诫我们:另外的那8小时如何使用将决定你的人生成败!本人自毕业以来,平均每天实际学习时间超过2小时。

  5、 书籍是人类进步的阶梯,对软件开发人员尤其如此。书籍是学习知识的最有效途径,不要过多地指望在工作中能遇到“世外高人”,并不厌其烦地教你。对于花钱买书,我个人经验是:千万别买国内那帮人出的书!我买的那些家伙出的书,!00%全部后悔了,无一本例外。更气愤的是,这些书在二手市场的地摊上都很难卖掉。“拥有书籍并不表示拥有知识;拥有知识并不表示拥有技能;拥有技能并不表示拥有文化;拥有文化并不表示拥有智慧。”只有将书本变成的自己智慧,才算是真正拥有了它。

  6、 不要仅局限于对某项技术的表面使用上,哪怕你只是偶尔用一、二次。“对任何事物不究就里”是任何行业的工程师所不应该具备的素质。开发Windows应用程序,看看Windows程序的设计、加载、执行原理,分析一下PE文件格式,试试用SDK开发从头开发一个Windows应用程序;用VC++、Delphi、Java、.Net开发应用程序,花时间去研究一下MFC、VCL、J2EE、.Net它们框架设计或者源码;除了会用J2EE、JBoss、Spring、Hibernate等等优秀的开源产品或者框架,抽空看看大师们是如何抽象、分析、设计和实现那些类似问题的通用解决方案的。试着这样做做,你以后的工作将会少遇到一些让你不明就里、一头雾水的问题,因为,很多东西你“知其然且知其所以然”!

  7、 在一种语言上编程,但别为其束缚了思想。“代码大全”中说:“深入一门语言编程,不要浮于表面”。深入一门语言开发还远远不足,任何编程语言的存在都有其自身的理由,所以也没有哪门语言是“包治百病”的“灵丹妙药”。编程语言对开发人员解决具体问题的思路和方式的影响与束缚的例子俯拾皆是。我的经验是:用面对对象工具开发某些关键模块时,为什么不可以借鉴C、C51、汇编的模块化封装方式?用传统的桌面开发工具(目前主要有VC++、Delphi)进行系统体统结构设计时,为什么不可以参考来自Java社区的IoC、AOP设计思想,甚至借鉴像Spring、Hibernate、JBoss等等优秀的开源框架?在进行类似于实时通信、数据采集等功能的设计、实现时,为什么不可以引用来自实时系统、嵌入式系统的优秀的体系框架与模式?为什么一切都必须以个人、团队在当然开发语言上的传统或者经验来解决问题???“他山之石、可以攻玉”。

  8、 养成总结与反思的习惯,并有意识地提炼日常工作成果,形成自己的个人源码库、解决某类问题的通用系统体系结构、甚至进化为框架。众所周知,对软件开发人员而言,有、无经验的一个显著区别是:无经验者完成任何任务时都从头开始,而有经验者往往通过重组自己的可复用模块、类库来解决问题(其实这个结论不应该被局限在软件开发领域、可以延伸到很多方面)。这并不是说,所有可复用的东西都必须自己实现,别人成熟的通过测试的成果也可以收集、整理、集成到自己的知识库中。但是,最好还是自己实现,这样没有知识产权、版权等问题,关键是自己实现后能真正掌握这个知识点,拥有这个技能。

  9、 理论与实践并重,内外双修。工程师的内涵是:以工程师的眼光观察、分析事物和世界。一个合格的软件工程师,是真正理解了软件产品的本质及软件产品研发的思想精髓的人(个人观点、欢迎探讨)。掌握软件开发语言、应用语言工具解决工作中的具体问题、完成目标任务是软件工程师的主要工作,但从软件工程师这个角度来看,这只是外在的东西,并非重要的、本质的工作。学习、掌握软件产品开发理论知识、软件开发方法论,并在实践中理解、应用软件产品的分析、设计、实现思想来解决具体的软件产品研发问题,才是真正的软件工程师的工作。站在成熟理论与可靠方法论的高度思考、分析、解决问题,并在具体实践中验证和修正这些思想与方式,最终形成自己的理论体系和实用方法论。

  10、心态有多开放,视野就有多开阔。不要抱着自己的技术和成果,等到它们都已经过时变成垃圾了,才拿出来丢人现眼。请及时发布自己的研究成果:开发的产品、有创意的设计或代码,公布出来让大家交流或者使用,你的成果才有进化和升华的机会。想想自己2000年间开发的那些Windows系统工具,5、6年之后的今天,还是那个样子,今天流行的好多Windows系统工具都比自己的晚,但进化得很好,且有那么多用户在使用。并且,不要保守自己的技术和思想,尽可能地与人交流与分享,或者传授给开发团队的成员。“与人交换苹果之后,每个人还是只有一个苹果;但交换思想之后,每个人都拥有两种思想”,道理大家都懂,但有多少人真正能做到呢?

  11、尽量参加开源项目的开发、或者与朋友共同研制一些自己的产品,千万不要因为没有钱赚而不做。网络早已不再只是“虚拟世界”,网上有很多的开源项目、合作开发项目、外包项目,这都是涉猎工作以外的知识的绝好机会,并且能够结识更广的人缘。不要因为工作是做ERP,就不去学习和了解嵌入式、实时、通信、网络等方面的技术,反过来也是一样。如果当他别人拿着合同找你合作,你却这也不会,那也不熟时,你将后悔莫及。

  12、书到用时方恨少,不要将自己的知识面仅仅局限于技术方面。诺贝尔经济学奖得主西蒙教授的研究结果表明: “对于一个有一定基础的人来说,他只要真正肯下功夫,在6个月内就可以掌握任何一门学问。”教育心理学界为感谢西蒙教授的研究成果,故命名为西蒙学习法。可见,掌握一门陌生的学问远远没有想想的那么高难、深奥。多方吸取、广泛涉猎。极力夯实自己的影响圈、尽量扩大自己的关注圈。财务、经济、税务、管理等等知识,有空花时间看看,韬光养晦、未雨绸缪。

  13、本文的总结与反思:

  A:不要去做技术上的高手,除非你的目标如此。虽然本文是关于提高软件开发知识的建议,做技术的高手是我一向都不赞同的。你可以提高自己的专业知识,但能胜任工作即止。

  B:提高软件知识和技术只是问题的表面,本质是要提高自己认识问题、分析问题、解决问题的思想高度。软件专业知识的很多方法和原理,可以很容易地延伸、应用到生活的其它方面。

  C:在能胜任工作的基础上,立即去涉猎其它领域的专业知识,丰富自己的知识体系、提高自己的综合素质,尤其是那些目标不在技术方面的朋友。

posted @ 2008-09-29 16:59 沈臻豪(foxtail) 阅读(122) | 评论 (1)编辑 收藏

2008年9月15日

为了更好地学习交流C++技术,虎子同学创建了CPP茶馆,欢迎大家聊天发贴

QQ群一号:35660860
QQ群二号:40790936

点这里:CPP茶馆总论坛

@英语已经不仅仅是一门语言,它可以改变一个人的视野。
************************************************************
目录与摘要
************************************************************
################
常用库的学习使用
################

1.[STL学习摘要之序列式容器]

##########
Project
##########
1.[俄罗斯方块][未完善]

2.[俄罗斯方块V1.0]

3.[俄罗斯方块V1.2]

3.[MD5计算工具]

4.[BMP位图操作类][基于LSB的数字图像水印]

#######
x86ASM
#######
1.[汇编学习测试例子]

#######
Tips:
#######
1.[GCC编译选项和GDB的使用

2.[如何自己写Win32控件 ]

3.[typedef用法小结] 
*************************************************************

posted @ 2008-09-15 09:03 沈臻豪(foxtail) 阅读(91) | 评论 (0)编辑 收藏

2008年9月7日

vector优势:1.随机访问 2.在尾部插入删除元素
#include<iostream>
#include
<vector>
using namespace std;

void Print(vector<int>& vec)
{
    
for(int i = 0; i < vec.size(); ++i)cout<<' '<<vec[i];
    cout
<<endl;
}


int main()
{
    vector
<int> first;
    vector
<int> second(41000);
    vector
<int> third(second.begin() + 2, second.end());
    vector
<int> forth(third);

    vector
<int>::iterator it;

    
int val[] = {1,2,3,4};
    vector
<int> fifth(val, val + sizeof(val) / sizeof(val[0]));

    cout
<<"First:";
    Print(first);
    cout
<<"Second:";
    Print(second);
    cout
<<"Third:";
    Print(third);
    cout
<<"Forth:";
    Print(forth);
    cout
<<"Fifth:";
    Print(fifth);

    first.swap(fifth);
    cout
<<"First:";
    Print(first);

    first.push_back(
12);
    cout
<<"First:";
    Print(first);

    it 
= first.begin() + 2;
    first.erase(it,first.end());
    cout
<<"First:";
    Print(first);

    it 
= first.begin();
    first.insert(it,
100);
    cout
<<"First:";
    Print(first);

    system(
"pause");
    
return 0;
}
结果:

Deque操作代码类似。
优势:比之Vector在头部插入删除元素也有很高效率。也支持迭代器随机访问。不过元素在内存中不连续。

List操作基本相同不过多了一些功能
优势:高效遍历元素,常量时间插入删除任意位置元素。
#include<iostream>
#include
<list>
using namespace std;

void Print(list<int>& ls)
{
    list
<int>::iterator it = ls.begin();
    
for(; it != ls.end(); ++it)cout<<' '<<*it;
    cout
<<endl;
}


void Print(list<double>& ls)
{
    list
<double>::iterator it = ls.begin();
    
for(; it != ls.end(); ++it)cout<<' '<<*it;
    cout
<<endl;
}


int main()
{
    list
<int> first;
    list
<int> second(41000);

    list
<int>::iterator it;

    
double first_val[] = {1.0,3.0,2.0,4.0};
    list
<double> third(first_val, first_val + sizeof(first_val) / sizeof(first_val[0]));

    
double sencond_val[] = {1.1,4.3,1.4,2.9};
    list
<double> fourth(sencond_val, sencond_val + sizeof(sencond_val)/sizeof(sencond_val[0]));

    it 
= first.begin();
    first.insert(it,
100);
    cout
<<"First:";
    Print(first);

    it 
= first.begin();
    first.splice(it,second);
//splice四个参数,第一个参数是插入的位置,第二个是插入源,第三四个参数指定范围
    cout<<"First:";
    Print(first);

    first.remove(
100);
    cout
<<"First:";
    Print(first);

    third.sort();
    fourth.sort();
    cout
<<"Third:";
    Print(third);
    cout
<<"Fourth:";
    Print(fourth);

    third.merge(fourth);
    cout
<<"Third:";
    Print(third);

    system(
"pause");
    
return 0;
}
结果:

splice在代码中已经说明,merge函数合并两个list而且是按照从小到大的顺序,merge有另一个版本包含两个参数,另一个是一个
返回bool类型的函数,说明了比较规则。用法相同。另外一些函数使用比较简单。
该类笔记均参考:www.cplusplus.com
posted @ 2008-09-07 15:24 沈臻豪(foxtail) 阅读(110) | 评论 (0)编辑 收藏

2008年8月31日

 1)运行时库就是   C   run-time   library,是   C   而非   C++   语言世界的概念:取这个名字就是因为你的   C   程序运行时需要这些库中的函数.  
   
  2)C   语言是所谓的“小内核”语言,就其语言本身来说很小(不多的关键字,程序流程控制,数据类型等);所以,C   语言内核开发出来之后,Dennis   Ritchie   和   Brian   Kernighan   就用   C   本身重写了   90%   以上的   UNIX   系统函数,并且把其中最常用的部分独立出来,形成头文件和对应的   LIBRARY,C   run-time   library   就是这样形成的。  
   
  3)随后,随着   C   语言的流行,各个   C   编译器的生产商/个体/团体都遵循老的传统,在不同平台上都有相对应的   Standard   Library,但大部分实现都是与各个平台有关的。由于各个   C   编译器对   C   的支持和理解有很多分歧和微妙的差别,所以就有了   ANSI   C;ANSI   C   (主观意图上)详细的规定了   C   语言各个要素的具体含义和编译器实现要求,引进了新的函数声明方式,同时订立了   Standard   Library   的标准形式。所以C运行时库由编译器生产商提供。至于由其他厂商/个人/团体提供的头文件和库函数,应当称为第三方   C   运行库(Third   party   C   run-time   libraries)。  
   
  4)C   run-time   library里面含有初始化代码,还有错误处理代码(例如divide   by   zero处理)。你写的程序可以没有math库,程序照样运行,只是不能处理复杂的数学运算,不过如果没有了C   run-time库,main()就不会被调用,exit()也不能被响应。因为C   run-time   library包含了C程序运行的最基本和最常用的函数。  
   
  5)到了   C++   世界里,有另外一个概念:Standard   C++   Library,它包括了上面所说的   C   run-time   library   和   STL。包含   C   run-time   library   的原因很明显,C++   是   C   的超集,没有理由再重新来一个   C++   run-time   library.   VC针对C++   加入的Standard   C++   Library主要包括:LIBCP.LIB,   LIBCPMT.LIB和   MSVCPRT.LIB  
   
  6)Windows环境下,VC提供的   C   run-time   library又分为动态运行时库和静态运行时库。  
  动态运行时库主要是DLL库文件msvcrt.dll(or   MSVCRTD.DLL   for   debug   build),对应的Import   library文件是MSVCRT.LIB(MSVCRTD.LIB   for   debug   build)  
  静态运行时库(release版)对应的主要文件是:  
  LIBC.LIB   (Single   thread   static   library,   retail   version)  
  LIBCMT.LIB   (Multithread   static   library,   retail   version)  
   
  msvcrt.dll提供几千个C函数,即使是像printf这么低级的函数都在msvcrt.dll里。其实你的程序运行时,很大一部分时间时在这些运行库里运行。在你的程序(release版)被编译时,VC会根据你的编译选项(单线程、多线程或DLL)自动将相应的运行时库文件(libc.lib,libcmt.lib或Import   library   msvcrt.lib)链接进来。  
   
  编译时到底哪个C   run-time   library联入你的程序取决于编译选项:  
  /MD,   /ML,   /MT,   /LD       (Use   Run-Time   Library)  
  你可以VC中通过以下方法设置选择哪个C   run-time   library联入你的程序:  
  To   find   these   options   in   the   development   environment,   click   Settings   on   the   Project   menu.   Then   click   the   C/C++   tab,   and   click   Code   Generation   in   the   Category   box.   See   the   Use   Run-Time   Library   drop-down   box.  
   
  从程序可移植性考虑,如果两函数都可完成一种功能,选运行时库函数好,因为各个   C   编译器的生产商对标准C   Run-time   library提供了统一的支持.  
posted @ 2008-08-31 20:59 沈臻豪(foxtail) 阅读(112) | 评论 (0)编辑 收藏

2008年8月20日

最早时候就曾经哪里看到过说所有控件都是窗口(window),更有甚者说都是对象,这个就不扯了。自己做好的控件是做成Lib还是Dll那是后话,MFC我是不熟悉了,Win32还是看了几天的。大致把制作的整个流程简要的记录一下。

自己做的控件最主要的功能就是接受你发给他的命令,也就是要给外部调用的接口。控件有自己的消息处理函数比如

LRESULT CALLBACK PETextViewWndProc(HWND hWnd,UINT Message,WPARAM wParam,LPARAM lParam)
{
    PETextView 
*View = (PETextView*)GetWindowLong(hWnd,0);

    
switch(Message)
    
{
    
case WM_NCCREATE:
        
if((View = new PETextView(hWnd)) == 0)
            
return false;

        SetWindowLong(hWnd,
0,(LONG)View);
        
return true;

    
case WM_NCDESTROY:
        
if(View)delete View;
        
return 0;

    
case WM_PAINT:
        
return View->OnPaint();

    
case WM_SIZE:
        
return View->OnSize(wParam, LOWORD(lParam), HIWORD(lParam));

    
case PEM_OPENFILE:
        
return View->OpenFile((TCHAR*)lParam);

    
case PEM_CLEAR:
        
return View->ClearFile();
    
default:
        
break;