您的位置:首页 > 其它

Cmap和Carray以及Cstring的使用以及MFC中的文件读写

2015-12-09 15:25 435 查看
参考资料:百度文库http://wenku.baidu.com/view/ddd1b32558fb770bf78a55a5.html?from=search
http://wenku.baidu.com/view/e07af57fc8d376eeaeaa31d4.html?from=search http://wenku.baidu.com/view/966cd848fe4733687e21aa7f.html?from=search http://wenku.baidu.com/view/2041cfa10029bd64783e2c93.html?from=search
CMap的使用

为什么使用CMap:

如果你要存储的每个数据至少有一个唯一的标志(数字、字符、字符串、类的对象。。。),并且这些数据会频繁的被查找和替换。那么你就需要使用CMap类来简化你的代码,提高你的效率。

CMap就是对Hash表的一种实现。对于Hash表来说,我们需要提供成对的Key与Value进行操作,其实,也就是将我们日常使用的数组下标替换成现在Key,这样就方便我们使用key来查找到相应的Value,提高我们遍历的速度。至于MFC是采用了什么样的散列函数,我们不必知道。

头文件: afxtempl.h

CMap的格式:

template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE >class CMap : public CObject

Key:用作Key的类型(比如整型、浮点型等) ARG_KEY:Key的值 VALUE: 用作VALUE的类型 ARG_VALUE:用作VALUE的值

1. 要使用Cmap,那么首先我们要实例化一个CMap的类型 举例:

typedef CMap<int, int, CString, CString> CMapPnt; //比如学生名册的列表 typedef CMao<CPoin, CPoin,CTime, CTime> CMapTime;//比如不同经纬度的时间 typedef CMap<CMyType, CMyType, CThing, CThing> CMyThing; //比如自己的私有物品的列表

任何类型都可以用作key或者value的类型。但是正如我们前面所说,key是一个唯一的标志,用以加快我们的查询速度。

2.我们举例来说明CMap的查询、遍历、删除等用法。

比如一个班级的花名册,那么学生的学号是唯一的,所以我们有了下面这个CMap的实例。 在使用之前声明:

typedef CMap<int, int, CString, CString> CMapStu;

使用时,我们认为CMapStu是一个类型就可以了。 CMapStu m_class1; //班级1

3.添加:void SetAt(ARG_KEY key, ARG_VALUE newValue); 此函数会以Key值遍历列表,当查找到key值后使用newValue替换以前的Value值。如果没有找到key值,则添加此项。

m_class1.SetAt(001, "张三"); m_class1.SetAt(002, "张A"); m_class1.SetAt(003, "张B"); m_class1.SetAt(004, "张C");

4.查找:Lookup(ARG_KEY key, ARG_VALUE& newValue)如果找到Key值,则newValue等于其存储的Value值,返回值为非0。 如果未找到,则返回值为0.

int studentId = 1; CString studentName;

if (m_class1.Lookup(studentId, studentName)) {

AfxMessageBox("ID号: %d, 姓名: %s", studentId, studentName); }

5.遍历:CMap提供了专门用作遍历的类型CPair,CPair顾名思义,就是一对。其中包含一个Key和对应的Value。

CMapStu::CPair* pCurValue= m_class1.PGetFirstAssoc(); while(pCurVal != NULL) {

CString str;

str.Format("学号: %d, 姓名:%s", pValue->key, pValue->value);

pCurValue = m_class1.PGetNextAssoc(); }

6.删除一个元素:RemoveKey(ARG_KEY key)

如果当前Key值存在,则返回非0值,如果不存在,则返回0值。 int studentId = 1;

RemoveKey(1); //删除学号为1的学生信息

7.删除所有元素:RemoveALL()

CMap<int,int,CPoint,CPoint> myMap;

// Add 10 elements to the map. for (int i=0;i < 10;i++)

myMap.SetAt( i, CPoint(i, i) );

myMap.RemoveAll();

CArray使用

我们在使用vc进行比较复杂的编程时,经常需要用到复杂的数组结构,并希望能实现动态管理。由于C++并不支持动态数组,MFC提供了一个CArray类来实现动态数组的功能。有效的使用CArray类,可以提高程序的效率。

MFC提供了一套模板库,来实现一些比较常见的数据结构如Array,List,Map。CArray即为其中的一个,用来实现动态数组的功能。

CArray是从CObject派生,有两个模板参数,第一个参数就是CArray类数组元素的变量类型,后一个是函数调用时的参数类型。

我们有一个类 class Object,我们要定义一个Object的动态数组,那么我们可以用以下两种方法:

 CArray<Object,Object> Var1; 

CArray<Object,Object&> Var2;

Var1与Var2哪一个的效率要高呢? Var2的效率要高。为什么呢?

CArray下标访问是非安全的,它并没有超标预警功能。虽然使用ASSERT提示,但下标超范围时没有进行处理,会引起非法内存访问的错误。

前面谈到模板实例化时有两个参数,后一个参数一般用引用,为什么呢?看看Add成员函数就可以明。Add函数的作用是向数组添加一个元素。下面是它的定义: int CArray<TYPE, ARG_TYPE>::Add(ARG_TYPE newElement)

Add函数使用的参数是模板参数的二个参数,也就是说,这个参数的类型是我们来决定的,可以使用Object或Object&的方式。熟悉C++的朋友都知道,传引用的效率要高一些。如果是传值的话,会在堆栈中再产生一个新的对象,需要花费更多的时间。

Cstring的使用

CString类的几种基本操作:

1、长度:GetLength();

CString str(_T("abc")); int len = str.GetLength(); //len == 3

2、是否为空(即不含字符):IsEmpty();

3、清空字符串:Empty();

CString str(_T("abc"));

BOOL mEmpty = str.IsEmpty(); //mEmpty == FALSE str.Empty();

mEmpty = str.IsEmpty(); //mEmpty == TRUE

4、转换大小写:MakeUpper(),MakeLower();

5、转换顺序:MakeReverse();

二、字符串的查找

1、Find:从制定位置开始查找指定字符串,返回其位置(找不到返回-1) CString str(_T("abcdefg"));

int idx = str.Find(_T("cde"), 0); //idx 的值为2;

2、ReverseFind:从字符串末尾开始查找指定的字符,返回其位置,找不到返回 -1,虽然是从后向前查找,但是位置为从开始算起; CString str(_T("abcdefg"));

int idx = str.ReverseFind('e'); //idx 的值为4;

3、FindOneOf:查找参数中给定字符串中的任意字符,返回第一次出现的位置 CString str(_T("abcabcd"));

int idx = str.FindOneOf(_T("cbd")); //idx 的值为1;

三、字符串的提取

Left,Mid,Right:分别实现从CString对象的左、中、右进行字符串的提取操作 CString str(_T("abcd"));

CString strResult = str.Left(2); //strResult == ab

strResult = str.Mid(1); //strResult == bcd

strResult = str.Mid(0, 2); //strResult == ab

strResult = str.Right(2); //strResult == cd

文本文件的读写

MFC主要读写文件的类是CFile,而CStdioFile类是派生自CFile类的,主要增加了一个按行的方式读取/写入文件每行字符串的功能!别的地方没咋研究!

//CFile读取所有文件到缓冲区:

CFile file;

char buffer[1024];

if(!file.Open("c://aaa.txt",CFile::modeRead))return; //打开aaa这个文件,打开形式为读取

file.Read(buffer,1024); //将文件的内容从开始,读1024到缓冲区(如果想读取不同地方的数据

则需要设置游标函数Seek,SeekToBegin,SeekToEnd..)

file.Close();

//CFile写内容到文件

CFile file;

char buffer[1024] = "在此添加要写入文件的字符串!";

if(!file.Open("c://aaa.txt",CFile::Create | CFile::Write))return; //打开aaa这个文件,打开形式为

(无此文件则新建)写入

file.Write(buffer,strlen(buffer));

file.Close();

//CStdioFile类的例子:

CStdioFile file;

CString str; //StdioFile可以直接使用字符串类CString的类型

if(!file.Open("c://aaa.txt",CFile::modeRead))return; //打开aaa这个文件,打开形式为读取

file.ReadString(str); //读一行内容到str字符串,注意此时文件的游标将自动设置到下一行的开头位置,所以如果想读下一行还是用file.ReadString(str);

file.Close();

正确的文本文件读写过程

1.定义文件变量;2.打开指定的文件;3.向从文本文件中写入信息;4.从文本文件中读取信息;5.关闭文件

1、定义文件变量

定义文件变量格式:CStdioFile 文件变量;

例如,定义一个名称为f1的文件变量,语句如下:CStdioFile f1;

2,打开指定文件

