当前位置: 移动技术网 > IT编程>开发语言>C/C++ > C++入门学习笔记

C++入门学习笔记

2018年01月22日  | 移动技术网IT编程  | 我要评论

南昌航空大学图书馆,望近寸终十六码,无限极增健口服液

这些是我刚学习C++的笔记,拿出来与大家分享,希望大家更容易入门!

1、 运算符<<(送出)用作输出运算符;cout是标准输出流。运算符>>(取入)用作输入运算;cin是标准的输入流。

2、 输出:一个输出表达式的结果本身还可以用于进一步的输出。

void h2(int i)

{

Cout<<”the value of I is”<

3、 输入:Void h3(int i)

{

Cin>>x;

Getline(cin,str);

}4、 迭代器是一种对象,它能够用来遍历标准模板库容器中的部分或全部元素,每个迭代器对象代表容器中的确定的地址。迭代器修改了常规指针接口,所谓迭代器是一种概念上的抽像:那些行为上像迭代器的东西都可以叫做迭代器。然而迭代器有很多不同的能力,他可以把抽象的容器和同用的算法有机的结合起来。迭代器提供一些基本操作符:*、++、==、!=、=。这些操作和c/c++操作array元素时的指针接口一致。不同之处在于迭代器是个所谓的复杂指针。具有遍历复杂数据结构的能力。其下层运行机制取决于其所遍历的数据结构。因此每一种容器型别都必须提供自己的迭代器。事实上每一种容器都将其迭代器以嵌套的方式定义域内部。因此各种迭代器的接口相同,型号却不同。这直接导出了泛型程序设计概念:所有操作行为都是用相同接口虽然他们的型别不同。功能迭代器使开发人员能够在类或结构中支持foreach迭代,而不必整个实现IEnumerable或者IEnumerator接口。只需提供一个迭代器,即可遍历类中的数据结构。当编译器检测到迭代器时,将自动生成IEnumerable接口或者IEnumerator接口的Current,MoveNext和Dispose方法。特点1.迭代器是可以返回相同类型值的有序序列的一段代码;2.迭代器可用作方法、运算符或get访问器的代码体;3.迭代器代码使用yieldreturn语句依次返回每个元素,yield break将终止迭代;4.可以在类中实现多个迭代器,每个迭代器都必须像任何类成员一样有惟一的名称,并且可以在foreach语句中被客户端,代码调用如下所示:foreach(int x in SimpleClass.Iterator2){};5.迭代器的返回类型必须为IEnumerable和IEnumerator中的任意一种;6.迭代器是产生值的有序序列的一个语句块,不同于有一个 或多个yield语句存在的常规语句块;7.迭代器不是一种成员,它只是实现函数成员的方式,理解这一点是很重要的,一个通过迭代器实现的成员,可以被其他可能或不可能通过迭代器实现的成员覆盖和重载;8.迭代器块在C#语法中不是独特的元素,它们在几个方面受到限制,并且主要作用在函数成员声明的语义上,它们在语法上只是语句块而已;9.yield关键字用于指定返回的值。到达yieldreturn语句时,会保存当前位置。下次调用迭代器时将从此位置重新开始执行。 迭代器对集合类特别有用,它提供一种简单的方法来迭代不常用的数据结构(如二进制树)。简介迭代器是一种检查容器内元素并遍历元素的数据类型。 5、 枚举(enum)枚举在C/C++/c#中,是一个被命名的整型常数的集合, 枚举在日常生活中很常见。例如表示星期的SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY,SATURDAY, 就是一个枚举。枚举的说明与结构和联合相似, 其形式为:enum 枚举名{

标识符[=整型常数],

标识符[=整型常数],

...

标识符[=整型常数]

} 枚举变量;如果枚举没有初始化, 即省掉”=整型常数”时, 则从第一个标识符开始, 顺次赋给标识符0, 1, 2, …。但当枚举中的某个成员赋值后, 其后的成员按依次加1的规则确定其值。例如下列枚举说明后, x1, x2, x3, x4的值分别为0, 1, 2, 3。enum Num{x1, x2, x3, x4}x;当定义改变成:enum Num

{

x1,

x2=0,

x3=50,

x4

}x;则x1=0, x2=0, x3=50, x4=51注意:1. 枚举中每个成员(标识符)结束符是”,”, 不是”;”, 最后一个成员可省略“,”。2. 初始化时可以赋负数, 以后的标识符仍依次加1。3. 枚举变量只能取枚举说明结构中的某个标识符常量。例如:enum Num

{

x1=5,

x2,

x3,

x4

};

enum Num x=x3;此时, 枚举变量x实际上是7。枚举类型变量的赋值和使用枚举类型在使用中有以下规定:1.枚举值是常量,不是变量。不能在程序中用赋值语句再对它赋值。例如对枚举weekday的元素再作以下赋值: sun=5;mon=2;sun=mon; 都是错误的。2. 枚举元素本身由系统定义了一个表示序号的数值,从0 开始顺序定义为0,1,2…。如在weekday中,sun值为0,mon值为1, …,sat值为6。main(){

enum weekday

{ sun,mon,tue,wed,thu,fri,sat } a,b,c;

a=sun;

b=mon;

c=tue;

printf("%d,%d,%d",a,b,c);

}只能把枚举值赋予枚举变量,不能把元素的数值直接赋予枚举变量。如: a=sun;b=mon; 是正确的。而: a=0;b=1; 是错误的。如一定要把数值赋予枚举变量,则必须用强制类型转换,如: a=(enum weekday)2;其意义是将顺序号为2的枚举元素赋予枚举变量a,相当于: a=tue; 还应该说明的是枚举元素不是字符常量也不是字符串常量, 使用时不要加单、双引号。main(){

enum body

{ a,b,c,d } month[31],j;

int i;

j=a;

for(i=1;i<=30;i++){

month[i]=j;

j++;

if (j>d) j=a;

}

for(i=1;i<=30;i++){

switch(month[i])

{

case a:printf(" %2d %c\t",i,'a'); break;

case b:printf(" %2d %c\t",i,'b'); break;

case c:printf(" %2d %c\t",i,'c'); break;

case d:printf(" %2d %c\t",i,'d'); break;

default:break;

}

}

printf("\n");

}10个数字,任意取出不相等的5个数字,

谁还记得这个算法的公式????????

用javascript有什么好的计算方法??

m n*(n-1)*(n-2)*...*(n-m+1) n!

C = --------------------------------------------- = --------------------------

n m*(m-1)*(m-2)*...*3*2*1 m!*(n-m)!这个是公式,但是对枚举作用不大,还是要遍历循环才行.这就需要一个好的算法6、 typedeftypedef为C语言的关键字,作用是为一种数据类型定义一个新名字。这里的数据类型包括内部数据类型(int,char等)和自定义的数据类型(struct等)。在编程中使用typedef目的一般有两个,一个是给变量一个易记且意义明确的新名字,另一个是简化一些比较复杂的类型声明。 7、 大小C++对象的大小事用char的大小的倍数表示的。按照定义char的大小为1,。一个对象或类型的大小可以用sizeof运算符得到。类型 大小Char bool 1

Short,wchar_t 2

Int,long,float 4

Float,long double 88、 显式类转换显示类型转换只是得到了一个所需类型的中间变量,原来变量的类型并不发生改变。标准C++中主要有4中显式类转换类型运算reinterpret_cast,static_cast,const_cast,dynamic_cast.1. reinterpret_cast语法:returnvalue=reinterpret_cast(casting value);这个操作符修改了操作数类型,但仅仅是重新解释了对象的比特模型而没有进行二进制转换。从语法上看,这个操作符仅用于指针类型的转换(返回值是指针)。它用来将一个类型指针转换为另一个类型指针,它只需在编译时重新解释指针的类型。这个操作符基本不考虑转换类型之间是否是相关的。reinterpret_cast常用的场景如下:1)普通指针转换,T*—>U*—>T*,保证T*经过一些列转换值不变比如将不同类型的指针存在一个容器里,vector可以存int*,char*,string*等各种指针,只要有别的方式确定某个void*当初的类型是T*,标准保证reinterpret_cast(v[i])可以得到当初的值。2)自己做memory allocator,可以将T*转换为U*,这个时候可能要注意字节对其的问题。2、static_cast语法:T static_cast (expression);该运算符把expression转换成type-id类型,但没有运行时类型检查来保证转换的安全性。static_cast是最经常用到的转换操作符,它最经常的一个应用就是将隐式转换变成显示转换,以消除编译器可能产生的warning,同reinterpret_cast不同,采用static_cast转换的两个类型之间一般有某种相关性。static_cast主要应用场景如下:1)用于类层次结构中基类和派生类之间指针或引用的转换。这个转换中,将派生类转成基类是安全的,将基类转成派生类时由于没有进行动态类型检查,所以是不安全的。2)用于基本数据之间的转换。如把int转成char,int转成num等。3)把空指针转换成目标类型的空指针。4)把任何类型的表达式转换成void类型。3、dynamic_cast语法:dynamic_cast < type-id > ( expression )该运算符把expression转换成type-id类型的对象。Type-id必须是类的指针、类的引用或者void *;dynamic_cast的转换是在运行时进行的,它的一个好处是会在运行是做类型检查,如果对象的类型不是期望的类型,它会在指针转换的时候返回NULL,并在引用转换的时候抛出一个std::bad_cast异常。dynamic_cast一般只在继承类对象的指针之间或引用之间进行类型转换。如果没有继承关系,则被转化的类具有虚函数对象的指针进行转换。4.const_castconst_cast< type-id > (expssion)这个运算符可以用来去除一个对象的const或volatile属性。type-id必须是一个指针或者引用。- 9、&—–取地址符运算例如: int e[3]={1,2,3};

Int *p;

p=&e[2];

则:

*p=2;

*(p+1)=3;

*(p-1)=1;10、C++语言中的基本数据类型及其范围 11、类类描述了一类食物,以及食物所应具有的属性,是一种用户自定义的数据类型。声明一个类时,以class关键字开始,接着是类的名字,其语法结构为: Class <类名称>

{

private:

[<私有数据和函数>]

public:

[<公有数据和函数>]

}类表示了一组相似的对象,是创建对象的有效模板,用它可以产生多个对象。类所代表的是一个抽象的概念或事物,在客观世界中世纪存在的是类的实例,即对象。类时具有相同属性和服务的一组对象的集合,它为属于该类的全部对象提供了一个统一的抽象描述,其内部包括属性和服务两个主要部分。类包含以下3种类型:- private:私有类型包含数据和函数,在private关键字后面声明。如果省略private关键字,则必须紧跟在类名的后面声明。在类中声明的数据和函数如果不特别指明,都被视为私有类型。私有类型的数据值允许类本身声明的函数对其进行存取,而类的外部的任何函数都不能访问。- public:公有类型public关键字后面声明,他们是类与外部的接口,任何外部函数都可以访问公有类的数据和函数。- protect:保护类型用于类的继承,当类的成员被声明为protect时,从类的外部就不能对其进行访问。类时面向对象程序最基本的单元。在设计面向对象程序时,首先要以类的方式设计实际待解决的问题,也就是将问题索要处理的数据定义成类的私有或公有类型数据,同时将处理问题的方法定义成类的公有或私有成员函数。11、对象对象时系统中用来描述客观事物的一个实体,它是构成系统的一个基本单位,有一组属性和对这组属性进行操作的一组服务组成。属性和服务是构成对象的两个基本要素,其定义是:属性是用来描述对象静态特征的一个数据项;服务是用来描述对象动态特征的一个操作序列。对象是类的实例,可以声明类时直接定义对象。此外,还可以在声明类之后再单独声明类对象。 Class example

{

Int I;

Public;

Float f;

Void fun();

};

Example A;对象声明后即可使用,使用方法如下:对象名.成员函数名和对象名,数据成员名例,可以按一下方式调用类example中的成员函数fun();A.fun();12、类和类之间的关系1.关联关系关联关系表示两个类之间存在某种语义上的联系,即与该关联链接的类的对象之间具有一定的语义链接关系,该关系表达了类之间的一种相关性。2.依赖关系依赖关系描述的是两个类之间的语义上的连接关系,它是一种Use-A关系。假设两个元素A与B,如果修改元素A的定义可能会一起对另一个元素B的定义的修改,则称元素B依赖于A。3.聚合关系聚合关系是一种Has-A关系,它体现的是类之间的一种整体与部分的关系。4.泛化关系泛化关系是一种Is-A关系,它描述的是类之间“一般”与“特殊”的关系。具有共同特性的元素可以抽象为一般类,并通过增加其内涵,进一步抽象成特殊类。改关系可以将类组成一种有层次,有分类的结构。13、多态性多态性是指类中具有相似功能的不同函数使用同一个名称实现。多态性的实现与联编有关。将一个函数的调用与其相应的函数体代码相链接的过程,成为函数联编。静态联编,动态联编编译时的多态性是通过静态联编来实现的。静态联编是指在调用同名函数时,编译器将根据调用时所使用的实际参数个数、类型的不同确定应该调用哪一个函数的实现,它是在程序编译阶段就确定下来的多态性。静态联编通过使用重载机制来获得,重载机制包括函数重载和运算符重载。14、形参和实参形参:全称为“形式参数”是在定义函数名和函数体的时候使用的参数,目的是用来接收调用该函数时传递的参数。形参的作用是实现主调函数与被调函数之间的联系,通常将函数所处理的数据,影响函数功能的因素或者函数处理的结果作为形参。没有形参的函数在形参表的位置应该写void.main 函数也可以有形参和返回值,其形参也称为命令行参数,由操作系统在启动程序时初始化,其返回值传递给操作系统。实参:可以是常量、变量、表达式、函数等, 无论实参是何种类型的量,在进行函数调用时,它们都必须具有确定的值, 以便把这些值传送给形参。 因此应预先用赋值,输入等办法使实参获得确定值。实参和形参的区别:空白或占位符1.函数的形参列于函数声明中,在函数定义的函数体内使用。当函数调用时,形参(任何种类的)是一类将被填充的空白或是占位符。用来填充形参2.实参是用来填充形参的。当函数被调用时,实参列在函数名后面的括号里。执行函数调用时,实参被传递给形参。传值调用和引用调用3.传值调用和引用调用指的是用于参数传递过程中的一种机制。传值调用中,只使用了实参的值。传值调用机制里,形参是一个局部变量,其初始值为相应实参的值。在引用调用机制里,将实参的地址传递给形参,从表面上看是以实参变量取代形参,因此任何发生在形参上的改变实际上都发生在实参变量上。15、运算符重载运算符重载本质上就是函数的重载,是函数重载的特殊形式(函数名为运算符号)。C++语言中允许程序员重新定义运算符的语义,这一机制称作运算符重载。16、正则表达式正则表达式又称正规表达式,常规表示法,计算机科学的一个概念。正则表达式使用单个字符串来描述。匹配一系列符合某个句法规则的字符串。在很多文本编辑器里,正则表达式常用来检索、替换那些符合摸个模式的文本。许多程序设计语言都支持利用正则表达式进行字符串操作。例如,在Perl中就内建了一个功能强大的正则表达式引擎。正则表达式这个概念最初是由Unix中的工具软件(例如sed和grep)普及开的。正则表达式通常缩写成“regex”,单数有regexp、regex,复数有regexps、regexes、regexen。正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。给定一个正则表达式和另一个字符串,我们可以达到如下的目的: 给定的字符串是否符合正则表达式的过滤逻辑(称作“匹配”); 可以通过正则表达式,从字符串中获取我们想要的特定部分。正则表达式的特点是: 灵活性、逻辑性和功能性非常的强; 可以迅速地用极简单的方式达到字符串的复杂控制。 对于刚接触的人来说,比较晦涩难懂。由于正则表达式主要应用对象是文本,因此它在各种文本编辑器场合都有应用,小到著名编辑器EditPlus,大到Microsoft Word、Visual Studio等大型编辑器,都可以使用正则表达式来处理文本内容。17、MFCMFC应用程序有自己特殊的运行机制,一般包括以下5步:调用CWinApp的构造函数。 程序入口函数WinMain接收控制。 WinMain调用应用程序类的InitInstance函数。 WinMain进入消息循环。 WinMain退出,程序终止。1、 应用程序类CTestApp从MFC的CWinApp类派生,对应的源文件Test.h和Test.cpp,为应用程序的入口,负责应用程序对象的定义与创建、程序的启动、命令行参数处理、主框架窗口的创建、文档模板的创建、文件菜单的处理、About对话框的创建和显示等。2、 主框架窗口类CmainFrame从MFC的CFrameWnd或CMDIFrameWnd派生,对应的源文件为MainFrm.h和MainFrm.cpp。为应用程序的界面,包含菜单栏、工具栏和状态栏,负责子框架窗口或视图类的创建。3、 字框架窗口类CchildFrame从MFC的CMDIChildWnd类派生,只有MDI程序才有,对应的源文件为ChildFram.h和ChildFrm.cpp,包含子框架窗口的标题条和边框,负责视图类的创建。 4、 文档类CtestDoc从MFC的CDocument类派生,对应的源文件为TestDoc.h和TestDoc.cpp,负责文件读写和数据处理。5、 视图类CTestView一般从MFC的CView类派生,也可以冲CScrollView等其他MFC视图类派生,对应的源文件TestView.h和TestView.cpp。对应于框架窗口的客户区,负责数据的显示、图形的绘制和用户的交互等。18、map的用法1、Map的简介Map是一类关联式容器。它的特点是增加和删除节点对迭代器的影响很小,除了那个操作节点,对其他的节点都没有什么影响。对于迭代器来说,可以修改实值,而不能修改key。2、map的功能自动建立Key - value的对应。key 和 value可以是任意你需要的类型。根据key值快速查找记录,查找的复杂度基本是Log(N),如果有1000个记录,最多查找10次,1,000,000个记录,最多查找20次。 快速插入Key - Value 记录。 快速删除记录 根据Key 修改value记录。 遍历所有记录。3、使用map使用map得包含map类所在的头文件 #include//STL头文件没有扩展名.hMap对象是模板类,需要关键字和存储对象两个模板参数,Std::mappersonal;这样就定义了一个用int作为索引,并拥有相关联的指向string的指针;为了使用方便,可以对模板类进行一下类型定义。Typedef mapUDT_MAP_INT_CSTRING;

UDT_MAP_INT_CSTRING enumMap;4、在map中插入元素改变map中的条目非常简单,因为map类已经对[]操作符进行了重载enumMap[1] = "One";

enumMap[2] = "Two";

.....这样非常直观,但存在一个性能的问题。插入2时,先在enumMap中查找主键为2的项,没发现,然后将一个新的对象插入enumMap,键是2,值是一个空字符串,插入完成后,将字符串赋为”Two”; 该方法会将每个值都赋为缺省值,然后再赋为显示的值,如果元素是类对象,则开销比较大。我们可以用以下方法来避免开销:enumMap.insert(map :: value_type(2, "Two"))19、删除文件到底如何查找文件呢?我们需要一个结构体和几个大家可能不太熟悉的函数。这些函数和结构体在的头文件中,结构体为struct _finddata_t ,函数为_findfirst、_findnext和_fineclose。具体如何使用,我会慢慢讲来~首先讲这个结构体吧~ struct _finddata_t ,这个结构体是用来存储文件各种信息的。说实话,这个结构体的具体定义代码,我没有找到,不过还好,文档里面在_find里有比较详细的成员变量介绍。我基本上就把文档翻译过来讲吧:unsigned atrrib: 文件属性的存储位置。它存储一个unsigned单元,用于表示文件的属性。文件属性是用位表示的,主要有以下一些:_A_ARCH(存档)、 _A_HIDDEN(隐藏)、_A_NORMAL(正常)、_A_RDONLY(只读)、_A_SUBDIR(文件夹)、_A_SYSTEM(系统)。这些都是在中定义的宏,可以直接使用,而本身的意义其实是一个无符号整型(只不过这个整型应该是2的几次幂,从而保证只有一位为 1,而其他位为0)。既然是位表示,那么当一个文件有多个属性时,它往往是通过位或的方式,来得到几个属性的综合。例如只读+隐藏+系统属性,应该为:_A_HIDDEN | _A_RDONLY | _A_SYSTEM 。time_t time_create: 这里的time_t是一个变量类型(长整型?相当于long int?),用来存储时间的,我们暂时不用理它,只要知道,这个time_create变量是用来存储文件创建时间的就可以了。time_t time_access: 文件最后一次被访问的时间。time_t time_write: 文件最后一次被修改的时间。_fsize_t size: 文件的大小。这里的_fsize_t应该可以相当于unsigned整型,表示文件的字节数。char name [_MAX_FNAME ]:文件的文件名。这里的_MAX_FNAME是一个常量宏,它在头文件中被定义,表示的是文件名的最大长度。以此,我们可以推测出,struct _finddata_t ,大概的定义如下: struct _finddata_t

{

unsigned attrib;

time_t time_create;

time_t time_access;

time_t time_write;

_fsize_t size;

char name[_MAX_FNAME];

}; 前面也说了,这个结构体是用来存储文件信息的,那么如何把一个硬盘文件的文件信息“存到”这个结构体所表示的内存空间里去呢?这就要靠_findfirst、_findnext和_fineclose三个函数的搭配使用了。

首先还是对这三个函数一一介绍一番吧……

long _findfirst( char *filespec, struct _finddata_t *fileinfo );

返回值: 如果查找成功的话,将返回一个long型的唯一的查找用的句柄(就是一个唯一编号)。这个句柄将在_findnext函数中被使用。若失败,则返回-1。

参数:

filespec:标明文件的字符串,可支持通配符。比如:*.c,则表示当前文件夹下的所有后缀为C的文件。

fileinfo :这里就是用来存放文件信息的结构体的指针。这个结构体必须在调用此函数前声明,不过不用初始化,只要分配了内存空间就可以了。函数成功后,函数会把找到的文件的信息放入这个结构体中。

int _findnext( long handle, struct _finddata_t *fileinfo );

返回值: 若成功返回0,否则返回-1。

参数:

handle:即由_findfirst函数返回回来的句柄。

fileinfo:文件信息结构体的指针。找到文件后,函数将该文件信息放入此结构体中。

int _findclose( long handle );

返回值: 成功返回0,失败返回-1。

参数:

handle :_findfirst函数返回回来的句柄。 大家看到这里,估计都能猜到个大概了吧?先用_findfirst查找第一个文件,若成功则用返回的句柄调用_findnext函数查找其他的文件,当查找完毕后用,用_findclose函数结束查找。恩,对,这就是正确思路。下面我们就按照这样的思路来编写一个查找C:/WINDOWS文件夹下的所有 exe可执行文件的程序。

#include

#include

const char *to_search="C://WINDOWS//*.exe"; //欲查找的文件,支持通配符

int main()

{

long handle; //用于查找的句柄

struct _finddata_t fileinfo; //文件信息的结构体

handle=_findfirst(to_search,&fileinfo); //第一次查找

if(-1==handle)return -1;

printf("%s/n",fileinfo.name); //打印出找到的文件的文件名

while(!_findnext(handle,&fileinfo)) //循环查找其他符合的文件,知道找不到其他的为止

{

printf("%s/n",fileinfo.name);

}

_findclose(handle); //别忘了关闭句柄

system("pause");

return 0;

} 当然,这个文件的查找是在指定的路径中进行,如何遍历硬盘,在整个硬盘中查找文件呢?大家可以在网络上搜索文件递归遍历等方法,这里不再做进一步介绍。

细心的朋友可能会注意到我在程序的末尾用了一个system函数。这个与程序本身并没有影响,和以前介绍给大家的使用getchar()函数的作用相同,只是为了暂停一下,让我们能看到命令提示符上输出的结果而已。不过system函数本身是一个非常强大的函数。大家可以查查MSDN看看~ 简单来说,它是一个C语言与操作系统的相互平台,可以在程序里通过这个函数,向操作系统传递command命令。这个简单的函数会在下一篇的文章中大放异彩,大家拭目以待吧~~

20判断文件类型 for example:

printf("File type: ");

switch (sb.st_mode & S_IFMT) {

case S_IFBLK: printf("block device\n"); break;

case S_IFCHR: printf("character device\n"); break;

case S_IFDIR: printf("directory\n"); break;

case S_IFIFO: printf("FIFO/pipe\n"); break;

case S_IFLNK: printf("symlink\n"); break;

case S_IFREG: printf("regular file\n"); break;

case S_IFSOCK: printf("socket\n"); break;

default: printf("unknown?\n"); break;

}

#include 主要是对磁盘文件路径进行操作的函数

#include 目录遍历

#include 主要是输入输出的函数

#include 主要是字符串函数 例如:strcpy

#include 基本系统数据类型 win32 api21、遍历文件夹 C++下遍历文件夹编写程序遍历文件夹及其子文件夹下所有文件,并输出到标准输出流或者文件流。1. 先考虑在单层目录下,遍历所有文件。以C:\WINDOWS为例:用到数据结构_finddata_t,文件信息结构体的指针。struct _finddata_t

{

unsigned attrib; //文件属性

time_t time_create; //文件创建时间

time_t time_access; //文件上一次访问时间

time_t time_write; //文件上一次修改时间

_fsize_t size; //文件字节数

char name[_MAX_FNAME]; //文件名

}; 文件属性是无符号整数,取值为相应的宏:_A_ARCH(存档),_A_SUBDIR(文件夹),_A_HIDDEN(隐藏),_A_SYSTEM(系统),_A_NORMAL(正常),_A_RDONLY(只读)。容易看出,通过这个结构体,我们可以得到关于该文件的很多信息。结合以下函数,我们可以将文件信息存储到这个结构体中://按FileName命名规则匹配当前目录第一个文件

_findfirst(_In_ const char * FileName, _Out_ struct _finddata64i32_t * _FindData);

//按FileName命名规则匹配当前目录下一个文件

_findnext(_In_ intptr_t _FindHandle, _Out_ struct _finddata64i32_t * _FindData);

//关闭_findfirst返回的文件句柄

_findclose(_In_ intptr_t _FindHandle);

_findfirst 函数返回的是匹配到文件的句柄,数据类型为long。遍历过程可以指定文件类型,这通过FileName的赋值来实现,例如要遍历C:\WINDOWS下的所有.exe文件

bool transfer(string fileName = "C:\\Windows\\*.exe", int exeNum = 0)

{

_finddata_t fileInfo;

long handle = _findfirst(fileName.c_str(), &fileInfo);

if (handle == -1L)

{

cerr << "failed to transfer files" << endl;

return false;

}

do

{

exeNum ++;

cout << fileInfo.name LRESULT Dlg::OnNotifyIcon(WPARAM wParam, LPARAM lParam){在最后加上return TRUE;}3.将afx_msg void OnNotifyIcon(WPARAM wParam, LPARAM lParam)->该成afx_msg LRESULT OnNotifyIcon(WPARAM wParam, LPARAM lParam);编译下就成功了23、树形控件 树形控件在Windows系统中很常见,树形视图中以分层结构显示数据,每层的缩进不同,层次越低缩进越多。属性控件的节点一般都由标签和图标两部分组成,图标用来抽象的描述数据,能够使树形控件的层次关系更加清晰。树形控件插入新的树节点时需要制定新节点与已有节点的关系。TVN_SELCHANGING和TVN_SELCHANGED:在用户改变了对树节点的选择时,控件会发送这两个消息。消息会附带一个指向NMTREEVIEW结构的指针,程序可从该结构中获得必要的信息。两个消息都会在该结构的itemOld成员中包含原来的选择项信息,在itemNew成员中包含新选择项的信息,在action成员中表明是用户的什么行为触发了该通知消息(若是TVC_BYKEYBOARD则表明是键盘,若是TVC_BYMOUSE则表明是鼠标,若是TVC_UNKNOWN则表示未知)。两个消息的不同之处在于,如果TVN_SELCHANGING的消息处理函数返回TRUE,那么就阻止选择的改变,如果返回FALSE,则允许改变。

TVN_KEYDOWN:该消息表明了一个键盘事件。消息会附带一个指向NMTVKEYDOWN结构的指针,通过该结构程序可以获得按键的信息。

TVN_BEGINLABELEDIT和TVN_ENDLABELEDIT:分别在用户开始编辑和结束编辑节点的标签时发送。消息会附带一个指向NMTVDISPINFO结构的指针,程序可从该结构中获得必要的信息。在前者的消息处理函数中,可以调用GetEditControl()成员函数返回一个指向用于编辑标题的编辑框的指针。如果处理函数返回FALSE,则允许编辑,如果返回TRUE,则禁止编辑。在后者的消息处理函数中,NMTVDISPINFO结构中的item.pszText指向编辑后的新标题,如果pszText为NULL,那么说明用户放弃了编辑,否则,程序应负责更新节点的标签,这可以由SetItem()或SetItemText()函数来完成。树形控件的创建也是有两种方式,一种是在对话框模板中直接拖入Tree Control控件创建,另一种就是通过CTreeCtrl类的Create成员函数创建。下面主要讲后者。CTreeCtrl类的Create成员函数的原型如下: virtual BOOL Create(

DWORD dwStyle,

const RECT& rect,

CWnd* pParentWnd,

UINT nID

); 此函数的原型与前面讲到的所有控件类的Create函数都类似。dwStyle指定树形控件风格的组合,rect指定树形控件窗口的位置和大小,pParentWnd为指向树形控件父窗口的指针,nID指定树形控件的ID。

CTreeCtrl类的主要成员函数CImageList* SetImageList(CImageList * pImageList,int nImageListType);如果树节点需要显示图标时,则必须先创建一个CImageList类的对象,并为其添加多个图像组成一个图像序列,然后调用SetImageList函数为树形控件设置图像序列,在用InsertItem插入节点时传入所需图像在图像序列中的索引即可。后面的例子中会演示。参数pImageList为指向图像序列类CImageList的对象的指针,若为NULL则删除树形控件的所有图像。参数nImageListType指定图像序列的类型,可以是TVSIL_NORMAL(普通图像序列)或TVSIL_STATE(状态图像序列,用图像表示节点的状态)。UINT GetCount( ) const;获取树形控件中节点的数量。DWORD_PTR GetItemData(HTREEITEM hItem) const;获取树形控件中某个指定节点的附加32位数据。参数hItem为指定的树节点的句柄。BOOL SetItemData(HTREEITEM hItem,DWORD_PTR dwData);为树形控件中某个指定节点设置附加的32位数据。参数hItem同上,dwData为要设置的32位数据。CString GetItemText(HTREEITEM hItem) const;获取树形控件中某个指定节点的标签文本。参数hItem同上。返回值是包含标签文本的字符串。BOOL SetItemText(HTREEITEM hItem,LPCTSTR lpszItem);为树形控件中某个指定节点设置标签文本。参数hItem同上,lpszItem为包含标签文本的字符串的指针。HTREEITEM GetNextSiblingItem(HTREEITEM hItem) const;获取树形控件中某个指定节点的下一个兄弟节点。参数hItem同上。返回值是下一个兄弟节点的句柄。HTREEITEM GetPrevSiblingItem(HTREEITEM hItem) const;获取树形控件中某个指定节点的上一个兄弟节点。参数hItem同上。返回值是上一个兄弟节点的句柄。HTREEITEM GetParentItem(HTREEITEM hItem) const;获取树形控件中某个指定节点的父节点。参数hItem同上。返回值是父节点的句柄。HTREEITEM GetRootItem( ) const;获取树形控件根节点的句柄。HTREEITEM GetSelectedItem( ) const;获取树形控件当前选中节点的句柄。BOOL DeleteAllItems( );删除树形控件中的所有节点。删除成功则返回TRUE,否则返回FALSE。BOOL DeleteItem(HTREEITEM hItem);删除树形控件中的某个节点。参数hItem为要删除的节点的句柄。删除成功则返回TRUE,否则返回FALSE。HTREEITEM InsertItem(LPCTSTR lpszItem,int nImage,int nSelectedImage,HTREEITEM hParent = TVI_ROOT,HTREEITEM hInsertAfter = TVI_LAST);在树形控件中插入一个新节点。参数lpszItem为新节点的标签文本字符串的指针,参数nImage为新节点的图标在树形控件图像序列中的索引,参数nSelectedImage为新节点被选中时的图标在图像序列中的索引,参数hParent为插入节点的父节点的句柄,参数hInsertAfter为新节点的前一个节点的句柄,即新节点将被插入到hInsertAfter节点之后。BOOL SelectItem(HTREEITEM hItem);选中指定的树节点。参数hItem为要选择的节点的句柄。若成功则返回TRUE,否则返回FALSE。24、列表视图控件 列表视图控件能够把热河字符串内容以列表的方式显示出来,这种显示方式的特点是整洁、直观、在实际应用中能为用户带来方便。列表视图控件是对列表框控件的改进和延伸。列表视图控件的列表项一般有图标和标签两部分。图标是对列表项的图形描述,标签是文字描述。当然列表项可以只包含图标也可以只包含标签。列表视图控件有4中风格:Icon,Small Icon,List和Report。列表视图控件的创建MFC同样为列表视图控件的操作提供了CListCtrl类。如果我们不想在对话框模板中直接拖入List Control来使用列表视图控件,而是希望动态创建它,则要用到CListCtrl类的成员函数Create函数,原型如下:virtual BOOL Create(

DWORD dwStyle,

const RECT& rect,

CWnd* pParentWnd,

UINT nID

); 参数rect为列表视图控件的位置和尺寸,pParentWnd为指向父窗口的指针,nID指定列表视图控件的ID,最复杂的一个参数同样还是dwStyle,它用于设定列表视图控件的风格,可以是以下风格的组合:

风格 含义

LVS_ALIGNLEFT 显示格式是大图标或小图标时,标签放在图标的左边

LVS_ALIGNTOP 显示格式是大图标或小图标时,标题放在图标的上边

LVS_AUTOARRANGE 显示格式是大图标或小图标时,自动排列控件中的列表项

LVS_EDITLABELS 用户可以修改标签文本

LVS_ICON 指定大图标显示格式

LVS_LIST 指定列表显示格式

LVS_NOCOLUMNHEADER 在报表格式中不显示列的表头

LVS_NOLABELWRAP 显示格式是大图标时,使标签文本单行显示。默认是多行显示

LVS_NOSCROLL 列表视图控件无滚动条,此风格不能与LVS_LIST或LVS_REPORT组合使用

LVS_NOSORTHEADER 报表格式的列表视图控件的表头不能作为排序按钮使用

LVS_OWNERDRAWFIXED 由控件的拥有者负责绘制表项

LVS_REPORT 指定报表显示格式

LVS_SHAREIMAGELISTS 使列表视图共享图像序列

LVS_SHOWSELALWAYS 即使控件失去输入焦点,仍显示出项的选择状态

LVS_SINGLESEL 指定只能有一个列表项被选中。默认时可以多项选择

LVS_SMALLICON 指定小图标显示格式

LVS_SORTASCENDING 按升序排列列表项

LVS_SORTDESCENDING 按降序排列列表项 与前面的控件一样,除了以上风格一般我们还要为列表视图控件设置WS_CHILD和WS_VISIBLE风格。对于直接在对话框模板中创建的列表视图控件,其属性页中的属性与上述风格是对应的,例如,属性Alignment默认为Left,也就等价于指定了LVS_ALIGNLEFT风格。

CListCtrl类的主要成员函数

CListCtrl类有很多成员函数,鸡啄米这里就为大家介绍几个常用的主要成员函数。

UINT GetSelectedCount( ) const;

该函数返回列表视图控件中被选择列表项的数量。

POSITION GetFirstSelectedItemPosition( ) const;

获取列表视图控件中第一个被选择项的位置。返回的POSITION值可以用来迭代来获取其他选择项,可以当作参数传入下面的GetNextSelectedItem函数来获得选择项的索引。如果没有被选择项则返回NULL。

int GetNextSelectedItem(POSITION& pos) const;

该函数获取由pos指定的列表项的索引,然后将pos设置为下一个位置的POSITION值。参数pos为之前调用GetNextSelectedItem或GetFirstSelectedItemPosition得到的POSITION值的引用。返回值就是pos指定列表项的索引。

int GetItemCount( ) const;

获取列表视图控件中列表项的数量。

int InsertColumn(int nCol,const LVCOLUMN* pColumn );

int InsertColumn(int nCol,LPCTSTR lpszColumnHeading,int nFormat = LVCFMT_LEFT,int nWidth = -1,int nSubItem = -1 );

这两个函数用于在报表式列表视图控件中插入列。第一个函数中,nCol参数为插入列的索引,pColumn参数指向LVCOLUMN结构,其中包含了插入列的属性。第二个函数中,nCol参数也是插入列的索引,lpszColumnHeading参数为列标题字符串,nFormat参数为列中文本的对齐方式,可以是LVCFMT_LEFT、LVCFMT_RIGHT或LVCFMT_CENTER,nWidth参数为列宽,nSubItem为插入列对应列表子项的索引。两个函数在成功时都返回新列的索引,失败都返回-1。

BOOL DeleteColumn(int nCol);

该函数用于删除列表视图控件中的某列。参数nCol为删除列的索引。删除成功则返回TRUE,失败返回FALSE。

int InsertItem(int nItem,LPCTSTR lpszItem);

向列表视图控件中插入新的列表项。参数nItem为要插入项的索引,参数lpszItem为要插入项的标签字符串。如果插入成功则返回新列表项的索引,否则返回-1。

BOOL DeleteItem(int nItem);

从列表视图控件中删除某个列表项。参数nItem指定了要删除的列表项的索引。删除成功则返回TRUE,否则返回FALSE。

CString GetItemText(int nItem,int nSubItem) const;

获取指定列表项或列表子项的显示文本。参数nItem指定了列表项的索引,参数nSubItem指定了列表子项的索引。

BOOL SetItemText(int nItem,int nSubItem,LPCTSTR lpszText);

设置指定列表项或列表子项的显示文本。参数nItem和nSubItem同GetItemText。参数lpszText为要设置的显示文本字符串。如果设置成功则返回TRUE,否则返回FALSE。

DWORD_PTR GetItemData(int nItem) const;

该函数用于获取指定列表项的附加32位数据。参数nItem为列表项的索引。返回值就是由nItem指定列表项的附加32位数据。

BOOL SetItemData(int nItem,DWORD_PTR dwData);

该函数用于为指定列表项设置附加32位是数据。参数nItem为列表项的索引,参数dwData为列表项的附加32位数据。

25、CString类 CString类作为MFC的常用类,只要是从事MFC开发,基本都会遇到使用CString类的场合。因为字符串的使用比较普遍,而CString类又提供了对字符串的便捷操作,所以它给MFC开发人员带来了高的开发效率。使用VS2010的话,可能会见到CStringT,实际上它是一个操作可变长度字符串的模板类。CStringT模板类有三个实例:CString、CStringA和CStringW,它们分别提供对TCHAR、char和wchar_t字符类型的字符串的操作。char类型定义的是Ansi字符,wchar_t类型定义的是Unicode字符,而TCHAR取决于MFC工程的属性对话框中的Configuration Properties->General->Character Set属性,如果此属性为Use Multi-Byte Character Set,则TCHAR类型定义的是Ansi字符,而如果为Use Unicode Character Set,则TCHAR类型定义的是Unicode字符。CString类又很多构造函数:CString(const CString&tringSrc);将一个已经存在的CString对象stringSrc的内容拷贝到该CString对象。例如:1. CString str1(_T("panda")); // 将常量字符串拷贝到str1

2. CString str2(str1); // 将str1的内容拷贝到str2

CString(LPCTSTR lpch, int nLength);

将字符串lpch中的前nLength个字符拷贝到该CString对象。例如:CString str(_T(“panda”),3); // 构造的字符串对象内容为”pan” CString(TCHAR ch, int nLength = 1);使用此函数构造的CString对象中将含有nLength个重复的ch字符。例如:CString str(_T(‘p’),3); // str为”ppp” CString类的大小写转换及顺序转换函数CString& MakeLower();将字符串中的所有大写字符转换为小写字符。CString& MakeUpper();将字符串中的所有小写字符转换为大写字符。CString& MakeReverse();将字符串中所有字符的顺序颠倒。例如: CString str(_T(“JiZhuoMi”)); str.MakeLower(); // str为”jizhuomi” str.MakeUpper(); // str为”JIZHUOMI” str.MakeReverse(); // str为”IMOUHZIJ”CString对象的连接多个CString对象的连接可以通过重载运算符+、+=实现。例如:C++代码 CString str(_T(“panda”)); // str内容为”panda” str = _T(“kongfun”) + str + _T(“.”); // str为”kongfunpanda.” str += _T(“net”); // str为”kongfunpanda.net”CString对象的比较CString对象的比较可以通过==、!=、<、>、<=、>=等重载运算符实现,也可以使用Compare和CompareNoCase成员函数实现。int Compare(PCXSTR psz) const;将该CString对象与psz字符串比较,如果相等则返回0,如果小于psz则返回值小于0,如果大于psz则返回值大于0。int CompareNoCase(PCXSTR psz) const throw();此函数与Compare功能类似,只是不区分大小写。例如:C++代码 CString str1 = _T(“JiZhuoMi”); CString str2 = _T(“jizhuomi”); if (str1 == str2) { // 因为str1、str2不相等,所以不执行下面的代码 … } if (0 == str1.CompareNoCase(str2)) { // 因为不区分大小写比较时,CompareNoCase函数返回0,所以执行下面的代码 … }CString对象字符串的提取操作CString Left(int nCount) const;提取该字符串左边nCount个字符的子字符串,并返回一个包含这个子字符串的拷贝的CString对象。CString Right(int nCount) const;提取该字符串右边nCount个字符的子字符串,并返回一个包含这个子字符串的拷贝的CString对象。CString Mid(int iFirst,int nCount) const;提取该字符串中以索引iFirst位置开始的nCount个字符组成的子字符串,并返回一个包含这个子字符串的拷贝的CString对象。CString Mid(int iFirst) const;提取该字符串中以索引iFirst位置开始直至字符串结尾的子字符串,并返回一个包含这个子字符串的拷贝的CString对象。例如:C++代码 CString str1 = _T(“kongfunpanda”); CString str2 = str1.Left(3); // str2为”kon” str2 = str1.Right(2); // str2为”da” str2 = str1.Mid(1,3); // str2为”ong” str2 = str1.Mid(5); // str2为”unpanda”CString对象字符串的查找操作int Find(PCXSTR pszSub,int iStart=0) const throw( );int Find(XCHAR ch,int iStart=0) const throw( );在CString对象字符串的iStart索引位置开始,查找子字符串pszSub或字符ch第一次出现的位置,如果没有找到则返回-1。int FindOneOf(PCXSTR pszCharSet) const throw( );查找pszCharSet字符串中的任意字符,返回第一次出现的位置,找不到则返回-1。int ReverseFind(XCHAR ch) const throw();从字符串末尾开始查找指定的字符ch,返回其位置,找不到则返回-1。这里要注意,尽管是从后向前查找,但是位置的索引还是要从开始算起。C++代码 CString str = _T(“panda”); int nIndex1 = str.Find(_T(“an”)); // nIndex1的值为1 int nIndex2 = str.FindOneOf(_T(“nad”)); // nIndex2的值为1 int nIndex3 = str.ReverseFind(_T(‘d’)); // nIndex3的值为3CString类对象字符串的替换与删除int Replace(PCXSTR pszOld,PCXSTR pszNew);用字符串pszNew替换CString对象中的子字符串pszOld,返回替换的字符个数。int Replace(XCHAR chOld,XCHAR chNew);用字符chNew替换CString对象中的字符chOld,返回替换的字符个数。int Delete(int iIndex,int nCount = 1);从字符串中删除iIndex位置开始的nCount个字符,返回删除操作后的字符串的长度。int Remove(XCHAR chRemove);删除字符串中的所有由chRemove指定的字符,返回删除的字符个数。例如:C++代码 CString str = _T(“panda”); int n1 = str.Replace(_T(‘a’), _T(‘b’)); // str为”pbndb”,n1为2 int n2 = str.Delete(1,2); // str为”pdb”,n2为3 int n3 = str.Remove(_T(‘d’)); // str为”pb”,n3为1CString类的格式化字符串方法使用CString类的Format成员函数可以将int、short、long、float、double等数据类型格式化为字符串对象。void __cdecl Format(PCXSTR pszFormat,[, argument]…);参数pszFormat为格式控制字符串;参数argument可选,为要格式化的数据,一般每个argument在pszFormat中都有对应的表示其类型的子字符串,int型的argument对应的应该是”%d”,float型的应对应”%f”,等等。例如:C++代码 CString str; int a = 1; float b = 2.3f; str.Format(_T(“a=%d,b=%f”), a, b); // str为”a=1,b=2.300000”26、C++_MFC如何遍历整个目录树查找文件  在应用程序的开发过程中,会遇到如何查找某一文件以确定此文件路径的问题。利用CFileFind类可以比较方便地在当前目录下进行文件查找,但却不能对其子目录中的文件进行搜寻。而实际应用中往往需要对某一整个目录树,甚至是整个C盘或D盘驱动器进行文件搜寻。通过实践,我们在Visual C++ 6.0中编程实现了如何遍历任意目录树,以查找某一特定的文件。  在下面的具体陈述中可以看到,在确定要查找的文件名和要进行搜索的目录的名称后,将调用函数Search_Directory进行文件的查找。首先依次查找当前目录下的每一个实体(文件或是子目录),如果是某一子目录,则进入该子目录并递归调用函数Search_Dirctory进行查找,查找完毕之后, 再返回上一级目录;如果不是子目录而是某一文件,则判断其是否就是我们要查找的文件,如果是则输出其完整的文件路径。这样,通过Search_Directory函数的反复递归调用,就可以实现对整个目录,包括子目录的遍历搜索。下面将举例详细讲述如何在VC++中编程实现在整个目录树中的文件查找。  1. 在Visual C++ 6.0中用默认方式创建了一基于对话框的应用程序Search。在主窗口对话框上放置一命令按钮,其Caption为“Search File”,ID为ID_BUTTON_SEARCH。单击此按钮将完成文件的查找工作。  2. 利用ClassWizard为“Search File”按钮的BN_CLICKED 事件添加处理函数OnButtonSearch,代码如下:#include 〈direct.h〉#include 〈io.h〉void CSearchDlg::OnButtonSearch(){// TODO: Add your control notification handler code herechar szFilename[80];// 字符串 szFilename 表示要查找的文件名strcpy(szFilename,”Mytext.txt”);_chdir(“d:\”); // 进入要查找的路径(也可为某一具体的目录)// 查找文件, 如果查到则显示文件的路径全名Search_Directory(szFilename);// 为CSearchDlg类的一成员函数MessageBox(″查找文件完毕!″);// 显示查找完毕的信息}  3. 在CSearchDlg类中增加成员函数Search_Directory,它将完成具体的文件查找工作,代码如下:void CSearchDlg::Search_Directory(char* szFilename)

{

long handle;

struct _finddata_t filestruct;

//表示文件(或目录)的信息

char path_search[_MAX_PATH];

//表示查找到的路径结果

// 开始查找工作, 找到当前目录下的第一个实体(文件或子目录),

// "*"表示查找任何的文件或子目录, filestruct为查找结果

handle = _findfirst("*", &filestruct);

// 如果handle为-1, 表示当前目录为空, 则结束查找而返回

if((handle == -1)) return;

// 检查找到的第一个实体是否是一个目录(filestruct.name为其名称)

if( ::GetFileAttributes(filestruct.name) & FILE_ATTRIBUTE_DIRECTORY )

{

// 如果是目录, 则进入该目录并递归调用函数Search_Dirctory进行查找,

// 注意: 如果目录名的首字符为'.'(即为"."或".."), 则不用进行查找

if( filestruct.name[0] != '.' )

{

_chdir(filestruct.name);

Search_Directory(szFilename);

// 查找完毕之后, 返回上一级目录

_chdir("..");

}

}

else // 如果第一个实体不是目录, 则检查是否是要查找的文件

{

// stricmp对两字符串进行小写形式的对比, 返回为0表示完全一致

if( !stricmp(filestruct.name, szFilename) )

{

// 先获得当前工作目录的全路径

_getcwd(path_search,_MAX_PATH);

// 再获得文件的完整的路径名(包含文件的名称)

strcat(path_search,"\\");

strcat(path_search,filestruct.name);

MessageBox(path_search); //输出显示

}

}

// 继续对当前目录中的下一个子目录或文件进行与上面同样的查找

while(!(_findnext(handle,&filestruct)))

{

if( ::GetFileAttributes(filestruct.name) & FILE_ATTRIBUTE_DIRECTORY )

{

if(*filestruct.name != '.')

{

_chdir(filestruct.name);

Search_Directory(szFilename);

_chdir("..");

}

}

else

{

if(!stricmp(filestruct.name,szFilename))

{

_getcwd(path_search,_MAX_PATH);

strcat(path_search,"\\");

strcat(path_search,filestruct.name);

MessageBox(path_search);

}

}

}

_findclose(handle);

// 最后结束整个查找工作

}  这样我们就可以对整个目录进行遍历搜索,查找某一特定的文件,并输出显示其完整的文件路径。以上的程序在Visual C++ 6.0中已调试通过。27、两种方法实现MFC 对话框最大化时控件也随比例最大化或者还原 方法一:单个控件ID操作第一步、在对话框类中(.h文件)定义如下变量和函数定义如下几个变量:[cpp] view plaincopy

1. void ReSize(int nID);

2. BOOL change_flag;

3. float m_Multiple_height;

4. float m_Multiple_width;

[cpp] view plaincopy

1. afx_msg void OnSize(UINT nType, int cx, int cy); 第二步、在OnInitDialog()中 计算出当前对话框的大小与最大化后大小[cpp] view plaincopy

1. CRect rect;

2. ::GetWindowRect(m_hWnd,rect);//这里m_hWnd为窗口句柄,如果不存在此变量则在该行代码前加一句:HWND h_Wnd=GetSafeHwnd( );

3. ScreenToClient(rect);

4. LONG m_nDlgWidth = rect.right - rect.left;

5. LONG m_nDlgHeight = rect.bottom - rect.top;

6. //Calc 分辨率

7. LONG m_nWidth = GetSystemMetrics(SM_CXSCREEN);

8. LONG m_nHeight = GetSystemMetrics(SM_CYSCREEN);

9. //计算放大倍数(要用float值,否则误差很大)

10. m_Multiple_width = float(m_nWidth)/float(m_nDlgWidth);

11. m_Multiple_height = float(m_nHeight)/float(m_nDlgHeight);

12. change_flag = TRUE;//用来判断OnSize执行时,OninitDialg是否已经执行了 第三步、给对话框添加 WM_SIZE消息[cpp] view plaincopy

1. //给对话框添加 VM_SIZE消息

2. void CStuDemoDlg::OnSize(UINT nType, int cx, int cy)

3. {

4. CDialog::OnSize(nType, cx, cy);

5.

6. // TODO: Add your message handler code here

7. if (change_flag)//如果OninitDlg已经调用完毕

8. {

9. ReSize(IDC_STATIC_1);

10. ReSize(IDC_STATIC_2);

11. ReSize(IDC_EDIT11);//

12. ReSize(IDC_EDIT12);//

13. ReSize(IDC_LIST_SHOW);//LIST

14. ReSize(IDC_BUTTON_ADD);

15. ReSize(IDC_BUTTON_DEL);

16. ReSize(IDOK);

17. ReSize(IDCANCEL);

18. //恢复放大倍数,并保存 (确保还原时候能够还原到原来的大小)

19. m_Multiple_width = float(1)/m_Multiple_width;

20. m_Multiple_height = float(1)/m_Multiple_height;

21. }

22. } 第四步、刷新控件:根据比例计算控件缩放的大小,然后movewindow 到新矩形上[cpp] view plaincopy

1. void CStuDemoDlg::ReSize(int nID)

2. {

3. CRect Rect;

4. GetDlgItem(nID)->GetWindowRect(Rect);

5. ScreenToClient(Rect);

6. //计算控件左上角点

7. CPoint OldTLPoint,TLPoint;

8. OldTLPoint = Rect.TopLeft();

9. TLPoint.x = long(OldTLPoint.x *m_Multiple_width);

10. TLPoint.y = long(OldTLPoint.y * m_Multiple_height );

11. //计算控件右下角点

12. CPoint OldBRPoint,BRPoint; OldBRPoint = Rect.BottomRight();

13. BRPoint.x = long(OldBRPoint.x *m_Multiple_width);

14. BRPoint.y = long(OldBRPoint.y * m_Multiple_height );

15. //移动控件到新矩形

16. Rect.SetRect(TLPoint,BRPoint);

17. GetDlgItem(nID)->MoveWindow(Rect,TRUE);

18. } 方法二:集体控件操作第一步、在对话框类中(.h文件)定义如下变量和函数[cpp] view plaincopy

1. void ReSize();

2. POINT old;

[cpp] view plaincopy

1. afx_msg void OnSize(UINT nType, int cx, int cy); 第二步、在OnInitDialog()中 计算出原始对话框的大小[cpp] view plaincopy

1. CRect rect;

2. GetClientRect(&rect); //取客户区大小

3. old.x=rect.right-rect.left;

4. old.y=rect.bottom-rect.top; 第三步、添加 WM_SIZE消息[cpp] view plaincopy

1. void CStuDemoDlg::OnSize(UINT nType, int cx, int cy)

2. {

3. CDialog::OnSize(nType, cx, cy);

4. // TODO: Add your message handler code here

5. if (nType==SIZE_RESTORED||nType==SIZE_MAXIMIZED)

6. {

7. ReSize();

8. }

9. } 第四步、刷新控件函数[cpp] view plaincopy

1. void CStuDemoDlg::ReSize()

2. {

3. float fsp[2];

4. POINT Newp; //获取现在对话框的大小

5. CRect recta;

6. GetClientRect(&recta); //取客户区大小

7. Newp.x=recta.right-recta.left;

8. Newp.y=recta.bottom-recta.top;

9. fsp[0]=(float)Newp.x/old.x;

10. fsp[1]=(float)Newp.y/old.y;

11. CRect Rect;

12. int woc;

13. CPoint OldTLPoint,TLPoint; //左上角

14. CPoint OldBRPoint,BRPoint; //右下角

15. HWND hwndChild=::GetWindow(m_hWnd,GW_CHILD); //列出所有控件

16. while(hwndChild)

17. {

18. woc=::GetDlgCtrlID(hwndChild);//取得ID

19. GetDlgItem(woc)->GetWindowRect(Rect);

20. ScreenToClient(Rect);

21. OldTLPoint = Rect.TopLeft();

22. TLPoint.x = long(OldTLPoint.x*fsp[0]);

23. TLPoint.y = long(OldTLPoint.y*fsp[1]);

24. OldBRPoint = Rect.BottomRight();

25. BRPoint.x = long(OldBRPoint.x *fsp[0]);

26. BRPoint.y = long(OldBRPoint.y *fsp[1]);

27. Rect.SetRect(TLPoint,BRPoint);

28. GetDlgItem(woc)->MoveWindow(Rect,TRUE);

29. hwndChild=::GetWindow(hwndChild, GW_HWNDNEXT);

30. }

31. old=Newp;

32. } 总结:就个人而言,本人还是比较倾向第二种方法,毕竟可以少操作控件ID,否则少了一个布局都会发生变化。版权声明:本文为博主原创文章,未经博主允许不得转载。28、1.#include #include

void SearchFile(const char* FileName, const char* Path, TStrings* Strings)

{

char *Name;

char File[512];

struct ffblk blk;

strcpy(File, Path);

Name = File+strlen(File);

if (*(Name-1)!='\\') *Name++ = '\\';

strcpy(Name, "*.*");

if (findfirst(File,&blk,FA_RDONLY|

FA_HIDDEN|FA_SYSTEM|FA_DIREC))

return;

do {

strcpy(Name, blk.ff_name);

if (blk.ff_attrib&FA_DIREC) {

if (*Name != '.')

SearchFile(FileName, File, Strings);

}

else if(strcmpi(Name,FileName))

Strings->Add(File);

}while(findnext(&blk)==0);

findclose(&blk); /* 有些编译器没有findclose,这行去掉 */

}

TStringList* SearchFile(const char* FileName)

{

char buf[128];

TStringList* Strings;

Strings = new TStringList;

GetLogicalDriveStrings(128, buf);

for(char* s=buf; *s!=0; s+=strlen(s)+1) {

SearchFile(FileName, s, Strings);

}

return Strings;

} 我原来写过的一个程序中的代码: void __fastcall SearchTxtDocFile::Execute()

{

DWORD AllDrives=GetLogicalDrives();

if (AllDrives==0)

return;

AnsiString Dir;

char d;

for(int i=2; i<26; i++)

{

if (AllDrives & (1<先取的所有盘,然后遍历

- 刚学BCB时写过,你在#codego.net#的软件里找“文件遍历”,有源码

- 29、C++内存分配函数Malloca/alloca:

1、在调用alloca的函数返回的时候,它分配的内存会自动释放。也就是说,用alloca分配的内存在栈上。所以释放不需要用户使用free。

2、alloca不具可移植性,而且在没有传统堆栈的机器上很难实现。当它的返回值直接传入另一个函数时会带来问题,因为他分配在栈上。

总结:由于这些原因,alloca不宜使用在必须广泛移植的程序中,不管它可能多么有用。

Realloca:

重新分配内存并返回void类型,如果没有足够的内存扩展内存块,则原来的指向的内存指针无变化,并返回NULL;如果重新分配大小设为0,而释放原来的内存块,并返回NULL。

Calloc:

分配指定数目的元素,每个元素的大小由size指定,并将其初始化为0,calloc调用malloc使用C++_set_new_mode函数来设置新的处理方式,默认情况下,malloc失败时不调用分配内存的处理程序例程。

Malloc:

从堆上分配指定大小的字节数并返回void类型,如分配失败则返回NULL,malloc分配的字节数可能比指定的字节要多,这是由内存对奇方式决定的,malloc实际上调用了HeapAlloc函数,因此malloc分配的内存也不能跨进程调用。

New:

分配内存的对象或数组类型的对象和返回一个适当类型,并调用对象的构造函数及在delete时调用对象的析构函数。其实现基于malloc调用。

下面是windows系统提供的API函数:

1、VirtualAlloc/VirtualAllocaEx

在虚拟地址空间中保留或提交内存,每次操作大小为Page页大小的整数倍,因此需要自己计算内存分配算法,在没有使用MEM_RESET的情况下会初始化内存块(0),VirtualAllocEx还可以在其他进程中的保留内存操作,并使用其对于的VirtualFree/VirtualFreeEx释放内存。

2.HeapAlloc/HeapFree

在指定的Heap中分配内存,heap应该由CreateHeap或GetProcessHeap返回,分配的内存不能移动,CreateHeap创建的堆只能在调用的进程中使用,因此如需跨进程滴啊用不能使用此种分配方式,由HeapFree释放。

3、GlobalAlloc/GlobalFree

从全局堆分配指定字节的内存,分配的内存可跨进程访问,并使用8字节对齐方式,有GloabalFree释放,在使用GlobalAlloc分配的内存块时需调用GlobalLock和GlobalUnlock函数。

PS:为了更好的理解内存分配,我们可以了解一下内存分区。

1)、栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。

2)、堆区(heap) — 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。

3)、全局区(静态区)(static)—,全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。 - 程序结束后有系统释放。注意:全局区又可分为未初始化全局区:.bss段和初始化全局区:.data段。

4)、常量区—常量字符串就是放在这里的。 程序结束后由系统释放

5)、代码区—存放函数体的二进制代码。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网