CString 类提供了以下几种构造函数来构造 CString 对象。
CString() //默认构造函数
CString(const CString& stringSrc); //使用 CString 参数的构造函数
CString(TCHAR ch,nRepeat=1); //使用重复字符的构造函数
CString(LPCTSTR lpch,int nLength); //带指定长度字符串的构造函数
CString(const unsigned char* psz); //带以NULL结束的字符串的构造函数
CString(LPCWSTR lpsz); //带以 NULL 结束的多字符集字符串的构造函数
CString(LPCSTR lpsz); //带以 NULL 结束的单字符集字符串的构造函数
函数名 | 说明 |
---|---|
=操作符 | 为CString对象赋值 |
+操作符 | 连接两个字符串,并返回连接后的新字符串 |
+=操作符 | 连接两个字符串,并将连接后的新字符串赋值给操作符左边的变量 |
==、<、>等比较运算符 | 比较字符串的大小,区分大小写 |
Compare() | 比较两个字符串,区分大小写 |
CompareNoCase() | 比较两个字符串,不分大小写 |
Collate() | 使用本地化比较两个字符串,区分大小写 |
CollateNoCase() | 使用本地化比较两个字符串,不分大小写 |
Find() | 从字符串头开始查找字符或子字符串 |
ReverseFind() | 从字符串尾开始查找字符或子字符串 |
FindOneOf() | 从字符串头开始查找第一个匹配的字符或子字符串 |
MakeUpper() | 将字符串中的所有字符转换成大写 |
MakeLower() | 将字符串中的所有字符转换成小写 |
MakeReverse() | 反转字符串中的字符 |
Replace() | 替换字符串中指定字符 |
Remove() | 移除字符串中指定字符 |
Insert() | 在字符串中的指定位置插入一个字符或另一个子字符串 |
Delete() | 从字符串中删除一个字符或子字符串 |
Format() | 使用 sprintf方式格式化字符串 |
FormatV() | 使用vsprintf方式格式化字符串 |
TrimLeft() | 取消字符串前面的空格 |
TrimRight() | 取消字符串后面的空格 |
FormatMessage() | 格式化消息字符串 |
Mid() | 截取字符串中间的数据 |
Left() | 截取字符串左边的数据 |
Right() | 截取字符串右边的数据 |
SpanIncluding() | 截取字符串中包含指定字符的部分 |
SpanExcluding() | 截取字符串中不包含指定字符的部分 |
operator<< | 插入字符串对象 |
operator>> | 提取字符串对象 |
GetLength() | 返回 CString对象的字符串数。对于多字符集,也是按照8位字符计数,也就是每个多字节字符算作两个字符 |
IsEmpty() | 判断CString对象是否不包含任何字符 |
Empty() | 其空字符串内容 |
GetAt() | 返回指定位置的字符 |
[] | 返回指定位置的字符 |
SetAt() | 设置指定位置的字符 |
LPCTSTR操作符 | 直接反问储存在CString对象中的字符串 |
GetBuffer() | 返回字符串对象的字符指针 |
GetBufferSetLength() | 返回字符串中指定长度的字符串的指针 |
ReleaseBuffer() | 释放有GetBuffer函数获取的对缓冲区的控制 |
FreeExtra() | 移除字符串对象以前分配给字符串前面的字符 |
LockBuffer() | 锁定字符缓冲区,并关闭引用计数 |
UnlockBuffer() | 释放字符缓冲区,并开启引用计数 |
AllocSysString() | 从字符串对象复制数据到新建的BSTR对象的变量中 |
SetSysString() | 复制字符串对象的数据到一个存在的BSTR对象中 |
LoadString() | 从Windows资源中装载一个存在的字符串对象 |
AnsiToOem() | 将字符串对象中的字符从ANSI字符集转换成OEM字符集 |
OemToAnsi() | 将字符串对象中的字符从OEM字符集转换成ANSI字符集 |
CString 类通过提取操作符和插入操作符实现对序列化的支持,这两个函数的原型:
//提取操作符
friend CArchive& operator <<(CArchive& ar,const CString& string);
//插入操作符
friend CArchive& operator >>(CArchive& ar,CString& string);
//提取操作符
friend CDumpContext& operator <<(CDumpContext& dc,const CString& string);
提取操作符 << 将 CString 对象序列化到文件等对象中,插入操作符 >> 从文档对象中反序列化 CString 对象。
CString 类提供 GetLength() 函数获取字符串长度;CString 类以 TCHAR 为基本数据类型储存字符——Unicode 字符编码下用16位字符储存字符串,否则 CString 存储的是8位的字符;CString 类支持双字节字符集(double-byte character sets, DBCS),以8位字符为基准,每个字节算一个字符,其函数原型:
int GetLength() const;
//清空字符串
void Empty();
//判断字符串是否为空,如果对象长度为零,返回True,否则返回False
BOOL IsEmpty() const;
//字符串比较函数
int Collate(LPCTSTR lpsz) const;
int collateNoCase(LPCTSTR lpsz) const; //不区分大小写的比较字符串函数
int Compare(LPCTSTR lpsz) const; //使用单字符集比较函数
int Compare(LPCSTR lpsz) const; //使用单字符集不区分大小写的比较字符串
//其中,参数lpsz为要比较的字符串。Collate 和 Compare 的区别在于,前者基于字符集设置进行比较,支持多字符集比较,后者基于单字符集进行比较
//增加字符和删除字符
int Delete( //返回值为成功删除的字符的个数
int nIndex,//开始删除字符的第一个字符的索引
int nCount = 1); //要删除的字符个数
int Insert( //在指定位置插入字符,返回值为增加字符后的字符串长度
int nIndex, //要在其增加的字符的索引
TCHAR ch);//要增加的字符
int Insert( //在指定位置插入字符,返回值为增加字符后的字符串长度
int nIndex, //要在其增加的字符的索引
LPCTSTR pstr); //要增加的字符串的指针
//字符查找
int Find(TCHAR ch) const; //查找指定字符ch,返回索引位置
//查找指定字符串并返回开始匹配的索引位置
int Find(LPCTSTR lpszSub) const;
//从指定位置开始查找指定字符
int Find(TCHAR ch,int nStart) const;
//从指定位置开始查找指定字符串
int Find(LPCTSTR pstr,int nStart) const;
//反向查找指定字符
int ReverseFind(TCHAR ch) const;
//返回字符串中是否包含lpszCharSet中的任一个字符以及这个字符的位置
int FindOfOne(
LPCTSTR lpszCharSet, //要查找的字符的字符集,其中的字符没有顺序
) const;
//字符串截取
//截取指定索引处的字符,返回值为TCHAR
TCHAR GetAt(int nIndex) const;
//截取字符串中nIndex索引处的字符,大于0小于GetLength()返回值
TCHAR operator [](int nIndex) const;
//将字符串作为数组操作,但此操作是只读操作
//操作缓冲区数据的函数
void FreeExtra(); //释放字符串占用的内存
LPRTSTR GetBuffer( //获取字符串缓冲区,返回字符串对象的内部字符缓冲区指针
int nMinBufferLength); //表示字符缓冲区中最小的字符数
//设置字符串长度,返回字符串对象的内部字符缓冲区指针
LPTSTR GetBufferSetLength(
int nNewLength); //表示设置的缓冲区字符的精确长度,-1表示当前字符串长度
//释放字符串缓冲区
void ReleaseBuffer(int nNewLength = -1);
//锁定字符串,保护数据不被其他字符串引用,也不能引用其他字符串
LPTSTR LockBuffer();
void UnlockBuffer(); //解锁字符串
//字符串数据截取函数
CString Left(int nCount) const; //截取字符串左边nCount个字符
CString Right(int nCount) const; //截取字符串右边nCount个字符
Cstring Mid(int nFirst) const; //获取从nFirst位置开始的字符串
CString Mid(int nFirst,int nCount) const; //获取从nFirst位置开始的nCount字符
//返回排除lpszCharSet字符集的字符串
CString SpanExcluding(LPCTSTR lpszCharSet) const;
//返回包含lpszCharSet字符集的字符串
CString SpanIncluding(LPCTSTR lpszCharSet) const;
void Format(LPCTSTR lpszFormat,...); //按照格式化字符串格式化
void Format(UINT nFormatID,...);//按照格式化ID格式化字符串
void FormatV(LPCTSTR lpszFormat,va_list arglist);//使用参数格式化字符串
void FormatMessage(LPCTSTR lpszFormat,...);//格式化消息字符串
void FormatMessage(UINT nFormatID,...);//按照格式化ID格式化消息字符串
//lpszFormat 参数是一个格式化空制字符串,nFormatID 参数是一个包含格式化控制字符串资源的标识,arglist 参数是一个传入的参数列表。
//不能在次函数中使用字符串对象本身作为可选参数写入字符串对象,这样会造成循环递归,发生不可知的错误
//格式化字符串头和字符串尾的函数
void TrimLeft(); //去除左边的空格,包括换行、空格和制表符
void TrimLeft(TCHAR chTarget); //去除字符串左边的chTarget字符
void TrimLeft(LPCTSTR lpszTargets); //去除字符串左边的lpszTarget字符串
void TrimRight(); //去除右边的空格,包括换行、空格和制表符
void TrimRight(TCHAR chTarget); //去除字符串右边的chTarget字符
void TrimRight(LPCTSTR lpszTargets); //去除字符串右边的lpszTarget字符串
void MakeLower(); //将字符串中的字符全部换成小写字母
void MakeUpper(); //将字符串中的字符全部换成大写字母
void MakeReverse(); //反转字符串中的字符
int ReMove(TCHAR ch); //移除字符串中的所有ch字符,并返回移除的字符数目
//替换chOld(lpszOld)字符(串)为chNew(lpszNew)字符(串)
int Replace(TCHAR chOld,TCHAR chNew);
int Replace(LPCTSTR lpszOld,LPCTSTR lpszNew);
void SetAt(int nIndex,TCHAR ch); //设置nIndex索引处的字符为ch字符
//赋值操作
const CString& operator = (const CString& stringSrc); //使用CString参数的赋值符
const CString& operator = (TCHAR ch); //使用自负参数的赋值符
const CString& operator = (const unsigned char* psz); //使用字符串参数的赋值符
const CString& operator = (LPCWSTR lpsz); //使用多字符集字符串参数的赋值符
const CString& operator = (LPCSTR lpsz); //使用单字符集字符串参数的赋值符
const CString& operator +=(const CString& string); //使用CString参数的加法操作符
const CString& operator +=(TCHAR ch); //使用字符参数的加法赋值操作符
const CString& operator +=(LPCTSTR lpsz);//使用字符串参数的加法赋值操作符
//类型转换
BOOL LoadString(UINT nID); //装载字符串,nID参数为 Windows 字符串资源的 ID
//从 OEM 类型转换成ANSI类型,如果定义了 _UNICODE宏,则此函数无效
void OemToAnsi();
//将字符串pbstr复制到BSTR类型中,并返回
BSTR SetSysString(BSTR* pbstr) const;
operator LPCTSTR() const; //将CString对象转换成LPCTSTR对象
#include "pch.h"
#include
#include
using namespace std;
int main()
{
//定义字符串
CString s(_T("abcdef"));
printf("%ls\n", LPCTSTR(s));
wcout << "初始化字符串=" <
MFC 中封装了 CArray 类实现数组的功能,并且实现动态缩减和增加数组长度的功能,索引也是从 0 开始,其类声明如下:
template
class CArray:public CObject
//其中,模板参数 TYPE 指定存储在数组中的对象类型,也是 CArray 类中返回的参数的类型 。
//模板参数 ARG_TYPE 指定用于访问储存在数组中的对象的参数类型,通常是 TYPE 的引用,也是传入 CArray的参数
CArray 类的数组操作成员函数
函数名 | 功能 |
---|---|
GetSize() | 获取数组中的元素个数 |
GetUpperBound() | 返回数组最大的有效索引 |
SetSize() | 设置数组中包含的元素数目 |
FreeExtra() | 释放当前数组范围下,不使用的内存 |
RemoveAll() | 从数组中移除所有的元素 |
GetAt() | 返回指定索引处的元素值 |
SetAt() | 设置指定索引处的值,不能使用此函数增加元素,只能修改已经存在的元素值 |
ElementAt() | 返回数组中指定索引处的元素的引用 |
GetData() | 允许访问数组中的元素,可以为NULL |
SetAtGrow() | 设置指定索引处的值,如果需要,此函数可以自动增加数组大小 |
Add() | 向数组尾添加元素,如果需要,会自动增加数组大小 |
Append() | 添加其他数组中的元素到数组中,如果需要,会自动增加数组大小 |
Copy() | 复制其他数组中的元素到数组中,如果需要,会自动增加数组大小 |
InsertAt() | 在指定索引处插入元素或者其他数组中的所有元素 |
RemoveAt() | 移除指定索引处的元素 |
operator | 设置或获取指定索引处的元素 |
// MFC代码测试.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include "pch.h"
#include
#include
#include
using namespace std;
CArraym_ptArray; //定义数组对象
void PrintArray()
{
for (int i = 0; i < m_ptArray.GetSize(); i++)
{
cout << "第" << i + 1 << "个元素=(" << m_ptArray[i].x << "," << m_ptArray.GetAt(i).y << ")" << endl;
}
}
int _tmain()
{
CPoint ptA(0, 0), ptB(20, 50), ptC(120, 30); //构造CPoint对象
m_ptArray.Add(ptA);//增加元素
m_ptArray.Add(ptB);
m_ptArray.Add(ptC);
cout << "初始CArray对象中共有" << m_ptArray.GetSize() << "个元素:" << endl;
PrintArray();
CPoint ptD(800, 600);
m_ptArray[1] = ptD;
cout << endl << "修改第二个元素后CArray对象中共有" << m_ptArray.GetSize() << "个元素:" << endl;
PrintArray();
m_ptArray.RemoveAt(0);
cout << endl << "删除第一个元素后CArray对象中共有" << m_ptArray.GetSize() << "个元素:" << endl;
PrintArray();
m_ptArray.RemoveAll();
cout << endl << "删除所有元素后CArray对象中共有" << m_ptArray.GetSize() << "个元素:" << endl;
PrintArray();
return 0;
}
//输出结果
初始CArray对象中共有3个元素:
第1个元素=(0,0)
第2个元素=(20,50)
第3个元素=(120,30)
修改第二个元素后CArray对象中共有3个元素:
第1个元素=(0,0)
第2个元素=(800,600)
第3个元素=(120,30)
删除第一个元素后CArray对象中共有2个元素:
第1个元素=(800,600)
第2个元素=(120,30)
删除所有元素后CArray对象中共有0个元素:
D:\users\lenovo\source\code\day02\MFC代码测试\Debug\MFC代码测试.exe (进程 13840)已退出,返回代码为: 0。
CList 类实现对象的链式存储方式,使用 POSITION 类型的变量表示元素的位置,链表类声明如下:
template
class CList:public CObject
//模板参数的意义与数组类的一致
//链表类对于频繁插入删除元素的情况非常适用。
链表类CList成员函数
函数名 | 函数功能 |
---|---|
GetHead() | 获取链表的头元素,即第一个元素 |
GetTail() | 获取链表的尾元素,即最后一个元素 |
RemoveHead() | 移除链表的头元素 |
RemoveTail() | 移除链表的尾元素 |
AddHead() | 在链表头处增加新元素或将其它链表中的元素增加到链表头 |
AddTail() | 在链表尾处增加新元素或将其它链表中的元素增加到链表尾 |
RemoveAll() | 移除链表中所有的元素 |
GetHeadPosition() | 返回链表头的位置值 |
GetTailPosition() | 返回链表尾的位置值 |
GetNext() | 相对于当前元素,获取链表中的下一个元素 |
GetPrev() | 相对于当前元素,获取链表中的前一个元素 |
GetAt() | 获取指定位置的元素值 |
SetAt() | 修改指定位置的元素值 |
RemoveAt() | 移除指定位置值的元素值 |
InsertAfter() | 在指定位置值后插入一个新元素 |
InsertBefore() | 在指定位置值前插入一个新元素 |
Find() | 查找指定元素的位置 |
FindIndex() | 返回基于0索引的元素的位置值 |
GetCount() | 获取链表中元素的数目 |
IsEmpty() | 判断链表是否为空 |
MFC中从CList派生的链表类有以下3个:
CObList:存放CObject对象的链表
CPTRList:存放指针对象的链表
CStringList:存放CString对象的链表
// MFC代码测试.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include "pch.h"
#include
#include
#include
#include
using namespace std;
//CStringList m_stringList;
CListm_stringList;
void PrintList()
{
cout << "当前字符串链表中共有" << m_stringList.GetCount()
<< "个元素:" << endl;
if (m_stringList.IsEmpty())
return;
POSITION pos = m_stringList.GetHeadPosition();
int i = 0;
while (pos != NULL)
{
cout << "第" << i + 1 << "个元素='";
std::wcout.imbue(std::locale("chs"));
wcout << LPCTSTR(m_stringList.GetAt(pos));
//printf("%ls", LPCTSTR(m_stringList.GetAt(pos)));
cout<< "'" << endl;
m_stringList.GetNext(pos);
i++;
}
cout << endl;
}
int _tmain()
{
CListm_intList;
m_intList.AddHead(2008);
m_intList.AddHead(2019);
cout << "整个链表中共有" << m_intList.GetCount() << "个元素" << endl;
POSITION posINT = m_intList.GetHeadPosition();
int i = 0;
while (posINT != NULL)
{
cout << "第" << i + 1 << "个整数元素="
<< m_intList.GetAt(posINT) << endl;
m_intList.GetNext(posINT);
//i++;
}
for (i = 0; i < 3; i++)
{
CString element;
element.Format(_T("这是第%d个元素"), (i + 1));
m_stringList.AddTail(element);//向链表尾添加元素
}
//m_stringList.AddTail(_T("这是第1个元素"));//向链表尾添加元素
//m_stringList.AddTail(_T("这是第2个元素"));//向链表尾添加元素
//m_stringList.AddTail(_T("这是第3个元素"));//向链表尾添加元素
PrintList();
POSITION pos = m_stringList.FindIndex(1);
if (pos != NULL)
{
cout << "执行操作-----使用InsertBefore函数在当前链表的";
cout << "第二个元素插入新元素" << endl;
m_stringList.InsertBefore(pos, _T("在第二个元素前插入的新元素"));
PrintList();
pos = m_stringList.FindIndex(1);
cout << "执行操作-------使用SetAt函数修改第二个元素值" << endl;
m_stringList.SetAt(pos, _T("修改了第二个元素"));
PrintList();
cout << "执行操作-----使用RemoveTail函数移除最后一个元素" << endl;
m_stringList.RemoveTail();
PrintList();
cout << "执行操作-------使用Removeall函数移除所有元素" << endl;
m_stringList.RemoveAll();
PrintList();
return 0;
}
}
//效果
整个链表中共有2个元素
第1个整数元素=2019
第1个整数元素=2008
当前字符串链表中共有3个元素:
第1个元素='这是第1个元素'
第2个元素='这是第2个元素'
第3个元素='这是第3个元素'
执行操作-----使用InsertBefore函数在当前链表的第二个元素插入新元素
当前字符串链表中共有4个元素:
第1个元素='这是第1个元素'
第2个元素='在第二个元素前插入的新元素'
第3个元素='这是第2个元素'
第4个元素='这是第3个元素'
执行操作-------使用SetAt函数修改第二个元素值
当前字符串链表中共有4个元素:
第1个元素='这是第1个元素'
第2个元素='修改了第二个元素'
第3个元素='这是第2个元素'
第4个元素='这是第3个元素'
执行操作-----使用RemoveTail函数移除最后一个元素
当前字符串链表中共有3个元素:
第1个元素='这是第1个元素'
第2个元素='修改了第二个元素'
第3个元素='这是第2个元素'
执行操作-------使用Removeall函数移除所有元素
当前字符串链表中共有0个元素:
函数名 | 功能 |
---|---|
GetCurrentTime() | 创建一个取值为当前时间的 CTime对象。此函数为静态函数 |
GetTime() | 返回 CTime 对象对应的 time_t 类型的取值 |
GetYear() | 返回 CTime 对象当前时间年的取值 |
GetMonth() | 返回 CTime 对象当前时间月的取值,范围1~12 |
GetDay() | 返回 CTime 对象当前时间天的取值,范围1~31 |
GetHour() | 返回 CTime 对象当前时间小时的取值,范围0~23 |
GetMinute() | 返回 CTime 对象当前时间分钟的取值,范围0~59 |
GetSecond() | 返回 CTime 对象当前时间秒的取值,范围0~59 |
GetDayOfWeek() | 返回 CTime 对象当前时间是星期几,其中1代表星期日,2代表星期一,以此类推 |
GetGmtTime() | 将 CTime 对象的时间按照 UTC 解释,并将其赋值给 tm 结构 |
GetLocalTime() | 将 CTime 对象的时间按照 本地时区解释,并将其赋值给 tm 结构 |
GetAsSystemTime() | 将 CTime 对象转换成 Win32 兼容的SYSTEMTIME结构 |
Format() | 将 CTime 对象转换成基于本地时区的格式化字符串 |
FormatGmt() | 将 CTime 对象转换成基于格林威治时间的格式化字符串 |
<< | 对象序列化操作,将对象输出到 CArchive 对象或 CdumpContext 对象中 |
>> | 对象反序列化操作,从 CArchive 对象导入到 CTime 对象 |
= | 为 CTime 对象赋值 |
+、- | CTime 对象与 CTimeSpan 对象或 CTime 对象之间进行相加相减 的操作 |
+=、-= | 赋值加减运算,操作与+、-运算相同,区别在于这两个操作数会将运算结果赋值给目标对象,即操作符左边的对象。 |
==、<、etc | 比较 CTime 对象的绝对时间 |
格式化 CTime 对象有两种方法:一种是通过构造函数,一种是通过 Fromat() 成员函数。
构造函数方法通常用于与多种时间结构之间进行转换:
CTime();//默认构造函数
CTime(const CTime& timeSrc); //带 CTime 参数的构造函数
CTime(time_t time); //带 time_t 参数的构造函数
//带年、月、日、时、分、秒参数的构造函数
CTime(int nYear,int nMonth,int nDay,int nHour,int nMin,int nSec,int nDST=-1);
CTime(WORD wDosDate,WORD wDosTime,int nDST=-1);//带日期值、时间值和差值的构造函数
CTime(const SYSTEMTIME& sysTime,int nDST=-1); //带 SYSTEMTIME 参数的构造函数
CTime(const FILETIME& fileTime,int nDTS=-1);//带 FILETIME 参数的构造函数
//参数 wDosDate 和 wDosTime 表示 MS-DOC 的日期和时间值转换成 CTime 对象。
//sysTime表示使用 STSTEMTIME 结构初始化 CTime 对象
//fileTime表示使用 FILETIME 结构初始化 CTime 对象
//nDST 参数表示是否使用夏令时,0表示标准时间,大于0表示使用夏令时,小于0表示根据计算机上的设置决定是否使用夏令时
//使用案例如下:
time_t osTime;
time(& osTime);
CTime time1;
CTime time2 = time1;
CTime time3(osTime);
CTime time4(2019,4,19,18,3,45);
使用 Format() 函数格式化 CTime 对象。
CString Format(LPCTSTR pFormat) const; //使用指定格式格式化字符串
CString Format(UINT nFormatID) const; //使用格式化ID格式化字符串
//参数 pFormat 有效的格式化代码如下
//%D:CTime 时间的当前天数
//%H:当天小时数
//%M:当前小时的分钟数
//%S:当前分钟的秒数
//%%:百分号
//案例:
CTime t(2009,1,19,22,15,59);
CString s = t.Format(L"%A,%B,%d,%Y");
//判断格式化后的时间字符串与指定值是否相同
ASSERT(s=="Friday,January 19,2009");
CTimeSpan 类,表示一个时间间隔,即两个不同的 CTime 对象之间的间隔,结合 ANSI 的 time_t 数据类型,并且与运行时函数相关。
CTimeSpan 对象以秒保存时间,由于它存储为4个字节的有符号数,因此最大的时间间隔值为-68~68年。
CTimeSpan 常用成员函数:
函数名 | 功能 |
---|---|
GetDays() | 返回 CTimeSpan 对象中的整天的数目 |
GetHours() | 返回 CTimeSpan 对象中的当天的小时数 |
GetTotalHours() | 返回 CTimeSpan 对象中的整小时数 |
GetMinutes() | 返回 CTimeSpan 对象中的当前小时的分钟数 |
GetTotalMinutes() | 返回 CTimeSpan 对象中的整分钟数 |
GetSeconds() | 返回 CTimeSpan 对象中的当前分钟的秒数 |
GetTotalSeconds() | 返回 CTimeSpan 对象中的整秒数 |
CTimeSpan ts(7,5,5,1);
ASSERT(ts.GetDays()==7); //判断CTimeSpan对象的天数是否为7
// CTimerSampleDlg 对话框
class CTimerSampleDlg : public CDialogEx
{
DECLARE_DYNAMIC(CTimerSampleDlg)
public:
CTimerSampleDlg(CWnd* pParent = nullptr); // 标准构造函数
virtual ~CTimerSampleDlg();
// 对话框数据
#ifdef AFX_DESIGN_TIME
enum { IDD = IDD_DIALOG2 };
#endif
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持
virtual BOOL OnInitDialog();
DECLARE_MESSAGE_MAP()
public:
CStatic m_staticTime;
CTime m_BeginTime;
afx_msg void OnButtonStart();
afx_msg void OnButtonStop();
afx_msg void OnTimer(UINT nIDEvent);
};
// CTimerSampleDlg.cpp: 实现文件
//
#include "stdafx.h"
#include "MFCApplication1.h"
#include "CTimerSampleDlg.h"
#include "afxdialogex.h"
// CTimerSampleDlg 对话框
IMPLEMENT_DYNAMIC(CTimerSampleDlg, CDialogEx)
CTimerSampleDlg::CTimerSampleDlg(CWnd* pParent /*=nullptr*/)
: CDialogEx(IDD_DIALOG2, pParent)
{
#ifndef _WIN32_WCE
EnableActiveAccessibility();
#endif
}
CTimerSampleDlg::~CTimerSampleDlg()
{
}
void CTimerSampleDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_STATIC_TIMELOG, m_staticTime);
}
BEGIN_MESSAGE_MAP(CTimerSampleDlg, CDialogEx)
ON_BN_CLICKED(IDC_BUTTON_START,OnButtonStart)
ON_BN_CLICKED(IDC_BUTTON_STOP,OnButtonStop)
ON_WM_TIMER(IDC_BUTTON_STOP, OnTimer)
END_MESSAGE_MAP()
// CTimerSampleDlg 消息处理程序
BOOL CTimerSampleDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
return TRUE;
}
void CTimerSampleDlg::OnButtonStart()
{
SetTimer(100, 1000, NULL);
m_BeginTime = CTime::GetCurrentTime();
}
void CTimerSampleDlg::OnButtonStop()
{
KillTimer(100);
}
void CTimerSampleDlg::OnTimer(UINT nIDEvent)
{
CTime m_EndTime = CTime::GetCurrentTime();
CTimeSpan m_span = m_EndTime - m_BeginTime;
CString log;
log.Format(L"%d", m_span.GetSeconds());
m_staticTime.SetWindowText(log);
UpdateData(FALSE);
CDialog::OnTimer(nIDEvent);
}
//主窗口添加菜单命令
afx_msg void OnTestTime();
DECLARE_MESSAGE_MAP()
ON_COMMAND(ID_T,OnTestTime)
void CMFCApplication1App::OnTestTime()
{
CTimerSampleDlg timeDlg;
timeDlg.DoModal();
}
CFile 类的构造函数如下:
CFile(); //默认构造函数
CFile(int hFile); //带文件句柄参数的构造函数
CFile(
//要打开的文件的路径,此路径可以是绝对路径,也可以是相对路径
LPCTSTR lpszFilename,
UINT nOpenFlags); //打开文件时的共享和访问方式
CFile 类打开文件的操作函数
virtual BOOL Open(
//要打开的文件的路径,此路径可以是绝对路径,也可以是相对路径
LPCTSTR lpszFilename,
UINT nOpenFlags,//打开文件时的共享和访问方式
CFileException* pError = NULL //打开文件的异常捕获常量
);
nOpenFlags 参数指定共享和访问的方式,可以是下列选项的任意组合,使用位或(|)组合
CFile::modeCreate:新建文件,如果文件已经存在,则截取文件的长度为0;
CFile::modeNoTruncate:与 modeCreate 组合使用,如果创建的文件已经存在,则不会截取长度为0长度。因此,其含义。因此,其含义是打开已经存在的文件或新建文件。
CFile::modeRead:以只读方式打开文件
CFile::modeReadWrite:以可读写的方式打开文件
CFile::modeNoInherit:阻止文件从子进程中继承
CFile::shareDenyNone:共享读写的打开文件。
CFile::shareDenyRead:排它读权限打开文件
CFile::shareDenyWrite:排它写权限打开文件
CFile::shareExclusive:排它模式打开文件
CFile::typeText:文本模式打开文件
CFile::typeBinary:二进制模式打开文件。
创建文件并以写模式打开文件
CString filename = L"comm.log";
void main()
{
TRY
{
//以创建方式和可写方式打开文件
CFile f(filename,CFile::modeCreate | CFile::modeWrite);
}
CATCH(CFileException, e)
{
#ifdef DEBUG
//显示打开文件错误的原因
afxDump << "打开文件失败" << e->m_cause << "\n";
#endif // DEBUG
}
END_CATCH
}
CFile 类提供了以下两个函数实现读文件的功能:
virtual UINT Read( //从文件中获取指定长度的数据到缓冲区中
void* lBuf, //存放读取的数据缓冲区指针
UINT nCount); //要读的字节数
DWORD ReadHuge( //获取指定长度的大量数据
void* lpBuffer,//存放读取的数据的缓冲区指针
DWORD dwCount); //要读取的字节数
//区别:Read() 函数最多可以读取64k-1个字节,超过64k的数据,则需要使用ReadHuge()函数读取。
//共同点:这两个函数的返回值都是读取的字节数。
//例:
char pbuf[50];
UINT nBytesread = cfile.Read(pbuf,50);
类似的,CFile 提供两种写文件的函数。
virtual void Write( //向文件中写入指定长度的数据
const void* lpBuf,//存放写入文件的数据的缓冲区指针
UINT nCount);//要写入的字节数
void WriteHuge( //向文件写入指定长度的大量数据
const void* lpBuf, //存放写入文件的数据缓冲区指针
DWORD dwCount); //要写入的字节数
//Write() 函数最多可以一次性写入小于64k-1的数据,超过64k的数据,需要使用 WriteHuge() 函数来操作。
//例
char pBuf[100];
cfile.Write(pBuf,100);
//CFile 还提供了一个 Flush() 函数,用于强制将文件缓冲区的内容刷新到文件中。
virtual void Flush(); //刷新文件缓冲区中的数据
### 3、定位文件
* CFile 类提供了用于文件定位的函数,使用这些函数可以实现在文件中的快速定位。
```C++
virtual LONG Seek(LOMG lOff,UINT nFrom); //定位文件中指定位置的数据
void SeekToBegin(); //定位到文件头
DWORD SeekToEnd(); //定位到文件尾
virtual DWORD GetLength() const; //获取文件的长度
virtual void SetLength(DWORD dwNewLength); //设置文件长度
//Seek() 函数按照指定条件执行文件定位。lOff 参数表示要定位的字符的偏移量;nFrom 参数用于指定定位模式,有下面三种:
//CFile::Begin:从文件头开始定位字符
//CFile::current:从文件当前位置开始定位字符
//CFile::end:从文件尾开始定位字符。
//Seek() 函数如果定位成功则返回定位位置的字符;否则,抛出异常。
//SeekToBegin() 和 SeekToEnd() 两个函数的返回值都是文件的字节数
//SetLength() 函数会扩展或截取文件的长度,参数为要设置的文件长度
//例:
LONG lOff = 255, lResult; //定义文件定位使用的变量
//定位到文件的第226个字符的位置
lResult = cfile.Seek(lOff,CFile::begin);
cfile.SeekToBegin(); //定位到文件头
DWORD dsResult = cfile.SeekToEnd(); //定位到文件尾
DWORD dwNewLen = 100;
cfile.SetLength(dwNewLen); //设置文件长度为100
CFile 提供的一些文件管理操作函数,如下:
函数名 | 功能 |
---|---|
LockRange() | 锁定文件中的一个范围的字节 |
UnlockRange() | 解锁文件中的一个范围的字节 |
GetPosition() | 获取文件当前位置的位置指针 |
GetStatus() | 获取指定文件的状态 |
GetFileName() | 获取选定的文件名 |
GetFileTitle() | 获取选定的文件标题 |
GetFilePath() | 获取选定的文件的完整路径 |
SetFilePath() | 设置选定的文件的完整路径 |
Rename() | 重命名指定文件 |
Remove() | 删除指定文件 |
SetStatus() | 设置指定文件的状态 |
示例:
DWORD dwPos = 5; //定义位置变量
DWORD dwCount = 20; //定义个数变量
//锁定指定位置处,制定个数的文件的内容
cfile.LockRange(dwPos,dwCopunt);
cfile.UnlockRange(dwPos,dwCount); //解锁对文件的锁定
DWORD dwPos = cfile.GetPosition(); //获取当前位置
CFileStatus status; //定义文件状态变量
cfile.GetStatus(status); //获取当前文件的状态
char* pOldname="old.log"; //原来的文件名
char* pNewname = "new.log"; //新的文件名
CFile::Rename(pOldname,pNewname); //重命名文件名
char* pFilename = "test.log"; //定义文件名变量
try
{
CFile::Remove(pFilename); //删除指定文件
}
catch(CFileException,e) //如果删除文件时发生异常
{
#ifdef _DEBUG
afxDump<<"删除文件"<
void CTimerSampleDlg::OnButtonRead()
{
CFile file;
file.Open(L"data.txt", CFile::modeRead); //打开文件
//获取读取的内容的长度
int len = min(file.GetLength(), MAX_FILE_LEN);
char buf[MAX_FILE_LEN] = { 0 };
char* pOldLocale = _strdup(setlocale(LC_CTYPE, NULL));
setlocale(LC_CTYPE, "chs");
file.Read(buf, len); //读取文件内容
setlocale(LC_CTYPE, pOldLocale);
free(pOldLocale);
buf[len] = '\0';
USES_CONVERSION;//转化为wchar_t* 可以使用CString的Format函数。
wchar_t* temp = new wchar_t[len + 1];
temp = A2T(buf);
CString temp1;
temp1.Format(_T("%s"), temp);
SetDlgItemText(IDC_EDIT_FILE, temp1);
file.Close();
UpdateData(FALSE);
}
void CTimerSampleDlg::OnButtonWrite()
{
UpdateData();
CFile file;
//打开文件
file.Open(L"data.txt", CFile::modeCreate | CFile::modeWrite);
//向文件写入内容
CString temp;
GetDlgItem(IDC_EDIT_FILE)->GetWindowText(temp);
CStringA str_ANSI(temp.GetBuffer(0)); //将字符从UTF-8转成ANSI
file.Write(str_ANSI.GetBuffer(), str_ANSI.GetLength());
file.Close(); //关闭文件
MessageBox(L"写入成功", L"提示");
}
CException 是 MFC 异常类的基类,封装了所有异常共有的操作。使用 CExecption 的 GetErrorMessage() 成员函数可以获取异常的描述说明;使用 ReportError() 函数可以以消息框的方式向用户报告错误信息。
在 CException 类的基础上,MFC 提供了对应多种操作的异常类,使程序可以准确定位异常情况。
异常类 | 实现的功能 |
---|---|
CMemoryException | 管理内存异常 |
CNotSupportException | 管理不支持的请求异常 |
CArchiveException | 管理序列化异常 |
CFileException | 管理文件异常 |
CresourceException | 管理资源异常,主要是资源没找到或创建失败的情况 |
COleException | OLE 异常 |
CDBException | 数据库异常,主要是基于 MFC 的 ODBC 操作发生的异常 |
COleDispatchException | OLE 调度异常 |
CUserException | 表示资源找不到的异常 |
CDaoException | 数据访问对象异常,由 DAO 类产生 |
CInternetException | Internet 异常 |
CFileException 类表示与文件相关的异常情况。CFileException 类包含下面三个数据成员:
m_cause:包含异常对应的原因代码。
m_IOsError:包含于操作系统相关的错误代码。
m_strFileName:包含异常对应的文件名
其中,m_cause 是用于表示文件异常的直接原因的,有效的取值如下:
值 | 原因 |
---|---|
CFileException::none | 没有错误发生 |
CFileException::generic | 发生未指定错误 |
CFileException::fileNotFount | 没有找到文件 |
CFileException::badPath | 文件路径无效 |
CFileException::tooManyOpenFiles | 打开的文件太多 |
CFileException::accessDenied | 文件不能访问 |
CFileException::invalidFile | 无效的文件句柄 |
CFileException::removeCurrentDir | 要移除的文件夹是当前工作的文件夹,不能移除 |
CFileException::diretoryFull | 文件夹已满 |
CFileException::badSeek | 在定位文件时发生错误 |
CFileException::hardIO | 发生硬件错误 |
CFileException::sharingViolation | 没有装载 SHARE.EXE,或已锁定了共享区域。 |
CFileException::lockViolation | 要锁定的区域已被锁定 |
CFileException::diskFull | 磁盘已满 |
CFileException::endOfFile | 已到达文件尾 |
捕获异常,需要使用 THROW、THROW_LAST、TRY、CATCH、AND_CATCH 和 END_CATCH 宏。
捕获特殊的异常,必须使用 CException 类相应的派生类;要捕获所有类型的异常,可以使用 CException 类,然后使用 CObject::IsKindOf() 函数判断是否是 CException 类的派生类对象。
注意:CException 类是抽象基类,要抛出异常,必须创建 CException 类的派生类对应的对象。
示例:
CString pFilename = L"omm.ini";
void main()
{
TRY
{
CFile f(pFilename,CFile::modeRead);
}
CATCH(CFileException, e)
{
if (e->m_cause == CFileException::fileNotFound)
printf("错误:文件没有找到\n");
}
END_CATCH
}