`
BlogDown
  • 浏览: 212909 次
  • 性别: Icon_minigender_1
  • 来自: 上海
文章分类
社区版块
存档分类
最新评论

CString常用方法解释举例 CString详解

 
阅读更多

1.CString::IsEmpty


BOOL IsEmpty( ) const;


返回值:如果CString 对象的长度为0,则返回非零值;否则返回0。


说明:此成员函数用来测试一个CString 对象是否是空的。


示例:


下面的例子说明了如何使用CString::IsEmpty。


// CString::IsEmpty 示例


CString s;


ASSERT( s.IsEmpty() );


请参阅 CString::GetLength





2.CString::Left


CString Left( int nCount ) const;


throw( CMemoryException );


返回值:返回的字符串是前nCount个字符。


示例:


CString s( _T("abcdef") );


ASSERT( s.Left(2) == _T("ab") );





3.CString::LoadString


BOOL LoadString( UINT nID );


throw( CMemoryException );


返回值:如果加载资源成功则返回非零值;否则返回0。


nID 一个Windows 字符串资源ID。


说明: 此成员函数用来读取一个由nID 标识的Windows 字符串资源,并放入一个已有CString 对象中。


示例:


下面的例子说明了如何使用CString::LoadString。


// CString::LoadString 示例


#define IDS_FILENOTFOUND 1


CString s;


if (! s.LoadString( IDS_FILENOTFOUND ))





4.CString::MakeLower


void MakeLower( ); //改变字符的小写





5.CString::MakeReverse


void MakeReverse( ); //字符倒置





6.CString::MakeUpper


void MakeUpper( ); //改变字符的大写





7.CString::Mid CString Mid( int nFirst ) const; CString Mid( int nFirst, int nCount ) const; nCount代表要提取的字符数, nFirst代表要提取的开始索引位置


示例: CString s( _T("abcdef") ); ASSERT( s.Mid( 2, 3 ) == _T("cde") );





8.CString::ReleaseBuffer


void ReleaseBuffer( int nNewLength = -1 );


参数:nNewLength


此字符串的以字符数表示的新长度,不计算结尾的空字符。如果这个字


符串是以空字符结尾的,则参数的缺省值-1 将把CString 的大小设置为


字符串的当前长度。


说明:


使用ReleaseBuffer 来结束对由GetBuffer 分配的缓冲区的使用。如果你知道缓


冲区中的字符串是以空字符结尾的,则可以省略nNewLength 参数。如果字符


串不是以空字符结尾的,则可以使用nNewLength 指定字符串的长度。在调用


ReleaseBuffer 或其它CString 操作之后,由GetBuffer 返回的地址是无效的。


示例:


下面的例子说明了如何使用CString::ReleaseBuffer。


// CString::ReleaseBuffer 示例


CString s;


s = "abc";


LPTSTR p = s.GetBuffer( 1024 );


strcpy(p, "abc"); // 直接使用该缓冲区


ASSERT( s.GetLength() == 3 ); // 字符串长度 = 3


s.ReleaseBuffer(); // 释放多余的内存,现在p 无效。


ASSERT( s.GetLength() == 3 ); // 长度仍然是3





9.CString::Remove


int CString::Remove ( TCHAR ch );


返回值:返回从字符串中移走的字符数。如果字符串没有改变则返回零。


参数:ch 要从一个字符串中移走的字符。


说明:此成员函数用来将ch 实例从字符串中移走。与这个字符的比较是区分大小写


的。


示例:


// 从一个句子中移走小写字母'c':


CString str (“This is a test.”);


int n = str.Remove( 't' );


ASSERT( n == 2 );


ASSERT( str ==“This is a es. ” );


10.CString::Replace


int Replace( TCHAR chOld, TCHAR chNew );


int Replace( LPCTSTR lpszOld, LPCTSTR lpszNew );


返回值:返回被替换的字符数。如果这个字符串没有改变则返回零。


参数:chOld 要被chNew 替换的字符。


chNew 要用来替换chOld 的字符。


lpszOld 一个指向字符串的指针,该字符串包含了要被lpszNew 替换的字符。


LpszNew 一个指向字符串的指针,该字符串包含了要用来替换lpszOld 的字符。


说明:此成员函数用一个字符替换另一个字符。函数的第一个原形在字符串中用chNew


现场替换chOld。函数的第二个原形用lpszNew 指定的字符串替换lpszOld 指定


的子串。


在替换之后,该字符串有可能增长或缩短;那是因为lpszNew 和lpszOld 的长度


不需要是相等的。两种版本形式都进行区分大小写的匹配。


示例:


// 第一个例子,old 和new 具有相同的长度。


CString strZap( “C - -” );


int n = strZap.Replace('-', '+' );


ASSERT( n == 2 );


ASSERT(strZap == “C++” );


// 第二个例子,old 和new 具有不同的长度。


CString strBang( “Everybody likes ice hockey” );


n = strBang.Replace( “hockey”, “golf” );


ASSERT( n ==1 );


n = strBang.Replace ( “likes” , “plays” );


ASSERT( n == 1 );


n = strBang.Replace( “ice”, NULL );


ASSERT( n == 1 );


ASSERT( strBang == “Everybody plays golg” );


// 注意,现在在你的句子中有了一个额外的空格。


// 要移走这个额外的空格,可以将它包括在要被替换的字符串中,例如,“ice ”。





11.CString::ReverseFind


int ReverseFind( TCHAR ch ) const;


返回值: 返回此CString 对象中与要求的字符匹配的最后一个字符的索引;如果没有找


到需要的字符则返回-1。


参数: ch 要搜索的字符。


说明:此成员函数在此CString 对象中搜索与一个子串匹配的最后一个字符。此函数


类似于运行时函数strrchr。


示例:


// CString::ReverseFind 示例


CString s( "abcabc" );


ASSERT( s.ReverseFind( 'b' ) == 4 );





12.CString::Right


CString Right( int nCount ) const;


throw( CMemoryException );


返回值: 返回的字符串是最后nCount个字符。


CString s( _T("abcdef") );


ASSERT( s.Right(2) == _T("ef") );





13.CString:: SetAt


void SetAt( int nIndex, TCHAR ch );


说明:可以把字符串理解为一个数组,SetAt类似于[].注意nIndex的范围,如果不合适会有调试错误。 Ch 更替字符, 把nIndex位置上的字符 变成ch


示例:


CString s( "abc" );


s.MakeReverse();


ASSERT( s == "cba" );





14.CString::TrimLeft


void TrimLeft( );


void CString::TrimLeft( TCHAR chTarget );


说明:如果没有参数,从左删除字符(\n\t空格等),至到遇到一个非此类字符. 当然你也可以指定删除那些字符. 如果指定的参数是字符串,那么遇上其中的一个字符就删除. \n 换行符 \t TAB字符


示例1: CString str = "\n\t a";


str.TrimLeft();


str为“a”;


示例2:


CString str = "abbcadbabcadb ";


str.TrimLeft("ab");


结果"cadbabcadb "


str.TrimLeft("ac");


结果"bcadbabcadb "





15.CString::TrimRight


void TrimRight( );


void CString::TrimRight( TCHAR chTarget );


void CString::TrimRight( LPCTSTR lpszTargets );


说明:用法类似于上面。





16.CString::Compare


int Compare( LPCTSTR lpsz ) const;


返回值:字符串一样返回0,小于lpsz 返回-1,大于lpsz 返回1, 区分大小字符


示例:


CString s1( "abc" );


CString s2( "abd" );


ASSERT( s1.Compare( s2 ) == -1 );


ASSERT( s1.Compare( "abe" ) == -1


17.CString::CompareNoCase


int CompareNoCase( LPCTSTR lpsz ) const;


返回值: 字符串一样 返回0,小于lpsz 返回-1,大于lpsz 返回1,不区分大小字符





18.CString::Collate


int Collate( LPCTSTR lpsz ) const;


同CString::Compare





19.CString::CollateNoCase


int CollateNocase( LPCTSTR lpsz ) const;


同CString::CompareNoCase





20.CString::CString //构造函数


CString( );


CString( const CString& stringSrc );


CString( TCHAR ch, int nRepeat = 1 );


CString( LPCTSTR lpch, int nLength );


CString( const unsigned char* psz );


CString( LPCWSTR lpsz );


CString( LPCSTR lpsz );


示例:


CString s1;


CString s2( "cat" );


CString s3 = s2;


CString s4( s2 + " " + s3 );


CString s5( 'x' ); // s5 = "x"


CString s6( 'x', 6 ); // s6 = "xxxxxx"


CString s7((LPCSTR)ID_FILE_NEW); // s7 = "Create a new document"


CString city = "Philadelphia";





21.CString::Delete


int Delete( int nIndex, int nCount = 1);


返回值:是被删除前的字符串的长度


nIndex是第一个被删除的字符,nCount是一次删除几个字符。根据我实验得出的结果:当nCount>要删除字符串的最大长度(GetCount() - nIndex)时会出错,当nCount过大,没有足够的字符删除时,此函数不执行。


示例:


CString str1,str2,str3;


char a;


str1 = "nihao";


str2 = "nIhao";


int x;


// int i=(str1 == str2);


str1.Delete(2,3);


如果nCount(3) > GetCount() – nIndex (5-2)就会执行错误





22.CString::Empty


Void Empty( );


返回值:没有返回值 清空操作;


示例:


CString s( "abc" );


s.Empty();


ASSERT( s.GetLength( ) == 0 );





23.CString::Find


int Find( TCHAR ch ) const;


int Find( LPCTSTR lpszSub ) const;


int Find( TCHAR ch, int nStart ) const;


int Find( LPCTSTR lpszSub, int nStart ) const;


返回值: 不匹配的话返回 -1; 索引以0 开始; nStar 代表以索引值nStart 的字符开始搜索 ,


即为包含以索引nStart字符后的字符串.


示例:


CString s( "abcdef" );


ASSERT( s.Find( 'c' ) == 2 );


ASSERT( s.Find( "de" ) == 3 );


Cstring str(“The stars are aligned”);


Ing n = str.Find('e',5);


ASSERT(n == 12)





24.CString::FindOneOf


int FindOneOf( LPCTSTR lpszCharSet ) const;


返回值: 不匹配的话返回 -1; 索引以0 开始


注意::返回此字符串中第一个在lpszCharSet中也包括字符并且从零开始的索引值


示例:


CString s( "abcdef" );


ASSERT( s.FindOneOf( "xd" ) == 3 ); // 'd' is first match.





25.CString::Format


void Format( LPCTSTR lpszFormat, ... );


void Format( UINT nFormatID, ... );


参数:lpszFormat 一个格式控制字符串


nFormatID 字符串标识符


示例:


CString str;


Str.Format(“%d”,13);


此时Str为13





26.CString::GetAt


TCHAR GetAt( int nIndex ) const;


返回值:返回标号为nIndex的字符,你可以把字符串理解为一个数组,GetAt类似于[].注意nIndex的范围,如果不合适会有调试错误。





27.CString::GetBuffer


LPTSTR GetBuffer( int nMinBufLength );


返回值:一个指向对象的(以空字符结尾的)字符缓冲区的LPTSTR 指针。


参数:nMinBufLength


字符缓冲区的以字符数表示的最小容量。这个值不包括一个结尾的空字符的空间。


说明:此成员函数返回一个指向CString 对象的内部字符缓冲区的指针。返回的LPTSTR 不是const,因此可以允许直接修改CString 的内容。如果你使用由GetBuffer 返回的指针来改变字符串的内容,你必须在使用其它的CString 成员函数之前调用ReleaseBuffer 函数。


在调用ReleaseBuffer 之后,由GetBuffer 返回的地址也许就无效了,因为其它的CString 操作可能会导致CString 缓冲区被重新分配。如果你没有改变此CString 的长度,则缓冲区不会被重新分配。当此CString 对象被销毁时,其缓冲区内存将被自动释放。


注意:如果你自己知道字符串的长度,则你不应该添加结尾的空字符。但是,当你用ReleaseBuffer 来释放该缓冲区时,你必须指定最后的字符串长度。如果你添加了结尾的空字符,你应该给ReleaseBuffer 的长度参数传递-1 ,ReleaseBuffer 将对该缓冲区执行strlen 来确定它的长度。


示例:


// CString::GetBuffer 例子


CString s( "abcd" );


#ifdef _DEBUG


afxDump << "CString s " << s << "\n";


#endif


LPTSTR p = s.GetBuffer( 10 );


strcpy( p, "Hello" ); // 直接访问CString 对象。


s.ReleaseBuffer( );


#ifdef _DEBUG


afxDump << "CString s " << s << "\n";


#endif





28.CString::GetLength


int GetLength( ) const;


返回值:返回字符串中的字节计数。


说明:此成员函数用来获取这个CString 对象中的字节计数。这个计数不包括结尾的空字符。


对于多字节字符集(MBCS),GetLength 按每一个8 位字符计数;即,在一个多字节字符中的开始和结尾字节被算作两个字节。


示例


下面的例子说明了如何使用CString::GetLength。


// CString::GetLength 示例


CString s( "abcdef" );


ASSERT( s.GetLength() == 6 );





29.CString::Insert


int Insert( int nIndex, TCHAR ch );


int Insert( int nIndex, LPCTSTR pstr );


返回值:返回修改后的长度,nIndex是字符(或字符串)插入后的索引号例子


示例:


CString str( “HockeyBest”);


int n = str.Insert( 6, “is” );


ASSERT( n == str.GetLength( ) );


printf( “1: %s\n”, ( LPCTSTR ) str );


n = str.Insert( 6, ' ' );


ASSERT( n == str.GetLength( ) );


printf ( “2: %s\n”, (LPCTSTR) STR );


n = str.Insert(555, ‘1’);


ASSERT( n == str.GetLength ( ) );


printf ( “3: %s\n”, ( LPCTSTR ) str );


输出


1. Hockeyis Best


2. Hockey is Best


3. Hockey is Best!






前言:串操作是编程中最常用也最基本的操作之一。 做为VC程序员,无论是菜鸟或高手都曾用过Cstring。而且好像实际编程中很难离得开它(虽然它不是标准C++中的库)。因为MFC中提供的这个类对我们操作字串实在太方便了,CString不仅提供各种丰富的操作函数、操作符重载,使我们使用起串起来更象basic中那样直观;而且它还提供了动态内存分配,使我们减少了多少字符串数组越界的隐患。但是,我们在使用过程中也体会到CString简直太容易出错了,而且有的不可捉摸。所以有许多高人站过来,建议抛弃它。

在此,我个人认为:CString封装得确实很完美,它有许多优点,如“容易使用 ,功能强,动态分配内存,大量进行拷贝时它很能节省内存资源并且执行效率高,与标准C完全兼容,同时支持多字节与宽字节,由于有异常机制所以使用它安全方便” 其实,使用过程中之所以容易出错,那是因为我们对它了解得还不够,特别是它的实现机制。因为我们中的大多数人,在工作中并不那么爱深入地去看关于它的文档,何况它还是英文的。

由于前几天我在工作中遇到了一个本不是问题但却特别棘手、特别难解决而且莫名惊诧的问题。好来最后发现是由于CString引发的。所以没办法,我把整个CString的实现全部看了一遍,才慌然大悟,并彻底弄清了问题的原因(这个问题,我已在csdn上开贴)。在此,我想把我的一些关于CString的知识总结一番,以供他(她)人借鉴,也许其中有我理解上的错误,望发现者能通知我,不胜感谢。

1. CString实现的机制.

CString是通过“引用”来管理串的,“引用”这个词我相信大家并不陌生,象Window内核对象、COM对象等都是通过引用来实现的。而CString也是通过这样的机制来管理分配的内存块。实际上CString对象只有一个指针成员变量,所以任何CString实例的长度只有4字节.

即: int len = sizeof(CString);//len等于4

这个指针指向一个相关的引用内存块,如图: CString str("abcd");

‘A’

‘B’

‘C’

‘D’

0

0x04040404 head部,为引用内存块相关信息

str 0x40404040

正因为如此,一个这样的内存块可被多个CString所引用,例如下列代码:

CString str("abcd");

CString a = str;

CString b(str);

CString c;

c = b;

上面代码的结果是:上面四个对象(str,a,b,c)中的成员变量指针有相同的值,都为0x40404040.而这块内存块怎么知道有多少个CString引用它呢?同样,它也会记录一些信息。如被引用数,串长度,分配内存长度。

这块引用内存块的结构定义如下:

struct CStringData

{

long nRefs; //表示有多少个CString 引用它. 4

int nDataLength; //串实际长度. 4

int nAllocLength; //总共分配的内存长度(不计这头部的12字节). 4

};

由于有了这些信息,CString就能正确地分配、管理、释放引用内存块。

如果你想在调试程序的时候获得这些信息。可以在Watch窗口键入下列表达式:

(CStringData*)((CStringData*)(this->m_pchData)-1)或

(CStringData*)((CStringData*)(str.m_pchData)-1)//str为指CString实例

正因为采用了这样的好机制,使得CString在大量拷贝时,不仅效率高,而且分配内存少。

2.LPCTSTR 与 GetBuffer(int nMinBufLength)

这两个函数提供了与标准C的兼容转换。在实际中使用频率很高,但却是最容易出错的地方。这两个函数实际上返回的都是指针,但它们有何区别呢?以及调用它们后,幕后是做了怎样的处理过程呢?

(1) LPCTSTR 它的执行过程其实很简单,只是返回引用内存块的串地址。 它是作为操作符重载提供的,所以在代码中有时可以隐式转换,而有时却需强制转制。如:

CString str;

const char* p = (LPCTSTR)str;

//假设有这样的一个函数,Test(const char* p); 你就可以这样调用

Test(str);//这里会隐式转换为LPCTSTR

(2) GetBuffer(int nMinBufLength) 它类似,也会返回一个指针,不过它有点差别,返回的是LPTSTR

(3) 这两者到底有何不同呢?我想告诉大家,其本质上完全不一样,一般说LPCTSTR转换后只应该当常量使用,或者做函数的入参;而GetBuffer(...)取出指针后,可以通过这个指针来修改里面的内容,或者做函数的出参。为什么呢?也许经常有这样的代码:

CString str("abcd");

char* p = (char*)(const char*)str;

p[2] = 'z';

其实,也许有这样的代码后,你的程序并没有错,而且程序也运行得挺好。但它却是非常危险的。再看

CString str("abcd");

CString test = str;

....

char* p = (char*)(const char*)str;

p[2] = 'z';

strcpy(p, "akfjaksjfakfakfakj");//这下完蛋了

你知道此时,test中的值是多少吗?答案是"abzd"。它也跟着改变了,这不是你所期望发生的。但为什么会这样呢?你稍微想想就会明白,前面说过,因为CString是指向引用块的,str与test指向同一块地方,当你p[2]='z'后,当然test也会随着改变。所以用它做LPCTSTR做转换后,你只能去读这块数据,千万别去改变它的内容。

假如我想直接通过指针去修改数据的话,那怎样办呢?就是用GetBuffer(...).看下述代码:

CString str("abcd");

CString test = str;

....

char* p = str.GetBuffer(20);

p[2] = 'z'; // 执行到此,现在test中值却仍是"abcd"

strcpy(p, "akfjaksjfakfakfakj"); // 执行到此,现在test中值还是"abcd"

为什么会这样?其实GetBuffer(20)调用时,它实际上另外建立了一块新内块存,并分配20字节长度的buffer,而原来的内存块引用计数也相应减1. 所以执行代码后str与test是指向了两块不同的地方,所以相安无事。

(4) 不过这里还有一点注意事项:就是str.GetBuffer(20)后,str的分配长度为20,即指针p它所指向的buffer只有20字节长,给它赋值时,切不可超过,否则灾难离你不远了;如果指定长度小于原来串长度,如GetBuffer(1),实际上它会分配4个字节长度(即原来串长度);另外,当调用GetBuffer(...)后并改变其内容,一定要记得调用ReleaseBuffer(),这个函数会根据串内容来更新引用内存块的头部信息。

(5) 最后还有一注意事项,看下述代码:

char* p = NULL;

const char* q = NULL;

{

CString str = "abcd";

q = (LPCTSTR)str;

p = str.GetBuffer(20);

AfxMessageBox(q);// 合法的

strcpy(p, "this is test");//合法的,

}

AfxMessageBox(q);// 非法的,可能完蛋

strcpy(p, "this is test");//非法的,可能完蛋

这里要说的就是,当返回这些指针后, 如果CString对象生命结束,这些指针也相应无效。

3.拷贝 & 赋值 & "引用内存块" 什么时候释放?

下面演示一段代码执行过程

void Test()

{

CString str("abcd");

//str指向一引用内存块(引用内存块的引用计数为1,长度为4,分配长度为4)

CString a;

//a指向一初始数据状态,

a = str;

//a与str指向同一引用内存块(引用内存块的引用计数为2,长度为4,分配长度为4)

CString b(a);

//a、b与str指向同一引用内存块(引用内存块的引用计数为3,长度为4,分配长度为4)

{

LPCTSTR temp = (LPCTSTR)a;

//temp指向引用内存块的串首地址。(引用内存块的引用计数为3,长度为4,分配长度为4)

CString d = a;

//a、b、d与str指向同一引用内存块(引用内存块的引用计数为4, 长度为4,分配长度为4)

b = "testa";

//这条语句实际是调用CString::operator=(CString&)函数。 b指向一新分配的引用内存块。(新分配的引用内存块的 引用计数为1, 长度为5, 分配长度为5)

//同时原引用内存块引用计数减1. a、d与str仍指向原 引用内存块(引用内存块的引用计数为3,长度为4,分配长度为4)

}

//由于d生命结束,调用析构函数,导至引用计数减1(引用内存块的引用计数为2,长度为4,分配长度为4)

LPTSTR temp = a.GetBuffer(10);

//此语句也会导致重新分配新内存块。temp指向新分配引用内存块的串首地址(新 分配的引用内存块的引用计数为1,长度为0,分配长度为10)

//同时原引用内存块引用计数减1. 只有str仍 指向原引用内存块 (引用内存块的引用计数为1, 长度为4, 分配长度为4)

strcpy(temp, "temp");

//a指向的引用内存块的引用计数为1,长度为0,分配长度为10 a.ReleaseBuffer();//注意:a指向的引用内存块的引用计数为1,长度为4,分配长度为10

}

//执行到此,所有的局部变量生命周期都已结束。对象str a b 各自调用自己的析构构

//函数,所指向的引用内存块也相应减1

//注意,str a b 所分别指向的引用内存块的计数均为0,这导致所分配的内存块释放

通过观察上面执行过程,我们会发现CString虽然可以多个对象指向同一引用内块存,但是它们在进行各种拷贝、赋值及改变串内容时,它的处理是很智能并且非常安全的,完全做到了互不干涉、互不影响。当然必须要求你的代码使用正确恰当,特别是实际使用中会有更复杂的情况,如做函数参数、引用、及有时需保存到CStringList当中,如果哪怕有一小块地方使用不当,其结果也会导致发生不可预知的错误

5 FreeExtra()的作用

看这段代码

(1) CString str("test");

(2) LPTSTR temp = str.GetBuffer(50);

(3) strcpy(temp, "there are 22 character");

(4) str.ReleaseBuffer();

(5) str.FreeExtra();

上面代码执行到第(4)行时,大家都知道str指向的引用内存块计数为1,长度为22,分配长度为50. 那么执行str.FreeExtra()时,它会释放所分配的多余的内存。(引用内存块计数为1,长度为22,分配长度为22)

6 Format(...) 与 FormatV(...)

这条语句在使用中是最容易出错的。因为它最富有技巧性,也相当灵活。在这里,我没打算对它细细分析,实际上sprintf(...)怎么用,它就怎么用。我只提醒使用时需注意一点:就是它的参数的特殊性,由于编译器在编译时并不能去校验格式串参数与对应的变元的类型及长度。所以你必须要注意,两者一定要对应上,

否则就会出错。如:

CString str;

int a = 12;

str.Format("first:%l, second: %s", a, "error");//result?试试

7 LockBuffer() 与 UnlockBuffer()

顾名思议,这两个函数的作用就是对引用内存块进行加锁及解锁。但使用它有什么作用及执行过它后对CString串有什么实质上的影响。其实挺简单,看下面代码:

(1) CString str("test");

(2) str.LockBuffer();

(3) CString temp = str;

(4) str.UnlockBuffer();

(5) str.LockBuffer();

(6) str = "error";

(7) str.ReleaseBuffer();

执行完(3)后,与通常情况下不同,temp与str并不指向同一引用内存块。你可以在watch窗口用这个表达式(CStringData*)((CStringData*)(str.m_pchData)-1)看看。

其实在msdn中有说明:

While in a locked state, the string is protected in two ways:

No other string can get a reference to the data in the locked string, even if that string is assigned to the locked string.

The locked string will never reference another string, even if that other string is copied to the locked string.

8 CString 只是处理串吗?

不对,CString不只是能操作串,而且还能处理内存块数据。功能完善吧!看这段代码

char p[20];

for(int loop=0; loop<sizeof(p); loop++)

{

p[loop] = 10-loop;

}

CString str((LPCTSTR)p, 20);

char temp[20];

memcpy(temp, str, str.GetLength());

str完全能够转载内存块p到内存块temp中。所以能用CString来处理二进制数据

8 AllocSysString()与SetSysString(BSTR*)

这两个函数提供了串与BSTR的转换。使用时须注意一点:当调用AllocSysString()后,须调用它SysFreeString(...)

9 参数的安全检验

在MFC中提供了多个宏来进行参数的安全检查,如:ASSERT. 其中在CString中也不例外,有许多这样的参数检验,其实这也说明了代码的安全性高,可有时我们会发现这很烦,也导致Debug与Release版本不一样,如有时程序Debug通正常,而Release则程序崩溃;而有时恰相反,Debug不行,Release行。其实我个人认为,我们对CString的使用过程中,应力求代码质量高,不能在Debug版本中出现任何断言框,哪怕release运行似乎看起来一切正常。但很不安全。如下代码:

(1) CString str("test");

(2) str.LockBuffer();

(3) LPTSTR temp = str.GetBuffer(10);

(4) strcpy(temp, "error");

(5) str.ReleaseBuffer();

(6) str.ReleaseBuffer();//执行到此时,Debug版本会弹出错框

10 CString的异常处理

我只想强调一点:只有分配内存时,才有可能导致抛出CMemoryException.

同样,在msdn中的函数声明中,注有throw( CMemoryException)的函数都有重新分配或调整内存的可能。

11 跨模块时的Cstring。即一个DLL的接口函数中的参数为CString&时,它会发生怎样的现象。解答我遇到的问题。我的问题原来已经发贴,地址为:

http://www.csdn.net/expert/topic/741/741921.xml?temp=.2283136

构造一个这样CString对象时,如CString str,你可知道此时的str所指向的引用内存块吗?也许你会认为它指向NULL。其实不对,如果这样的话,CString所采用的引用机制管理内存块就会有麻烦了,所以CString在构造一个空串的对象时,它会指向一个固定的初始化地址,这块数据的声明如下:

AFX_STATIC_DATA int _afxInitData[] = {-1,0,0,0};

简要描述概括一下:当某个CString对象串置空的话,如Empty(),CString a等,它的成员变量m_pchData就会指向_afxInitData这个变量的地址。当这个CString对象生命周期结束时,正常情况下它会去对所指向的引用内存块计数减1,如果引用计数为0(即没有任何CString引用它时),则释放这块引用内存。而现在的情况是如果CString所指向的引用内存块是初始化内存块时,则不会释放任何内存。

说了这么多,这与我遇到的问题有什么关系呢?其实关系大着呢?其真正原因就是如果exe模块与dll模块有一个是static编译连接的话。那么这个CString初始化数据在exe模块与dll模块中有不同的地址,因为static连接则会在本模块中有一份源代码的拷贝。另外一种情况,如果两个模块都是share连接的,CString的实现代码则在另一个单独的dll中实现,而AFX_STATIC_DATA指定变量只装一次,所以两个模块中_afxInitData有相同的地址。

现在问题完全明白了吧!你可以自己去演示一下。

__declspec (dllexport) void test(CString& str)

{

str = "abdefakdfj";//如果是static连接,并且传入的str为空串的话,这里出错。

}

最后一点想法:写得这里,其实CString中还有许多技巧性的好东东,我并没去解释。如很多重载的操作符、查找等。我认为还是详细看看msdn,这样也许会比我讲的好多了。我只侧重那些可能会出错的情况。当然,如我上面叙述中有错误,敬请高手指点,不胜感谢!



CString位于头文件afx.h中。
CString 的 成员函数
<wbr style="">CString的构造函数</wbr><wbr style=""></wbr><wbr style=""><br style=""> CString( );<br style=""> 例:CString csStr;<br style=""><br style=""> CString( const CString&amp; stringSrc );<br style=""> 例:CString csStr("ABCDEF中文123456");<br style=""> CString csStr2(csStr);<br style=""><br style=""> CString( TCHAR ch, int nRepeat = 1 );<br style=""> 例:CString csStr('a',5);<br style=""><span style="font-size:14px; color:#990000; line-height:1.5em">//csStr="aaaaa"</span><wbr style=""><br style=""><br style=""> CString( LPCTSTR lpch, int nLength );<br style=""> 例:CString csStr("abcdef",3);<br style=""><span style="font-size:14px; color:#990000; line-height:1.5em">//csStr="abc"</span><wbr style=""><br style=""><br style=""> CString( LPCWSTR lpsz );<br style=""> 例:wchar_t s[]=L"abcdef";<br style=""> CString csStr(s);<br style=""><span style="font-size:14px; color:#990000; line-height:1.5em">//csStr=L"abcdef"</span><wbr style=""><br style=""><br style=""> CString( const unsigned char* psz );<br style=""> 例:const unsigned char s[]="abcdef";<br style=""> const unsigned char* sp=s;<br style=""> CString csStr(sp);<br style=""><span style="font-size:14px; color:#990000; line-height:1.5em">//csStr="abcdef"</span><wbr style=""><br style=""><br style=""> CString( LPCSTR lpsz );<br style=""> 例:CString csStr("abcdef");<br style=""><span style="font-size:14px; color:#990000; line-height:1.5em">//csStr="abcdef"</span><wbr style=""><br style=""><br style=""><span style="font-size:14px; color:#0000cc; line-height:1.5em"><span style=""><wbr style="">int GetLength( ) const;</wbr></span><wbr style=""></wbr></span><wbr style=""><br style=""> 返回字符串的长度,不包含结尾的空字符。<br style=""> 例:csStr="ABCDEF中文123456";<br style=""> printf("%d",csStr.GetLength());<span style="font-size:14px; color:#990000; line-height:1.5em">//16</span><wbr style=""><br style=""><br style=""><span style="font-size:14px; color:#0000cc; line-height:1.5em"><span style=""><wbr style="">void MakeReverse( );</wbr></span><wbr style=""></wbr></span><wbr style=""><br style=""> 颠倒字符串的顺序<br style=""> 例:csStr="ABCDEF中文123456";<br style=""> csStr.MakeReverse();<br style=""> cout&lt;&lt;csStr;<span style="font-size:14px; color:#990000; line-height:1.5em">//654321文中FEDCBA</span><wbr style=""><br style=""><br style=""><span style=""><wbr style=""><span style="font-size:14px; color:#0000cc; line-height:1.5em">void MakeUpper( );</span><wbr style=""></wbr></wbr></span><wbr style=""><br style=""> 将小写字母转换为大写字母<br style=""> 例:csStr="abcdef中文123456";<br style=""> csStr.MakeUpper();<br style=""> cout&lt;&lt;csStr;<span style="font-size:14px; color:#990000; line-height:1.5em">//ABCDEF中文123456</span><wbr style=""><br style=""><br style=""><span style="font-size:14px; color:#0000cc; line-height:1.5em"><span style=""><wbr style="">void MakeLower( );</wbr></span><wbr style=""></wbr></span><wbr style=""><br style=""> 将大写字母转换为小写字母<br style=""> 例:csStr="ABCDEF中文123456";<br style=""> csStr.MakeLower();<br style=""> cout&lt;&lt;csStr;<span style="font-size:14px; color:#990000; line-height:1.5em">//abcdef中文123456</span><wbr style=""><br style=""><br style=""><span style="font-size:14px; color:#0000cc; line-height:1.5em"><span style=""><wbr style="">int Compare( LPCTSTR lpsz ) const;</wbr></span><wbr style=""></wbr></span><wbr style=""><br style=""> 区分大小写比较两个字符串,相等时返回0,大于时返回1,小于时返回-1<br style=""> 例:csStr="abcdef中文123456";<br style=""> csStr2="ABCDEF中文123456";<br style=""> cout&lt;&lt;csStr.CompareNoCase(csStr2);<span style="font-size:14px; color:#990000; line-height:1.5em">//0</span><wbr style=""><br style=""><br style=""><span style="font-size:14px; color:#0000cc; line-height:1.5em"><span style=""><wbr style="">int CompareNoCase( LPCTSTR lpsz ) const;</wbr></span><wbr style=""></wbr></span><wbr style=""><br style=""> 不区分大小写比较两个字符串,相等时返回0,大于时返回1,小于时返回-1<br style=""> 例:csStr="abcdef中文123456";<br style=""> csStr2="ABCDEF中文123456";<br style=""> cout&lt;&lt;csStr.CompareNoCase(csStr2);<span style="font-size:14px; color:#990000; line-height:1.5em">//-1</span><wbr style=""><br style=""><br style=""><span style="font-size:14px; color:#0000cc; line-height:1.5em"><span style=""><wbr style="">int Delete( int nIndex, int nCount = 1 )</wbr></span><wbr style=""></wbr></span><wbr style=""><br style=""> 删除字符,删除从下标nIndex开始的nCount个字符<br style=""> 例:csStr="ABCDEF";<br style=""> csStr.Delete(2,3);<br style=""> cout&lt;&lt;csStr;<span style="font-size:14px; color:#990000; line-height:1.5em">// ABF<br style=""> //当nIndex过大,超出对像所在内存区域时,函数没有任何操作。<br style=""> //当nIndex为负数时,从第一个字符开始删除。<br style=""> //当nCount过大,导致删除字符超出对像所在内存区域时,会发生无法预料的结果。<br style=""> //当nCount为负数时,函数没有任何操作。</span><wbr style=""><br style=""><br style=""><span style="font-size:14px; color:#0000cc; line-height:1.5em"><span style=""><wbr style="">int Insert( int nIndex, TCHAR ch )<br style=""> int Insert( int nIndex, LPCTSTR pstr )</wbr></span><wbr style=""></wbr></span><wbr style=""><br style=""> 在下标为nIndex的位置,插入字符或字符串。返回插入后对象的长度<br style=""> 例:csStr="abc";<br style=""> csStr.Insert(2,'x');<br style=""> cout&lt;&lt;csStr;<span style="font-size:14px; color:#990000; line-height:1.5em">//abxc<br style=""></span><wbr style="">csStr="abc";<br style=""> csStr.Insert(2,"xyz");<br style=""> cout&lt;&lt;csStr;<span style="font-size:14px; color:#990000; line-height:1.5em">//abxyzc</span><wbr style=""><br style=""><span style="font-size:14px; color:#990000; line-height:1.5em">//当nIndex为负数时,插入在对象开头<br style=""> //当nIndex超出对象末尾时,插入在对象末尾</span><wbr style=""><br style=""><br style=""><span style="font-size:14px; color:#0000cc; line-height:1.5em"><span style=""><wbr style="">int Remove( TCHAR ch );</wbr></span><wbr style=""></wbr></span><wbr style=""><br style=""> 移除对象内的指定字符。返回移除的数目<br style=""> 例:csStr="aabbaacc";<br style=""> csStr.Remove('a');<br style=""> cout&lt;&lt;csStr;<span style="font-size:14px; color:#990000; line-height:1.5em">//bbcc</span><wbr style=""><br style=""><br style=""><span style="font-size:14px; color:#0000cc; line-height:1.5em"><span style=""><wbr style="">int Replace( TCHAR chOld, TCHAR chNew );<br style=""> int Replace( LPCTSTR lpszOld, LPCTSTR lpszNew );</wbr></span><wbr style=""></wbr></span><wbr style=""><br style=""> 替换字串<br style=""> 例:csStr="abcdef";<br style=""> csStr.Replace('a','x');<br style=""> cout&lt;&lt;csStr;<span style="font-size:14px; color:#990000; line-height:1.5em">//xbcdef</span><wbr style=""><br style=""> csStr="abcdef";<br style=""> csStr.Replace("abc","xyz");<br style=""> cout&lt;&lt;csStr;<span style="font-size:14px; color:#990000; line-height:1.5em">//xyzdef</span><wbr style=""><br style=""><br style=""><span style="font-size:14px; color:#0000cc; line-height:1.5em"><span style=""><wbr style="">void TrimLeft( );<br style=""> void TrimLeft( TCHAR chTarget );<br style=""> void TrimLeft( LPCTSTR lpszTargets );</wbr></span><wbr style=""></wbr></span><wbr style=""><br style=""> 从左删除字符,被删的字符与chTarget或lpszTargets匹配,一直删到第一个不匹配的字符为止<br style=""> 例:csStr="aaabaacdef";<br style=""> csStr.TrimLeft('a');<br style=""> cout&lt;&lt;csStr;<span style="font-size:14px; color:#990000; line-height:1.5em">//baacdef<br style=""></span><wbr style="">csStr="aaabaacdef";<br style=""> csStr.TrimLeft("ab");<br style=""> cout&lt;&lt;csStr;<span style="font-size:14px; color:#990000; line-height:1.5em">//cdef</span><wbr style=""><br style=""><span style="font-size:14px; color:#990000; line-height:1.5em">//无参数时删除空格</span><wbr style=""><br style=""><br style=""><span style="font-size:14px; color:#0000cc; line-height:1.5em"><span style=""><wbr style="">void TrimRight( );<br style=""> void TrimRight( TCHAR chTarget );<br style=""> void TrimRight( LPCTSTR lpszTargets );</wbr></span><wbr style=""></wbr></span><wbr style=""><br style=""> 从右删除字符,被删的字符与chTarget或lpszTargets匹配,一直删到第一个不匹配的字符为止<br style=""> 例:csStr="abcdeaafaaa";<br style=""> csStr.TrimRight('a');<br style=""> cout&lt;&lt;csStr;<span style="font-size:14px; color:#990000; line-height:1.5em">//abcdeaaf</span><wbr style=""><br style=""> csStr="abcdeaafaaa";<br style=""> csStr.TrimRight("fa");<br style=""> cout&lt;&lt;csStr;<span style="font-size:14px; color:#990000; line-height:1.5em">//abcde<br style=""> //无参数时删除空格</span><wbr style=""><br style=""><br style=""><span style="font-size:14px; color:#0000cc; line-height:1.5em"><span style=""><wbr style="">void Empty( );</wbr></span><wbr style=""></wbr></span><wbr style=""><br style=""> 清空<br style=""> 例:csStr="abcdef";<br style=""> csStr.Empty();<br style=""> printf("%d",csStr.GetLength());<span style="font-size:14px; color:#990000; line-height:1.5em">//0</span><wbr style=""><br style=""><br style=""><span style="font-size:14px; color:#0000cc; line-height:1.5em"><span style=""><wbr style="">BOOL IsEmpty( ) const;</wbr></span><wbr style=""></wbr></span><wbr style=""><br style=""> 测试对象是否为空,为空时返回零,不为空时返回非零<br style=""> 例:csStr="abc";<br style=""> cout&lt;&lt;csStr.IsEmpty();<span style="font-size:14px; color:#990000; line-height:1.5em">//0;<br style=""></span><wbr style="">csStr.Empty();<br style=""> cout&lt;&lt;csStr.IsEmpty();<span style="font-size:14px; color:#990000; line-height:1.5em">//1;</span><wbr style=""><br style=""><br style=""><span style="font-size:14px; color:#0000cc; line-height:1.5em"><span style=""><wbr style="">int Find( TCHAR ch ) const;<br style=""> int Find( LPCTSTR lpszSub ) const;<br style=""> int Find( TCHAR ch, int nStart ) const;<br style=""> int Find( LPCTSTR pstr, int nStart ) const;</wbr></span><wbr style=""></wbr></span><wbr style=""><br style=""> 查找字串,nStart为开始查找的位置。未找到匹配时返回-1,否则返回字串的开始位置<br style=""> 例:csStr="abcdef";<br style=""> cout&lt;&lt;csStr.Find('b');<span style="font-size:14px; color:#990000; line-height:1.5em">//1<br style=""></span><wbr style="">cout&lt;&lt;csStr.Find("de");<span style="font-size:14px; color:#990000; line-height:1.5em">//3</span><wbr style=""><br style=""> cout&lt;&lt;csStr.Find('b',3);<span style="font-size:14px; color:#990000; line-height:1.5em">//-1</span><wbr style=""><br style=""> cout&lt;&lt;csStr.Find('b',0);<span style="font-size:14px; color:#990000; line-height:1.5em">//1</span><wbr style=""><br style=""> cout&lt;&lt;csStr.Find("de",4);<span style="font-size:14px; color:#990000; line-height:1.5em">//-1</span><wbr style=""><br style=""> cout&lt;&lt;csStr.Find("de",0);<span style="font-size:14px; color:#990000; line-height:1.5em">//3</span><wbr style=""><br style=""><span style="font-size:14px; color:#990000; line-height:1.5em">//当nStart超出对象末尾时,返回-1。<br style=""> //当nStart为负数时,返回-1。</span><wbr style=""><br style=""><br style=""><span style="font-size:14px; color:#0000cc; line-height:1.5em"><span style=""><wbr style="">int FindOneOf( LPCTSTR lpszCharSet ) const;</wbr></span><wbr style=""></wbr></span><wbr style=""><br style=""> 查找lpszCharSet中任意一个字符在CString对象中的匹配位置。未找到时返回-1,否则返回字串的开始位置<br style=""> 例:csStr="abcdef";<br style=""> cout&lt;&lt;csStr.FindOneOf("cxy");<span style="font-size:14px; color:#990000; line-height:1.5em">//2</span><wbr style=""><br style=""><br style=""><span style="font-size:14px; color:#0000cc; line-height:1.5em"><span style=""><wbr style="">CString SpanExcluding( LPCTSTR lpszCharSet ) const;</wbr></span><wbr style=""></wbr></span><wbr style=""><br style=""> 返回对象中与lpszCharSet中任意匹配的第一个字符之前的子串<br style=""> 例:csStr="abcdef";<br style=""> cout&lt;&lt;csStr.SpanExcluding("cf");<span style="font-size:14px; color:#990000; line-height:1.5em">//ab</span><wbr style=""><br style=""><br style=""><span style="font-size:14px; color:#0000cc; line-height:1.5em"><span style=""><wbr style="">CString SpanIncluding( LPCTSTR lpszCharSet ) const;</wbr></span><wbr style=""></wbr></span><wbr style=""><br style=""> 从对象中查找与lpszCharSe中任意字符不匹配的字符,并返回第一个不匹配字符之前的字串<br style=""> 例:csStr="abcdef";<br style=""> cout&lt;&lt;csStr.SpanIncluding("fdcba");<span style="font-size:14px; color:#990000; line-height:1.5em">//abcd</span><wbr style=""><br style=""><br style=""><span style="font-size:14px; color:#0000cc; line-height:1.5em"><span style=""><wbr style="">int ReverseFind( TCHAR ch ) const;</wbr></span><wbr style=""></wbr></span><wbr style=""><br style=""> 从后向前查找第一个匹配,找到时返回下标。没找到时返回-1<br style=""> 例:csStr="abba";<br style=""> cout&lt;&lt;csStr.ReverseFind('a');<span style="font-size:14px; color:#990000; line-height:1.5em">//3</span><wbr style=""><br style=""><br style=""><span style="font-size:14px; color:#0000cc; line-height:1.5em"><span style=""><wbr style="">void Format( LPCTSTR lpszFormat, ... );<br style=""> void Format( UINT nFormatID, ... );</wbr></span><wbr style=""></wbr></span><wbr style=""><br style=""> 格式化对象,与C语言的sprintf函数用法相同<br style=""> 例:csStr.Format("%d",13);<br style=""> cout&lt;&lt;csStr;<span style="font-size:14px; color:#990000; line-height:1.5em">//13</span><wbr style=""><br style=""><br style=""><span style="font-size:14px; color:#0000cc; line-height:1.5em"><span style=""><wbr style="">TCHAR GetAt( int nIndex ) const;</wbr></span><wbr style=""></wbr></span><wbr style=""><br style=""> 返回下标为nIndex的字符,与字符串的[]用法相同<br style=""> 例:csStr="abcdef";<br style=""> cout&lt;&lt;csStr.GetAt(2);<span style="font-size:14px; color:#990000; line-height:1.5em">//c<br style=""> //当nIndex为负数或超出对象末尾时,会发生无法预料的结果。</span><wbr style=""><br style=""><br style=""><span style="font-size:14px; color:#0000cc; line-height:1.5em"><span style=""><wbr style="">void SetAt( int nIndex, TCHAR ch );</wbr></span><wbr style=""></wbr></span><wbr style=""><br style=""> 给下标为nIndex的字符重新赋值<br style=""> 例:csStr="abcdef";<br style=""> csStr.SetAt(2,'x');<br style=""> cout&lt;&lt;csStr;<span style="font-size:14px; color:#990000; line-height:1.5em">//abxdef<br style=""> //当nIndex为负数或超出对象末尾时,会发生无法预料的结果。</span><wbr style=""><br style=""><br style=""><span style="font-size:14px; color:#0000cc; line-height:1.5em"><span style=""><wbr style="">CString Left( int nCount ) const;</wbr></span><wbr style=""></wbr></span><wbr style=""><br style=""> 从左取字串<br style=""> 例:csStr="abcdef";<br style=""> cout&lt;&lt;csStr.Left(3);<span style="font-size:14px; color:#990000; line-height:1.5em">//abc<br style=""> //当nCount等于0时,返回空。<br style=""> //当nCount为负数时,返回空。<br style=""> //当nCount大于对象长度时,返回值与对象相同。</span><wbr style=""><br style=""><br style=""><span style="font-size:14px; color:#0000cc; line-height:1.5em"><span style=""><wbr style="">CString Right( int nCount ) const;</wbr></span><wbr style=""></wbr></span><wbr style=""><br style=""> 从右取字串<br style=""> 例:csStr="abcdef";<br style=""> cout&lt;&lt;csStr.Right(3);<span style="font-size:14px; color:#990000; line-height:1.5em">//def<br style=""> //当nCount等于0时,返回空。<br style=""> //当nCount为负数时,返回空。<br style=""> //当nCount大于对象长度时,返回值与对象相同。</span><wbr style=""><br style=""><br style=""><span style="font-size:14px; color:#0000cc; line-height:1.5em"><span style=""><wbr style="">CString Mid( int nFirst ) const;<br style=""> CString Mid( int nFirst, int nCount ) const;</wbr></span><wbr style=""></wbr></span><wbr style=""><br style=""> 从中间开始取字串<br style=""> 例:csStr="abcdef";<br style=""> cout&lt;&lt;csStr.Mid(2);<span style="font-size:14px; color:#990000; line-height:1.5em">//cdef<br style=""></span><wbr style="">csStr="abcdef";<br style=""> cout&lt;&lt;csStr.Mid(2,3);<span style="font-size:14px; color:#990000; line-height:1.5em">//cde<br style=""> //当nFirst为0和为负数时,从第一个字符开始取。<br style=""> //当nFirst等于对象末尾时,返回空字串。<br style=""> //当nFirst超出对象末尾时,会发生无法预料的结果。<br style=""> //当nCount超出对象末尾时,返回从nFirst开始一直到对象末尾的字串<br style=""> //当nCount为0和为负数时,返回空字串。</span><wbr style=""><br style=""><br style=""><span style="font-size:14px; color:#0000cc; line-height:1.5em"><span style=""><wbr style="">LPTSTR GetBuffer( int nMinBufLength );</wbr></span><wbr style=""></wbr></span><wbr style=""><br style=""> 申请新的空间,并返回指针<br style=""> 例:csStr="abcde";<br style=""> LPTSTR pStr=csStr.GetBuffer(10);<br style=""> strcpy(pStr,"12345");<br style=""> csStr.ReleaseBuffer();<br style=""> pStr=NULL;<br style=""> cout&lt;&lt;csStr<span style="font-size:14px; color:#990000; line-height:1.5em">//12345<br style=""> //使用完GetBuffer后,必须使用ReleaseBuffer以更新对象内部数据,否则会发生无法预料的结果。</span><wbr style=""><br style=""><br style=""><span style="font-size:14px; color:#0000cc; line-height:1.5em"><span style=""><wbr style="">void ReleaseBuffer( int nNewLength = -1 );</wbr></span><wbr style=""></wbr></span><wbr style=""><br style=""> 使用GetBuffer后,必须使用ReleaseBuffer以更新对象内部数据<br style=""> 例:csStr="abc";<br style=""> LPTSTR pStr=csStr.GetBuffer(10);<br style=""> strcpy(pStr,"12345");<br style=""> cout&lt;&lt;csStr.GetLength();<span style="font-size:14px; color:#990000; line-height:1.5em">//3(错误的用法)</span><wbr style=""><br style=""> csStr.ReleaseBuffer();<br style=""> cout&lt;&lt;csStr.GetLength();<span style="font-size:14px; color:#990000; line-height:1.5em">//5(正确)<br style=""></span><wbr style="">pStr=NULL;<br style=""><span style="font-size:14px; color:#990000; line-height:1.5em">//CString对象的任何方法都应在ReleaseBuffer之后调用</span><wbr style=""><br style=""><br style=""><span style="font-size:14px; color:#0000cc; line-height:1.5em"><span style=""><wbr style="">LPTSTR GetBufferSetLength( int nNewLength );</wbr></span><wbr style=""></wbr></span><wbr style=""><br style=""> 申请新的空间,并返回指针<br style=""> 例:csStr="abc";<br style=""> csStr.GetBufferSetLength(20);<br style=""> cout&lt;&lt;csStr;<span style="font-size:14px; color:#990000; line-height:1.5em">//abc<br style=""></span><wbr style="">count&lt;&lt;csStr.GetLength();<span style="font-size:14px; color:#990000; line-height:1.5em">//20;<br style=""></span><wbr style="">csStr.ReleaseBuffer();<br style=""> count&lt;&lt;csStr.GetLength();<span style="font-size:14px; color:#990000; line-height:1.5em">//3;<br style=""> //使用GetBufferSetLength后可以不必使用ReleaseBuffer。</span></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>



数据类型转换函数

CString CZjyDlg::VariantToString(VARIANT var)

{

CString strValue;

_variant_t var_t;

_bstr_t bstr_t;

time_t cur_time;

CTime time_value;

COleCurrency var_currency;

switch(var.vt)

{

case VT_EMPTY:

case VT_NULL:strValue=_T("");break;

case VT_UI1:strValue.Format("%d",var.bVal);break;

case VT_I2:strValue.Format("%d",var.iVal);break;

case VT_I4:strValue.Format("%d",var.lVal);break;

case VT_R4:strValue.Format("%f",var.fltVal);break;

case VT_R8:strValue.Format("%f",var.dblVal);break;

case VT_CY:

var_currency=var;

strValue=var_currency.Format(0);break;

case VT_BSTR:

var_t =var;

bstr_t=var_t;

strValue.Format("%s",(const char *)bstr_t);break;

case VT_DATE:

cur_time=var.date;

time_value=cur_time;

strValue.Format("%A,%B,%d,%Y");break;

case VT_BOOL:strValue.Format("%d",var.boolVal);break;

default:strValue=_T("");break;

}

return strValue;

}


在多线程中使用一个局部CString变量相加时发现相加的结果是后一个字符串值,没有时间过多研究,只好改成了char*,不过如下方法也可以避免:
CWin32HeapstringHeap(HEAP_NO_SERIALIZE,0,0);
CAtlStringMgrstringMgr(
&stringHeap);
CStringstrstate(
&stringMgr);

找了一些资料贴上来希望对过客有用:
http://www.cppblog.com/alantop/archive/2008/07/10/55786.html

讨论CString线程安全性问题(内存泄漏)

CString在线程处理中,稍有处理不当,极易引起内存泄漏。
让我们来看一个例子:
在线程函数中使用如下代码

CStringstrstate;
strstate.Format("正在解密,请稍后...(共%d张地图)",p->m_countmap);

可以看到非常简单,在debug下,很容易看到如下的内存泄漏。



怎么回事?
先把修改好的代码放上来
CWin32HeapstringHeap(HEAP_NO_SERIALIZE,0,0);
CAtlStringMgrstringMgr(&stringHeap);
CStringstrstate(&stringMgr);
strstate.Format("正在解密,请稍后...(共%d张地图)",p->m_countmap);
如上代码才具有线程安全性。

http://msdn.microsoft.com/zh-cn/library/cc485480(VS.71).aspx

Visual C++ 概念:添加功能
自定义字符串管理器的实现(基本方法)

为字符串数据自定义内存分配方案的最简单的方式是使用 ATL 提供的CAtlStringMgr类,但您需要自己提供内存分配例程。CAtlStringMgr的构造函数采用单一参数:即指向IAtlMemMgr对象的指针。IAtlMemMgr是提供到堆的一般接口的抽象基类。通过IAtlMemMgr接口,CAtlStringMgr分配、重新分配和释放用于存储字符串数据的内存。您既可以自已实现IAtlMemMgr接口,也可以使用由 ATL 提供的五个内存管理器类之一。ATL 提供的内存管理器只包装现有的内存分配功能:

要进行字符串内存管理,最有用的类是CWin32Heap,因为它使您能够创建多个独立的堆。例如,如果使用仅用于字符串的独立堆,可进行以下操作:

//Declare a thread-safe, growable, private heap with initial size 0
CWin32Heap g_stringHeap( 0, 0, 0 );
// Declare a string manager that uses the private heap
CAtlStringMgr g_stringMgr( &g_stringHeap ); 

要使用此专用的字符串管理器来管理CString变量的内存,请将一个指针传递给管理器作为CString变量的构造函数的一个参数:

void PrintPowers( int nBase )
{
int n = 1;
for( int nPower = 0; nPower < 10; nPower++ )
{
// Use the private string manager, instead of the default
CString strPower( &g_stringMgr );
strPower.Format( "%d", n );
printf( "%s\n", LPCSTR( strPower ) );
n *= nBase;
}
}

http://blog.csdn.net/zero_dian/archive/2006/01/08/573352.aspx谈新手对CString的使用
CString类功能强大,比STL的string类有过之无不及.新手使用CString时,都会被它强大的功能所吸引.然而由于对它内部机制的不了解,新手在将CString向C的字符数组转换时容易出现很多问题.因为CString已经重载了LPCTSTR运算符,所以CString类向const char *转换时没有什么麻烦,如下所示:
  char a[100];
  CString str("aaaaaa");
  strncpy(a,(LPCTSTR)str,sizeof(a));
  或者如下:

  strncpy(a,str,sizeof(a));

  以上两种用法都是正确地.因为strncpy的第二个参数类型为const char *.所以编译器会自动将CString类转换成const char *.很多人对LPCTSTR是什么东西迷惑不解,让我们来看看:

  1.LP表示长指针,在win16下有长指针(LP)和短指针(P)的区别,而在win32下是没有区别的,都是32位.所以这里的LP和P是等价的.

  2.C表示const

  3.T是什么东西呢,我们知道TCHAR在采用UNICODE方式编译时是wchar_t,在普通时编译成char那么就可以看出LPCTSTR(PCTSTR)在UINCODE时是const wchar_t *,PCWSTR,LPCWSTR,在多字节字符模式时是const char *, PCSTR,LPCSTR.接下来我们看在非UNICODE情况下,怎样将CString转换成char *,很多初学者都为了方便采用如下方法:
  (char *)(LPCSTR)str

  这样对吗?我们首先来看一个例子:
  CString str("aa");
  strcpy((char *)(LPCTSTR)str,"aaaaaaaa");
  cout<<(LPCTSTR)str<<endl;

  在Debug下运行出现了异常,我们都知道CString类内部有自己的字符指针,指向一个已分配的字符缓冲区.如果往里面写的字符数超出了缓冲区范围,当然会出现异常.但这个程序在Release版本下不会出现问题.原来对CString类已经进行了优化.当需要分配的内存小于64字节时,直接分配64字节的内存,以此类推,一般CString类字符缓冲区的大小为64,128,256,512...这样是为了减少内存分配的次数,提高速度.

  那有人就说我往里面写的字符数不超过它原来的字符数,不就不会出错了,比如
  CString str("aaaaaaa");
  strcpy((char *)(LPCTSTR)str,"aa");
  cout<<(LPCTSTR)str<<endl;

  这样看起来是没什么问题.我们再来看下面这个例子:
  CString str("aaaaaaa");
  strcpy((char *)(LPCTSTR)str,"aa");
  cout<<(LPCTSTR)str<<endl;
  cout<<str.GetLength()<<endl;

  我们看到str的长度没有随之改变,继续为7而不是2.还有更严重的问题:
  CString str("aaaaaaa");
  CString str1 = str;
  strcpy((char *)(LPCTSTR)str,"aa");
  cout<<(LPCTSTR)str<<endl;
  cout<<(LPCTSTR)str1<<endl;

  按说我们只改变了str,str1应该没有改变呀,可是事实时他们都变成了"aa".难道str和str1里面的字符指针指向的缓冲区是一个.我们在Effective C++里面得知,如果你的类内部有包含指针,请为你的类写一个拷贝构造函数和赋值运算符.不要让两个对象内部的指针指向同一区域,而应该重新分配内存.难道是微软犯了错?

  原来这里还有一个"写时复制"和"引用计数"的概念.CString类的用途很广,这样有可能在系统内部产生大量的CString临时对象.这时为了优化效率,就采用在系统软件内部广泛使用的"写时复制"概念.即当从一个CString产生另一个CString并不复制它的字符缓冲区内容,而只是将字符缓冲区的"引用计数"加1.当需要改写字符缓冲区内的内容时,才分配内存,并复制内容.以后我会给出一个"写时复制"和"引用计数"的例子我们回到主题上来,当我们需要将CString转换成char *时,我们应该怎么做呢?其时只是麻烦一点,如下所示:
  CString str("aaaaaaa");
  strcpy(str.GetBuffer(10),"aa");
  str.ReleaseBuffer();

  当我们需要字符数组时调用GetBuffer(int n),其中n为我们需要的字符数组的长度.使用完成后一定要马上调用ReleaseBuffer();还有很重要的一点就是,在能使用const char *的地方,就不要使用char *


分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics