c++小知识

来源:互联网 发布:人工智能:伏羲觉醒 编辑:程序博客网 时间:2024/06/07 14:34

 一、生存期和作用域

变量的生存期和作用域是两个概念。生存期是执行过程的一个期间,从创建这个变量时开始,到销毁这个变量并且释放其占用的内存时结束。变量的作用域是可以在其中访问这个变量的程序代码区域。

二、CString头文件

CString的头文件是:atlstr.h,(非MFC应用程序引用).   非MFC工程中.
CString的头文件是:afxstr.h MFC工程中.而且不需要手动添加此头文件

三、读取文件

int readFile(CString& str, const CString& strPathName)
    {
        FILE* fp = fopen(strPathName, "r"); // 打开文件
        fseek(fp, 0, SEEK_END);
        int nLen = ftell(fp); // 获得文件长度
        fseek(fp, 0, SEEK_SET); // 重置读指针
        char* psz = str.GetBuffer(nLen);
        fread(psz, sizeof(char), nLen, fp); //读文件内容
        str.ReleaseBuffer(); //千万不能缺少
        fclose(fp);
    }

或者是

FILE *ft;
 //用这种方式打开文件,既可以读又可以写,而且原来存在于文件中的数据不会被覆盖掉,如果此文件不存在,会建立一个的
 ft = fopen("hello.txt","a+");
 //下面两句是获取文件中数据的长度,首先将指针移至文件末尾,然后求出末尾指针的位置就是文件的长度
 fseek(ft, 0L,SEEK_END);
 int len =ftell(ft);
 //最开始我没有加这一句,结果死活读不出文件中的内容,最后在付老大的帮助下找到了这个错误,应将指针重新移至文件首
 fseek(ft,0,SEEK_SET);
 //动态生成数组,减少内存占用量
 char *data = (char *)malloc((len+1)*sizeof(char));
 //将文件中len+1长度的内容读出赋给data
 fgets(data,len+1,ft);

解释一下getbuffer和releasebuffer:

这个GetBuffer函数是为一个CString对象重新获取其内部字符缓冲区的指针,返回的LPTSTR为非const的,从而允许直接修改CString中的内容!如果nMinBufLength 比当前buffer大,那么就调用ReleaseBuffer函数去释放当前的Buffer,用一个被请求的大小去覆盖这个buffer 。

GetBuffer说白了就两个功能:

1:就是将CString里面的内存交到外部来处理,外部可以直接修改它的内容。

2:重新修改CString的内存大小,这个数值不包含null结尾符。

另一个典型的用法:就是将CString里面的内容变为int或long型,需要先获取里面的内存指针。这样就可以先GetBuffer(内存大小)方便直接转换。

 

 

四、new运算符

在c++中,可以用new来动态建立对象进行内存分配

五、不同数据类型之间的装换

1、string->CString

CString = string.c_str();

2、char->CString

CString str;

char buf[100];

str.Format("%s",buf);

3、CString->int或者tring->int

即把字符串转换成整型数用atoi函数,原型int atoi(const char *nptr);头文件: #include <stdlib.h>

五、如何获取编辑框中输入的值

1、编辑框的ID号为IDC_EDIT1

CString str;
CWnd *pWnd = GetDlgItem(IDC_EDIT1);
pWnd->GetWindowText(str);

MessageBox(str);

2、给编辑框关联一个成员变量m_edit,m_edit的类型为CString类型

Updatedata(true);

即可得到m_edit的值


六、MFC

1、句柄并非对象的地址指针,它是作为系统内部表的索引值来使用的,这样就能避免应用程序直接同对象的内存地址打交道,体现了windows资源管理的优越性。例如,一个窗口打开后,对应内存中的一个内存块,这个窗口所在的内存块地址往往 由windows系统作动态调整,但其句柄却不会随之变化。这样程序员就不必关心其地址的变化,而是通过作为窗口标识的句柄来访问这个窗口。

      如果要获取某个MFC类对象的句柄,可以采用两种方法。一种方法是通过访问类的一个public属性的成员变量,如CWnd类的成员变量m_hWnd就是一个窗口对象的句柄。另一种方法就是先定义一个句柄,然后调用MFC类的成员函数Attach()将句柄与一个MFC类对象联系在一起,此时的句柄就成为该MFC类对象的句柄。但要注意,在退出对象作用域之前,要调用成员函数Detach()将句柄和对象进行分离,因为在销毁对象时,其构造函数将自动销毁与它联系在一起的句柄,造成句柄的重复销毁,使系统发生异常。

以下是一段正确 的示例代码:

BOOL CMyClass::MyMemberFunction()

{

CWnd  myWnd://定义一个窗口

HWND hWnd;//定义一个窗口句柄

myWnd.Attach(hWnd);//将窗口句柄hWnd与窗口对象myWnd联系在一起

......

myWnd.Detach();//在窗口对象myWnd销毁之前,分离窗口句柄hWnd

return TRUE;

}

 2、MFC的消息管理

(1)消息管理主要包括消息的发送和处理两个过程,消息处理采用了消息映射机制,并利用ClassWizard类向导管理消息映射。

(2)消息发送有两种方式:传送(send)和寄送(post)两种方式。

         函数SendMessage()用于向一个或多个窗口传送消息,直到目标窗口处理完收到的消息,该函数才返回。

         函数声明如下:

         LRESULT SendMessage(HWND hWnd ,UINT Msg,WPARAM wparam ,LPARAM lparam)分别表示接收消息的目标窗口的句柄,要发送的消息,消息的第一个参数,  消息的第二个参数

         函数PostMessage()用于向一个或多个窗口寄送消息,该函数把消息放在创建目标窗口线程的消息队列中,然后不等消息处理就返回。

         函数SendDlgItemMessage()用于向对话框中指定的控件发送消息,直到目标控件处理完收到的消息,该函数才返回。

(3)自定义消息,windows已经定义了 很多标准的消息,能够满足基本的程序设计需要。但有时也需要我们手工自定义一些消息。windows将所有的消息值分为4段,0~WM_USER-1用于windows系统消息,WM_USER~0X7FFF段用于用户自定义的窗口消息,0X8000~OXBFFF段作为windows保留值,0XC000~0XFFFF段用于应用程序的字符串消息。用户必须为每一个自定义消息定义一个相对于WM_USER的偏移量。

七、SetTimer函数

        创建或设置一个定时器,该函数创建的定时器与Timer控件(定时器控件)效果相同。

  当你想每隔一段时间执行一件事的的时候,你可以使用它。 使用定时器的方法比较简单,通常告诉WINDOWS一个时间间隔,然后WINDOWS以此时间间隔周期性触发程序。通常有两种方法来实现:发送WM_TIMER消息和调用应用程序定义的回调函数。

先请看SetTimer这个API函数的原型

  UINT_PTR SetTimer(

  HWND hWnd, // 窗口句柄

  UINT_PTR nIDEvent, // 定时器ID,多个定时器时,可以通过该ID判断是哪个定时器

  UINT uElapse, // 时间间隔,单位为毫秒

  TIMERPROC lpTimerFunc // 回调函数

  );

  例如

  SetTimer(m_hWnd,1,1000,NULL); //一个1秒触发一次的定时器

  在MFC程序中SetTimer被封装在CWnd类中,调用就不用指定窗口句柄了

  于是SetTimer函数的原型变为:

  UINT SetTimer(UINT nIDEvent,UINT nElapse,void(CALLBACK EXPORT *lpfnTimer)(HWND,UINT ,YINT ,DWORD))

  当使用SetTimer函数的时候,就会生成一个计时器。函数中nIDEvent指的是计时器的标识,也就是名字。nElapse指的是时间间隔,也就是每隔多长时间触发一次事件。第三个参数是一个回调函数,在这个函数里,放入你想要做的事情的代码,你可以将它设定为NULL,也就是使用系统默认的回调函数,系统默认的是onTime函数。这个函数怎么生成的呢?你需要在需要计时器的类的生成onTime函数:在ClassWizard里,选择需要计时器的类,添加WM_TIME消息映射,就自动生成onTime函数了。然后在函数里添加代码,让代码实现功能。每隔一段时间就会自动执行一次。

       当不需要定时器的时候就用KillTimer(0)函数销毁定时器,如果存在定时器,且成功销毁就会返回TRUE,但如果没有定时器存在,使用此函数就会返回FALSE。

八、clock函数

clock函数的返回值是CPU时钟计时单元(clock tick)数,CLOCKS_PER_SEC,它用来表示一秒钟会有多少个时钟计时单元,因此需要除以这个得到的才是秒数。

九、向前的类声明

使用向前的类声明来减少#include的使用,一个向前的类声明是一个忽略细节的方法,而这些细节又是你不需要关心的。使用向前声明简单的创建名字,任何在这个头文件中的类都可以引用这个名字。但并不是一直都能使用向前声明,如果类B仅使用了类A的指针或者引用,可以使用一个向前声明。但是如果使用了类A中的成员函数或者成员变量的话,就必须使用#include了。

十、模板

模板定义:模板就是实现代码重用机制的一种工具,它可以实现类型参数化,即把类型定义为参数, 从而实现了真正的代码可重用性。模版可以分为两类,一个是函数模版,另外一个是类模版。

 1、

函数模板的一般形式如下:

Template <class或者也可以用typename T>

返回类型 函数名(形参表)
{//
函数定义体 }

说明: template是一个声明模板的关键字,表示声明一个模板关键字class不能省略,如果类型形参多余一个 ,每个形参前都要加class <类型 形参表>可以包含基本数据类型可以包含类类型.

template <class T>

T min(T x,T y)

return(x<y)?x:y;}

2、

定义一个类模板:

Template < class或者也可以用typename T >
class类名{
//类定义......
};

说明:其中,template是声明各模板的关键字,表示声明一个模板,模板参数可以是一个,也可以是多个。

例如:定义一个类模板:

// ClassTemplate.h
#ifndef ClassTemplate_HH

#define ClassTemplate_HH

template<typename T1,typename T2>

class myClass{

private:

     T1 I;

     T2 J;

public:

     myClass(T1 a, T2 b);//Constructor

     void show();

};

十一、获得某种数值类型的最小和最大值

使用<limit>中的numeric_limits类模板的min和max函数就能获得最大最小值。

原创粉丝点击