可以直接通过CStdioFile的构造函数来打开磁盘文件,同时可以用标志位指定打开方式(只读、只写、读写等):

CStdioFile(LPCTSTR lpszFileName,UINT nOpenFlags);

其中,lpszFileName表示要打开的文件名,可以是相对路径或绝对路径

nOpenFlags设置文件打开方式标志位,可以指定用“|”连接多个标志位。

下面是常用的打开标志:

CFile::modeRead:以只读方式打开文件

CFile::modeReadWrite:以可读可写方式打开文件

CFile::modeWrite:以只写方式打开文件

此外,可以不在构造函数中打开文件,而仅仅调用空的构造函数CStidoFile(),然后用CStdioFile::Open()打开文件。Open函数的前两个参数和非空构造函数的参数相同,其声明如下:

BOOL Open(LPCTSTR lpszFileName,UINT nOpenFlags,CFileException* pError=NULL); 第3个参数与打开失败时的异常处理有关。

实例1:以只读方式打开一个文件

char * pszFileName="C:\\myfile.txt"; CStdioFile myFile;

CFileException fileException;

if(!myFile.Open(pszFileName,CFile::modeCreate|CFile::typeText|CFile::modeRead),&fileException) {

TRACE("Can't open file %s, error = %u\n",pszFileName,fileException.m_cause); }

运行结果:如果C:\下没有myfile.txt文件,则新生成该文件。

3.向从文本文件中写入信息

CStdioFile提供了函数WriteString来向文本文件中写入文本,WriteString函数的格式如下: void WriteString(LPCTSTR lpsz);

WriteString的参数lpsz是一个以”\0”字符结束的字符串,要把这个字符串的内容写入文件。

提示:使用WriteString函数时,如果希望每执行一次WriteString,文本文件中的内容就会自动换行一次,那么就需要在需要换行的地方输出“\n”: myFile.WriteString(“第1行\n”);

实例2:向文件中写入文本

建立MFC基于对话框的程序,删除自动添加的所有控件,添加一个“确定”按钮,双击按钮,按默认添加事件函数,双击按钮,在相应的函数处添加如下代码: char* pszFileName="C:\\myfile.txt"; CStdioFile myFile;

CFileException fileException;

if(myFile.Open(pszFileName,CFile::typeText|CFile::modeCreate|CFile::modeReadWrite),&fileException) {

myFile.WriteString("第1行\n");

CString strOrder;

strOrder.Format("%d,%.3f",66,88.88);

myFile.WriteString(strOrder);

}

else {

TRACE("Can't open file %s,error=%u\n",pszFileName,fileException.m_cause); }

程序运行结果:C:\myfile.txt文件中内容如下:

第1行

66,88.880

4.从文本文件中读取信息

CStidoFile提供了函数ReadString来读取文本,ReadString有两种形式,一种为:

virtual LPTSTR ReadString(LPTSTR lpsz, UINIT nMax);

ReadString函数的参数如下:

lpsz :是用户提供的一个指向字符串的指针,它用来接受从文件读出的文本,以”\0”结束。

nMax是本次所允许读入的文本字符个数,不计“\0”字符,也就是说最多能读入nMax-1个文本字符。

ReadString的返回值是一个LPTSTR类型的指针,它指向从文件读出的文本字符串,如果到达文件尾,则返回NULL。

ReadString的另一种形式为:

BOOL ReadString(CString& rString);

参数rString用来容纳从文件读出的文本。

CString版本忽略回车换行符,返回值是一个布尔值。如果返回值为FALSE,表示因到达文件尾而没有读到任何字符。

提示:每执行一次ReadString,就会自动从文本文件中读取一行数据,同时文件操作指针会自动跳转到下一行。

实例3:从文件中读取文本信息

char* pszFileName="C:\\myfile.txt";

CStdioFile myFile;

CFileException fileException;

if(myFile.Open(pszFileName,CFile::typeText|CFile::modeReadWrite),&fileException) {

myFile.SeekToBegin();

CString str1;

myFile.ReadString(str1);

CString str2;

myFile.ReadString(str2);

AfxMessageBox(str1+str2);

}

else

{

TRACE("Can't open file %s,error=%u\n",pszFileName,fileException.m_cause);

}

myFile.Close();

5.关闭文件

对文件的操作完成后,使用CloseFile关闭文件。

函数CStdioFile::Close关闭一个文件,一般一个文件使用完毕就应该关闭它:

myFile.Close();
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: