|
灰度增强是一种在空域进行的图像增强方法。它是指将一定范围的像素(l,h)线性映射到一个新的范围(nl,nh)的操作。如果原来某个位置(x,y)的像素p(x,y)在(l,h)的范围内。那么,变换后的像素 f(p(x,y))=(p(x,y)-l)*(nh-nl)/(h-l);
使用gdi+对应的处理代码如下:
void EnhanceImage_Linear(Bitmap *bmp, int oldLow,int oldHigh, int newLow,int newHigh) { ASSERT(bmp!=NULL); ASSERT(oldLow>=0 &&oldLow<=255); ASSERT(oldHigh>=0 &&oldHigh<=255); ASSERT(newLow>=0 &&newLow<=255); ASSERT(newHigh>=0 &&newHigh<=255); ASSERT(oldLow<oldHigh); ASSERT(newLow<newHigh);
long width=bmp->GetWidth(); long height=bmp->GetHeight(); BitmapData bmpData; bmp->LockBits(&Rect(0,0,width,height), ImageLockModeRead|ImageLockModeWrite,PixelFormat24bppRGB ,&bmpData); unsigned char *pStart=(unsigned char *)(bmpData.Scan0); REAL oldDiff=oldHigh-oldLow; REAL newDiff=newHigh-newLow; REAL ratio=newDiff/oldDiff; for(int j=0;j<height;j++) { for(int i=0;i<width;i++) { pStart+=j*bmpData.Stride+3*i; for(int k=0;k<3;k++) { if(pStart[k]>=oldLow &&pStart[k]<=oldHigh) { int data=((pStart[k]-oldLow)*ratio); if(data>255) { data=255; } pStart[k]=(unsigned char)data; } } } }
bmp->UnlockBits(&bmpData); }
图像增强技术是将图像的部分信息按照一定的要求加以强化,使得其更适合于某种应用要求。比如,我们可能觉得图像的对比度太差,那么就可以将图像的频域中高频信息加以强化,使得图像的对比度更好;或者觉得图像太过锐利了,那么可以增强图像的低频部分使得图像得以平滑。 图像增强可以在频域或者空域进行。前者是只将图像的空间一定位置的像素值pixel(x,y)按照一定的要求映射到另一个像素值f(pixel(x,y),这里的f就是我们的变换函数。后者(频域增强)是指对图像进行傅立叶变换等变换而获取其像素变化的频率信息,然后按照一定的要求将这些频率信息处理以使之符合要求,然后将图像变换回空间像素阵列。
第一阶段 此阶段主要是能熟练地使用某种语言。这就相当于练武中的套路和架式这些表面的东西。 第二阶段 此阶段能精通基于某种平台的接口(例如我们现在常用的Win 32的API函数)以及所对应语言的自身的库函数。到达这个阶段后,也就相当于可以进行真实散打对练了,可以真正地在实践中做些应用。 第三阶段 此阶段能深入地了解某个平台系统的底层,已经具有了初级的内功的能力,也就是“手中有剑,心中无剑”。 第四阶级 此阶段能直接在平台上进行比较深层次的开发。基本上,能达到这个层次就可以说是进入了高层次。这时进入了高级内功的修炼。比如能进行VxD或操作系统的内核的修改。 这时已经不再有语言的束缚,语言只是一种工具,即使要用自己不会的语言进行开发,也只是简单地熟悉一下,就手到擒来,完全不像是第一阶段的时候学习语言的那种情况。一般来说,从第三阶段过渡到第四阶段是比较困难的。为什么会难呢?这就是因为很多人的思想变不过来。 第五阶级 此阶段就已经不再局限于简单的技术上的问题了,而是能从全局上把握和设计一个比较大的系统体系结构,从内核到外层界面。可以说是“手中无剑,心中有剑”。到了这个阶段以后,能对市面上的任何软件进行剖析,并能按自己的要求进行设计,就算是MS Word这样的大型软件,只要有充足的时间,也一定会设计出来。 第六阶级 此阶段也是最高的境界,达到“无招胜有招”。这时候,任何问题就纯粹变成了一个思路的问题,不是用什么代码就能表示的。也就是“手中无剑,心中也无剑”。 此时,对于练功的人来说,他已不用再去学什么少林拳,只是在旁看一下少林拳的对战,就能把此拳拿来就用。这就是真正的大师级的人物。这时,Win 32或Linux在你眼里是没有什么差别的。 每一个阶段再向上发展时都要按一定的方法。第一、第二个阶段通过自学就可以完成,只要多用心去研究,耐心地去学习。 要想从第二个阶段过渡到第三个阶段,就要有一个好的学习环境。例如有一个高手带领或公司里有一个好的练手环境。经过二、三年的积累就能达到第三个阶段。但是,有些人到达第三个阶段后,常常就很难有境界上的突破了。他们这时会产生一种观念,认为软件无非如此,认为自己已无所不能。其实,这时如果遇到大的或难些的软件,他们往往还是无从下手。 现在我们国家大部分程序员都是在第二、三级之间。他们大多都是通过自学成才的,不过这样的程序员一般在软件公司也能独当一面,完成一些软件的模块。 但是,也还有一
java方面的: it人资讯交流网 http://www.it315.org 这个网站是我最近才发现的,虽然内容不多,但是提供的相关java工具挺齐全。还有就是里面提供了java教学视频录象的免费下载,好像一两周更换一段。个人觉得挺适合初学者的,尤其是那个classpath的设置,讲的很透彻,大家有空可以看一看。
java官方站点(英文) http://java.sun.com 要想了解最新的java动态,下载最新的java相关,比如j2se、j2ee、j2se的最新jdk版本就来这里吧。
java中文站 http://www.java-cn.com 这个可能大家都知道,不用说了,他提供的java资源是最丰富的。注册论坛是免费的,还送积分,用积分可以下载软件和电子书等,如果积分用完了,就需要自己发表一些文章来赚新的积分。
中文java网站 http://www.cn-java.com 跟上面站点类似的一个站,宗旨就是:为java爱好者服务。值得一看!
锋网 http://www.ijsp.net/tech/book/index.jsp 综合性的java网站,内含“下载中心”、“教程教学”等栏目。
java动力 http://eww.cn 网站的内容可以,但是最为出色的是它所运用的flash技术,我就不在这里多说了,大家去看看就知道了,一个字“酷”!!!
vc方面的: vc知识库 http://www.vckbase.com 这个网站就不用多说了,学习vc必去之地。网站专门提供了免费的ftp下载,好东东巨多!
vc之路 http://www.vcroad.com 综合软件开发网站,以vc为主。“资源中心”有许多值得下载的东东。
visual c++/mfc开发指南 http://www.vchelp.net 以讲述windows开发为主的站点,提供了最新的源代码,开发工具,开发资料,开发教程和对好的开发站点,开发工具,图书做介绍,同时为从事开发的朋友提供发布自己开发的软件,代码和工具场所。
c维视点 http://www.c-view.org/root/index.htm 最近发现的vc好站,书籍、软件、代码下载一应具全!!!
游戏开发: 风云工作室 http://member.netease.com/~cloudwu/2000/index.html
标点游戏制作 http://makegame.myetang.com/
未来开发者 http://www.fdev.net/
综合的: 中国软件网 http://www.csdn.net 中国最大的开发者网络,他之所以著名就是因为他的论坛,大家有空可以去看看,能下到很多不错的东东,另外也是交流学习的好地方。
电子书籍的: http://www.itebook.net
最后公布一个巨好的,狂多的电子书下载 http://www.pdown.net 还有巨好的 http://www.codestudy.net/default.asp
我会不断完善这个帖子,要是斑竹允许,请置顶
(一)深入浅出理解索引结构
实际上,您可以把索引理解为一种特殊的目录。微软的SQL SERVER提供了两种索引:聚集索引(clustered index,也称聚类索引、簇集索引)和非聚集索引(nonclustered index,也称非聚类索引、非簇集索引)。下面,我们举例来说明一下聚集索引和非聚集索引的区别:
其实,我们的汉语字典的正文本身就是一个聚集索引。比如,我们要查“安”字,就会很自然地翻开字典的前几页,因为“安”的拼音是“an”,而按照拼音排序汉字的字典是以英文字母“a”开头并以“z”结尾的,那么“安”字就自然地排在字典的前部。如果您翻完了所有以“a”开头的部分仍然找不到这个字,那么就说明您的字典中没有这个字;同样的,如果查“张”字,那您也会将您的字典翻到最后部分,因为“张”的拼音是“zhang”。也就是说,字典的正文部分本身就是一个目录,您不需要再去查其他目录来找到您需要找的内容。
我们把这种正文内容本身就是一种按照一定规则排列的目录称为“聚集索引”。
如果您认识某个字,您可以快速地从自动中查到这个字。但您也可能会遇到您不认识的字,不知道它的发音,这时候,您就不能按照刚才的方法找到您要查的字,而需要去根据“偏旁部首”查到您要找的字,然后根据这个字后的页码直接翻到某页来找到您要找的字。但您结合“部首目录”和“检字表”而查到的字的排序并不是真正的正文的排序方法,比如您查“张”字,我们可以看到在查部首之后的检字表中“张”的页码是672页,检字表中“张”的上面是“驰”字,但页码却是63页,“张”的下面是“弩”字,页面是390页。很显然,这些字并不是真正的分别位于“张”字的上下方,现在您看到的连续的“驰、张、弩”三字实际上就是他们在非聚集索引中的排序,是字典正文中的字在非聚集索引中的映射。我们可以通过这种方式来找到您所需要的字,但它需要两个过程,先找到目录中的结果,然后再翻到您所需要的页码。
我们把这种目录纯粹是目录,正文纯粹是正文的排序方式称为“非聚集索引”。
通过以上例子,我们可以理解到什么是“聚集索引”和“非聚集索引”。
进一步引申一下,我们可以很容易的理解:每个表只能有一个聚集索引,因为目录只能按照一种方法进行排序。
(二)何时使用聚集索引或非聚集索引
下面的表总结了何时使用聚集索引或非聚集索引(很重要)。
动作描述 使用聚集索引 使用非聚集索引
列经常被分组排序 应 应
返回某范围内的数据 应 不应
一个或极少不同值 不应 不应
小数目的不同值 应 不应
大数目的不同值 不应 应
频繁更新的列 不应 应
外键列 应 应
主键列 应 应
频繁修改索引列 不应 应
事实上,我们可以通过前面聚集索引和非聚集索引的定义的例子来理解上表。如:返回某范围内的数据一项。比如您的某个表有一个时间列,恰好您把聚合索引建立在了该列,这时您查询2004年1月1日至2004年10月1日之间的全部数据时,这个速度就将是很快的,因为您的这本字典正文是按日期进行排序的,聚类索引只需要找到要检索的所有数据中的开头和结尾数据即可;而不像非聚集索引,必须先查到目录中查到每一项数据对应的页码,然后再根据页码查到具体内容。
(三)结合实际,谈索引使用的误区
理论的目的是应用。虽然我们刚才列出了何时应使用聚集索引或非聚集索引,但在实践中以上规则却很容易被忽视或不能根据实际情况进行综合分析。下面我们将根据在实践中遇到的实际问题来谈一下索引使用的误区,以便于大家掌握索引建立的方法。
1、主键就是聚集索引
这种想法笔者认为是极端错误的,是对聚集索引的一种浪费。虽然SQL SERVER默认是在主键上建立聚集索引的。
通常,我们会在每个表中都建立一个ID列,以区分每条数据,并且这个ID列是自动增大的,步长一般为1。我们的这个办公自动化的实例中的列Gid就是如此。此时,如果我们将这个列设为主键,SQL SERVER会将此列默认为聚集索引。这样做有好处,就是可以让您的数据在数据库中按照ID进行物理排序,但笔者认为这样做意义不大。
显而易见,聚集索引的优势是很明显的,而每个表中只能有一个聚集索引的规则,这使得聚集索引变得更加珍贵。
从我们前面谈到的聚集索引的定义我们可以看出,使用聚集索引的最大好处就是能够根据查询要求,迅速缩小查询范围,避免全表扫描。在实际应用中,因为ID号是自动生成的,我们并不知道每条记录的ID号,所以我们很难在实践中用ID号来进行查询。这就使让ID号这个主键作为聚集索引成为一种资源浪费。其次,让每个ID号都不同的字段作为聚集索引也不符合“大数目的不同值情况下不应建立聚合索引”规则;当然,这种情况只是针对用户经常修改记录内容,特别是索引项的时候会负作用,但对于查询速度并没有影响。
在办公自动化系统中,无论是系统首页显示的需要用户签收的文件、会议还是用户进行文件查询等任何情况下进行数据查询都离不开字段的是“日期”还有用户本身的“用户名”。
通常,办公自动化的首页会显示每个用户尚未签收的文件或会议。虽然我们的where语句可以仅仅限制当前用户尚未签收的情况,但如果您的系统已建立了很长时间,并且数据量很大,那么,每次每个用户打开首页的时候都进行一次全表扫描,这样做意义是不大的,绝大多数的用户1个月前的文件都已经浏览过了,这样做只能徒增数据库的开销而已。事实上,我们完全可以让用户打开系统首页时,数据库仅仅查询这个用户近3个月来未阅览的文件,通过“日期”这个字段来限制表扫描,提高查询速度。如果您的办公自动化系统已经建立的2年,那么您的首页显示速度理论上将是原来速度8倍,甚至更快。
在这里之所以提到“理论上”三字,是因为如果您的聚集索引还是盲目地建在ID这个主键上时,您的查询速度是没有这么高的,即使您在“日期”这个字段上建立的索引(非聚合索引)。下面我们就来看一下在1000万条数据量的情况下各种查询的速度表现(3个月内的数据为25万条):
(1)仅在主键上建立聚集索引,并且不划分时间段:
Select gid,fariqi,neibuyonghu,title from tgongwen
用时:128470毫秒(即:128秒)
(2)在主键上建立聚集索引,在fariq上建立非聚集索引:
select gid,fariqi,neibuyonghu,title from Tgongwen
where fariqi> dateadd(day,-90,getdate())
用时:53763毫秒(54秒)
(3)将聚合索引建立在日期列(fariqi)上:
select gid,fariqi,neibuyonghu,title from Tgongwen
where fariqi> dateadd(day,-90,getdate())
用时:2423毫秒(2秒)
虽然每条语句提取出来的都是25万条数据,各种情况的差异却是巨大的,特别是将聚集索引建立在日期列时的差异。事实上,如果您的数据库真的有1000万容量的话,把主键建立在ID列上,就像以上的第1、2种情况,在网页上的表现就是超时,根本就无法显示。这也是我摒弃ID列作为聚集索引的一个最重要的因素。
得出以上速度的方法是:在各个select语句前加:declare @d datetime
set @d=getdate()
并在select语句后加:
select [语句执行花费时间(毫秒)]=datediff(ms,@d,getdate())
2、只要建立索引就能显著提高查询速度
事实上,我们可以发现上面的例子中,第2、3条语句完全相同,且建立索引的字段也相同;不同的仅是前者在fariqi字段上建立的是非聚合索引,后者在此字段上建立的是聚合索引,但查询速度却有着天壤之别。所以,并非是在任何字段上简单地建立索引就能提高查询速度。
从建表的语句中,我们可以看到这个有着1000万数据的表中fariqi字段有5003个不同记录。在此字段上建立聚合索引是再合适不过了。在现实中,我们每天都会发几个文件,这几个文件的发文日期就相同,这完全符合建立聚集索引要求的:“既不能绝大多数都相同,又不能只有极少数相同”的规则。由此看来,我们建立“适当”的聚合索引对于我们提高查询速度是非常重要的。
3、把所有需要提高查询速度的字段都加进聚集索引,以提高查询速度
上面已经谈到:在进行数据查询时都离不开字段的是“日期”还有用户本身的“用户名”。既然这两个字段都是如此的重要,我们可以把他们合并起来,建立一个复合索引(compound index)。
很多人认为只要把任何字段加进聚集索引,就能提高查询速度,也有人感到迷惑:如果把复合的聚集索引字段分开查询,那么查询速度会减慢吗?带着这个问题,我们来看一下以下的查询速度(结果集都是25万条数据):(日期列fariqi首先排在复合聚集索引的起始列,用户名neibuyonghu排在后列)
(1)select gid,fariqi,neibuyonghu,title from Tgongwen where fariqi>'2004-5-5'
查询速度:2513毫秒
(2)select gid,fariqi,neibuyonghu,title from Tgongwen where fariqi>'2004-5-5' and neibuyonghu='办公室'
查询速度:2516毫秒
(3)select gid,fariqi,neibuyonghu,title from Tgongwen where neibuyonghu='办公室'
查询速度:60280毫秒
从以上试验中,我们可以看到如果仅用聚集索引的起始列作为查询条件和同时用到复合聚集索引的全部列的查询速度是几乎一样的,甚至比用
__cdecl和__stdcall都是函数调用规范(还有一个__fastcall),规定了参数出入栈的顺序和方法,如果只用VC编程的话可以不用关心,但是要在C++和Pascal等其他语言通信的时候就要注意了,只有用相同的方法才能够调用成功.另外,像printf这样接受可变个数参数的函数只有用cdecl才能够实现. __declspec主要是用于说明DLL的引出函数的,在某些情况下用__declspec(dllexport)在DLL中生命引出函数,比用传统的DEF文件方便一些.在普通程序中也可以用__declspec(dllimport)说明函数是位于另一个DLL中的导出函数.
int WINAPI MessageBoxA(HWND,LPCSTR,LPSTR,UINT); 而WINAPI实际上就是__stdcall. 大多数API都采用__stdcall调用规范,这是因为几乎所有的语言都支持__stdcall调用.相比之下,__cdecl只有在C语言中才能用.但是__cdecl调用有一个特点,就是能够实现可变参数的函数调用,比如printf,这用__stdcall调用是不可能的. __fastcall这种调用规范比较少见,但是在Borland C++ Builder中比较多的采用了这种调用方式. 如果有共享代码的需要,比如写DLL,推荐的方法是用__stdcall调用,因为这样适用范围最广.如果是C++语言写的代码供Delphi这样的语言调用就必须声明为__stdcall,因为Pascal不支持cdecl调用(或许Delphi的最新版本能够支持也说不定,这个我不太清楚).在其他一些地方,比如写COM组件,几乎都用的是stdcall调用.在VC或Delphi或C++Builder里面都可以从项目设置中更改默认的函数调用规范,当然你也可以在函数声明的时候加入__stdcall,__cdecl,__fastcall关键字来明确的指示本函数用哪种调用规范. __declspec一般都是用来声明DLL中的导出函数.这个关键字也有一些其他的用法,不过非常罕见.
#ifndef _ALV_TREE_H #define _ALV_TREE_H #define Max(a,b) (((a)>(b))?(a):(b)) #include <iostream>
template<class T> class AVLTree { struct _TreeNode; typedef struct _TreeNode TreeNode; struct _TreeNode { T data; int height; TreeNode* left; TreeNode* right; };
private: TreeNode *root; public: AVLTree() { this->root=NULL; }
~AVLTree() { this->MakeEmpty(this->root); }
int GeiHeight() { return this->GetHeightUtil(this->root); }
void Insert(T data) { this->root=this->InsertUtil(this->root,data); } void Delete(T data) { this->root=this->DeleteUtil(this->root,data); }
void Print() { /*if(root!=NULL) { std::cout<<"The root node is: "<<root->data<<std::endl; }*/ for(int level=0;;level++) { if(this->PrintUtil(this->root,level)==0) { break; } std::cout<<std::endl; } }
private: TreeNode *InsertUtil(TreeNode *_root,T data) { if(_root==NULL) { _root=new TreeNode(); _root->data=data; _root->left=0; _root->right=0; _root->height=0; } if(data>_root->data) { _root->right=this->InsertUtil(_root->right,data); if(GetHeightUtil(_root->right)-GetHeightUtil(_root->left)==2) { if(data>_root->right->data) { _root=this->SingleRotateWithRight(_root); } else { _root=this->DoubleRotateWithRight(_root); } } } else if(data<_root->data) { _root->left=this->InsertUtil(_root->left,data); if(GetHeightUtil(_root->left)-GetHeightUtil(_root->right)==2) { if(data<_root->left->data) { _root=this->SingleRotateWithLeft(_root); } else { _root=this->DoubleRotateWithLeft(_root); } } } _root->height=Max(GetHeightUtil(_root->left),GetHeightUtil(_root->right))+1; return _root; }
TreeNode *DeleteUtil(TreeNode *_root,T data) { if(_root==NULL) { return _root; } else if(_root->data==data &&_root->left==NULL &&_root->right==NULL) { delete _root; return NULL; } else if(_root->data==data &&_root->left!=NULL &&_root->right==NULL) { TreeNode* tmpNode=_root->left; delete _root; tmpNode->height=this->RecalculateHeight(tmpNode); return tmpNode; } else if(_root->data==data &&_root->left==NULL &&_root->right!=NULL) { TreeNode *tmpNode=_root->right; delete _root; tmpNode->height=this->RecalculateHeight(tmpNode); return tmpNode; } else { if(data==_root->data) { TreeNode *tmpNode,*parentNode; tmpNode=_root->right->right; parentNode=_root->right; if(tmpNode!=NULL) { while(tmpNode->right!=NULL) { parentNode->height-=1; parentNode=tmpNode; tmpNode=tmpNode->right; } parentNode->right=NULL; _root->data=tmpNode->data; delete tmpNode; } else { _root=parentNode; } _root->height=this->RecalculateHeight(_root); //TreeNode *tmpNode=this->FindMax(_root->right); //_root->data=tmpNode->data; if(GetHeightUtil(_root->left)-GetHeightUtil(_root->right)==2) { if(_root->left->left!=NULL) { _root=this->SingleRotateWithLeft(_root); } else if(_root->left->right!=NULL) { _root=this->DoubleRotateWithLeft(_root); } } } else if(data>_root->data) { _root->right=this->DeleteUtil(_root->right,data); _root->height=this->RecalculateHeight(_root); if(GetHeightUtil(_root->left)-GetHeightUtil(_root->right)==2) { if(_root->left->left!=NULL) { _root=this->SingleRotateWithLeft(_root); } else if(_root->left->right!=NULL) { _root=this->DoubleRotateWithLeft(_root); } } } else { _root->left=this->DeleteUtil(_root->left,data); _root->height=this->RecalculateHeight(_root); if(GetHeightUtil(_root->right)-GetHeightUtil(_root->left)==2) { if(_root->right->right!=NULL) { _root=this->SingleRotateWithRight(_root); } else if(_root->right->left!=NULL) { _root=this->DoubleRotateWithRight(_root); } } } } //_root->height=this->RecalculateHeight(_root); return _root; }
void MakeEmpty(TreeNode *_root) { if(_root==NULL) { return; } else { MakeEmpty(_root->left); MakeEmpty(_root->right); delete _root; } }
int GetHeightUtil(TreeNode *_root) { /*if(_root==NULL|| (_root->left==NULL && _root->right==NULL)) { return 0; } else { return 1+GetHeightUtil(_root->left)+GetHeightUtil(_root->right); }*/ if(_root==NULL) { return -1; } else { return _root->height; } }
int PrintUtil(TreeNode *node, int level) { if(node==NULL||level<0) { return 0; } else { if(level==0) { std::cout<<node->data<<" "; return 1; } return PrintUtil(node->left,level-1)+PrintUtil(node->right,level-1); } }
TreeNode *SingleRotateWithLeft(TreeNode *node) { TreeNode *tmpNode=node->left; node->left=tmpNode->right; tmpNode->right=node; node->height=Max(GetHeightUtil(node->left),GetHeightUtil(node->right))+1; tmpNode->height=Max(GetHeightUtil(tmpNode->left),GetHeightUtil(tmpNode->right))+1; return tmpNode; }
TreeNode*SingleRotateWithRight(TreeNode *node) { TreeNode *tmpNode=node->right; node->right=tmpNode->left; tmpNode->left=node; node->height=Max(GetHeightUtil(node->left),GetHeightUtil(node->right))+1; tmpNode->height=Max(GetHeightUtil(tmpNode->left),GetHeightUtil(tmpNode->right))+1; return tmpNode; }
TreeNode* DoubleRotateWithLeft(TreeNode *node) { node->left=this->SingleRotateWithRight(node->left); return this->SingleRotateWithLeft(node); }
TreeNode* DoubleRotateWithRight(TreeNode *node) { node->right=this->SingleRotateWithLeft(node->right); return this->SingleRotateWithRight(node); }
TreeNode* FindMax(TreeNode *node) { //T maxData; while(node!=NULL&&node->right!=NULL) { node=node->right; } //maxData=node->data; return node; }
int RecalculateHeight(TreeNode *node) { if(node==NULL) { return -1; } else { node->height=Max(RecalculateHeight(node->left),RecalculateHeight(node->right))+1; return node->height; } } };
#endif
首先打开菜单 项目->项目属性页
1。选择配置属性->链接器->调试->生成调试信息 改为 是
2。选择 配置属性->C/C++ ->常规->调试信息格式 改为 用于“编辑并继续”的程序数据库(/ZI)
3。选择 配置属性->C/C++ ->优化->优化 改为 自定义
重新编译,运行
文本编辑器是所有计算机系统中最常用的一种工具。UNIX下的编辑器有ex,sed和vi等,其中,使用最为广泛的是vi,而vi命令繁多,论坛里好像这方面的总结不多,以下稍做总结,以资共享!渴望更正和补充!
进入vi的命令 vi filename :打开或新建文件,并将光标置于第一行首 vi +n filename :打开文件,并将光标置于第n行首 vi + filename :打开文件,并将光标置于最后一行首 vi +/pattern filename:打开文件,并将光标置于第一个与pattern匹配的串处 vi -r filename :在上次正用vi编辑时发生系统崩溃,恢复filename vi filename....filename :打开多个文件,依次进行编辑
移动光标类命令 h :光标左移一个字符 l :光标右移一个字符 space:光标右移一个字符 Backspace:光标左移一个字符 k或Ctrl+p:光标上移一行 j或Ctrl+n :光标下移一行 Enter :光标下移一行 w或W :光标右移一个字至字首 b或B :光标左移一个字至字首 e或E :光标右移一个字至字尾 ) :光标移至句尾 ( :光标移至句首 }:光标移至段落开头 {:光标移至段落结尾 nG:光标移至第n行首 n+:光标下移n行 n-:光标上移n行 n$:光标移至第n行尾 H :光标移至屏幕顶行 M :光标移至屏幕中间行 L :光标移至屏幕最后行 0:(注意是数字零)光标移至当前行首 $:光标移至当前行尾
屏幕翻滚类命令 Ctrl+u:向文件首翻半屏 Ctrl+d:向文件尾翻半屏 Ctrl+f:向文件尾翻一屏 Ctrl+b;向文件首翻一屏 nz:将第n行滚至屏幕顶部,不指定n时将当前行滚至屏幕顶部。
插入文本类命令 i :在光标前 I :在当前行首 a:光标后 A:在当前行尾 o:在当前行之下新开一行 O:在当前行之上新开一行 r:替换当前字符 R:替换当前字符及其后的字符,直至按ESC键 s:从当前光标位置处开始,以输入的文本替代指定数目的字符 S:删除指定数目的行,并以所输入文本代替之 ncw或nCW:修改指定数目的字 nCC:修改指定数目的行
删除命令 ndw或ndW:删除光标处开始及其后的n-1个字 do:删至行首 d$:删至行尾 ndd:删除当前行及其后n-1行 x或X:删除一个字符,x删除光标后的,而X删除光标前的 Ctrl+u:删除输入方式下所输入的文本
搜索及替换命令 /pattern:从光标开始处向文件尾搜索pattern ?pattern:从光标开始处向文件首搜索pattern n:在同一方向重复上一次搜索命令 N:在反方向上重复上一次搜索命令 :s/p1/p2/g:将当前行中所有p1均用p2替代 :n1,n2s/p1/p2/g:将第n1至n2行中所有p1均用p2替代 :g/p1/s//p2/g:将文件中所有p1均用p2替换
选项设置 all:列出所有选项设置情况 term:设置终端类型 ignorance:在搜索中忽略大小写 list:显示制表位(Ctrl+I)和行尾标志($) number:显示行号 report:显示由面向行的命令修改过的数目 terse:显示简短的警告信息 warn:在转到别的文件时若没保存当前文件则显示NO write信息 nomagic:允许在搜索模式中,使用前面不带“\”的特殊字符 nowrapscan:禁止vi在搜索到达文件两端时,又从另一端开始 mesg:允许vi显示其他用户用write写到自己终端上的信息
最后行方式命令 :n1,n2 co n3:将n1行到n2行之间的内容拷贝到第n3行下 :n1,n2 m n3:将n1行到n2行之间的内容移至到第n3行下 :n1,n2 d :将n1行到n2行之间的内容删除 :w :保存当前文件 :e filename:打开文件filename进行编辑 :x:保存当前文件并退出 :q:退出vi :q!:不保存文件并退出vi :!command:执行shell命令command :n1,n2 w!command:将文件中n1行至n2行的内容作为command的输入并执行之,若不指定n1,n2,则表示将整个文件内容作为command的输入 :r!command:将命令command的输出结果放到当前行
寄存器操作 "?nyy:将当前行及其下n行的内容保存到寄存器?中,其中?为一个字母,n为一个数字 "?nyw:将当前行及其下n个字保存到寄存器?中,其中?为一个字母,n为一个数字 "?nyl:将当前行及其下n个字符保存到寄存器?中,其中?为一个字母,n为一个数字 "?p:取出寄存器?中的内容并将其放到光标位置处。这里?可以是一个字母,也可以是一个数字 ndd:将当前行及其下共n行文本删除,并将所删内容放到1号删除寄存器中。
代码: #include <iostream> #include <windows.h> using namespace std;
int main() { SECURITY_ATTRIBUTES secStru; secStru.bInheritHandle=0; secStru.lpSecurityDescriptor=0; secStru.nLength=0; HANDLE hDevice=CreateFile("\\\\.\\PhysicalDrive0",GENERIC_READ | GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,0,NULL);
if(hDevice==INVALID_HANDLE_VALUE) { return -1; }
//DWORD outBuff[1000]; GET_LENGTH_INFORMATION infoStruct;
memset(&infoStruct,0,sizeof(infoStruct)); DWORD bytesReturned; if(DeviceIoControl(hDevice,IOCTL_DISK_GET_LENGTH_INFO,NULL,0,&infoStruct,sizeof(infoStruct),&bytesReturned,NULL)==0) { cout<<"Failed to get disk information."<<endl; DWORD error; error=GetLastError(); HRESULT hRe=HRESULT_FROM_WIN32(error); char errorData[10]; sprintf(errorData,"%x",hRe); cout<<"Error code:"<</*hRe*/errorData<<endl; CloseHandle(hDevice); return -1; }
DISK_GEOMETRY_EX geoStruct; memset(&geoStruct,0,sizeof(geoStruct)); if(DeviceIoControl(hDevice,IOCTL_DISK_GET_DRIVE_GEOMETRY_EX ,NULL,0,&geoStruct,sizeof(geoStruct),&bytesReturned,NULL)==0) { cout<<"Failed to get disk information."<<endl; DWORD error; error=GetLastError(); HRESULT hRe=HRESULT_FROM_WIN32(error); char errorData[10]; sprintf(errorData,"%x",hRe); cout<<"Error code:"<</*hRe*/errorData<<endl; CloseHandle(hDevice); return -1; }
cout<<"The disk's size is:"<<infoStruct.Length.QuadPart/1024/1024/1024<<" G Bytes."<<endl; cout<<"The disk's cylinder number:"<<geoStruct.Geometry.Cylinders.QuadPart<<endl; cout<<"The disk's media type:"<<geoStruct.Geometry.MediaType<<endl; cout<<"Number of tracks per cylinder:"<<geoStruct.Geometry.TracksPerCylinder<<endl; cout<<"Number of sectors per track:"<<geoStruct.Geometry.SectorsPerTrack<<endl; cout<<"Number of bytes per sector:"<<geoStruct.Geometry.BytesPerSector<<endl;
PDISK_PARTITION_INFO partitionInfo=DiskGeometryGetPartition(&geoStruct);
DRIVE_LAYOUT_INFORMATION_EX layOutInfo[20];
memset(&layOutInfo,0,sizeof(DRIVE_LAYOUT_INFORMATION_EX)*20);
//layOutInfo.PartitionEntry=*(new PARTITION_INFORMATION_EX[10]);
if(DeviceIoControl(hDevice,IOCTL_DISK_GET_DRIVE_LAYOUT_EX,NULL,0,&layOutInfo,sizeof(DRIVE_LAYOUT_INFORMATION_EX)*20,&bytesReturned,NULL)==0) { cout<<"Failed to get disk information."<<endl; DWORD error; error=GetLastError(); HRESULT hRe=HRESULT_FROM_WIN32(error); char errorData[10]; sprintf(errorData,"%x",hRe); cout<<"Error code:"<</*hRe*/errorData<<endl; CloseHandle(hDevice); return -1; }
int partitionCount=layOutInfo[0].PartitionCount; cout<<"Number of partitions:"<<layOutInfo[0].PartitionCount<<endl; cout<<"Partitions' information:"<<endl; for(int i=0;i<partitionCount;i++) { //PDISK_PARTITION_INFO pParInfo=partitionInfo+i*sizeof(DISK_PARTITION_INFO); if(layOutInfo[i].PartitionEntry[0].PartitionNumber!=0) { cout<<"Partition "<<layOutInfo[i].PartitionEntry[0].PartitionNumber<<", partition size is "<<layOutInfo[i].PartitionEntry[0].PartitionLength.QuadPart/1024/1024/1024<<" G Bytes, partition style is "<<layOutInfo[i].PartitionEntry[0].PartitionStyle<<endl; } }
//cout<<"The type of partition:"<<((partitionInfo.PartitionStyle==PARTITION_STYLE_MBR) ?"MBR":((partitionInfo.PartitionStyle==PARTITION_STYLE_GPT )?"GPT":((partitionInfo.PartitionStyle==PARTITION_STYLE_RAW)?"RAW":"")))<<endl;
CloseHandle(hDevice);
return 0; }
|