CString之GetBuffer()

转载自:http://hayyoungsue.blog.163.com/blog/static/1238409772010214002734/

LPTSTR GetBuffer( int nMinBufLength ) 这个函数是CString 的一个比较实用的函数,请看如下示例:

GetBuffer(int nMinBufLength);的参数问题一直比较困扰人,网站的资料还像也不是太好给的,请看msdn解释

Parameters

nMinBufLength

The minimum size of the character buffer in characters. This value does not include space for a null terminator.

得到buffer的最小长度,当然这是由我们自己设定的一个参数,其原型定义如下:

LPTSTR CString::GetBuffer(int nMinBufLength)

{

 ASSERT(nMinBufLength >= 0);

 if (GetData()->nRefs > 1 || nMinBufLength > GetData()->nAllocLength)

 {

#ifdef _DEBUG

  // give a warning in case locked string becomes unlocked

  if (GetData() != _afxDataNil && GetData()->nRefs < 0)

   TRACE0("Warning: GetBuffer on locked CString creates unlocked CString!\n");

#endif

  // we have to grow the buffer

  CStringData* pOldData = GetData();

  int nOldLen = GetData()->nDataLength;   // AllocBuffer will tromp it

  if (nMinBufLength < nOldLen)

   nMinBufLength = nOldLen;

  AllocBuffer(nMinBufLength);

  memcpy(m_pchData, pOldData->data(), (nOldLen+1)*sizeof(TCHAR));

  GetData()->nDataLength = nOldLen;

  CString::Release(pOldData);

 }

 ASSERT(GetData()->nRefs <= 1);

 // return a pointer to the character storage for this string

 ASSERT(m_pchData != NULL);

 return m_pchData;

}

上面的代码已经比较清楚了,当设定的长度小于原字符串长度时,nMinBufLength = nOldLen,然后分配相应的内存,当你设定的长度大于原字符串本身的长度时就要分配一块比较大的空间出来,这时你可以实现字符串对接的操作,请看如下一段代码:

 CString s;

 s = "abc";

 char* p = s.GetBuffer(6);

  int l=s.GetLength();

 memcpy(p+l,"111",3);

 char* c=new char[6];

 memset(c,'1',3);

 char* d="sss";

 strcat(c,d);

 CString e;

 e=(LPCTSTR)c;

 AfxMessageBox(e);

 AfxMessageBox(s);

 s.ReleaseBuffer();  // Surplus memory released, p is now invalid.

 

这段代码主要是考察GetBuffer()函数的动作,在char* p=s.GetBuffer(6),通过debug 可以看到p[6]='',这说明他自动加上了一个结束符,如果你分配空间为5这时将发生指针越界的现象,再次印证了原函数的动作。

 

CString a("hello world");

char* b=a.GetBuffer(0);

strcpy(b,"guanchanghui");

a.ReleaseBuffer();

 

 

标签:CString GetBuffer 

一.函数原型

CString::GetBuffer

LPTSTR GetBuffer( int nMinBufLength );

throw( CMemoryException );

Return Value

An LPTSTR pointer to the object’s (null-terminated) character buffer.

Parameters

nMinBufLength

The minimum size of the character buffer in characters. This value does not include space for a null terminator.

Remarks

Returns a pointer to the internal character buffer for the CString object. The returned LPTSTR is not const and thus allows direct modification of CString contents.

If you use the pointer returned by GetBuffer to change the string contents, you must call ReleaseBuffer before using any other CString member functions.

二.函数作用及使用范围

对一个CString变量,你可以使用的唯一合法转换符是LPCTSTR,直接转换成非常量指针(LPTSTR-[const] char*)是错误的。正确的得到一个指向缓冲区的非常量指针的方法是调用GetBuffer()方法。

GetBuffer()主要作用是将字符串的缓冲区长度锁定,releaseBuffer则是解除锁定,使得CString对象在以后的代码中继续可以实现长度自适应增长的功能。

CString ::GetBuffer有两个重载版本:

LPTSTR GetBuffer( );LPTSTR GetBuffer(int nMinBufferLength);

在第二个版本中,当设定的长度小于原字符串长度时,nMinBufLength = nOldLen,该参数会被忽

略,不分配内存,指向原CString;当设定的长度大于原字符串本身的长度时就要重新分配(reallocate)一块比较大的空间出来。而调用第一个版本时,应如通过传入0来调用第二个版本一样。

是否需要在GetBufer后面调用ReleaseBuffer(),是根据你的后面的程序是否需要继续使用该字符串变量,并且是否动态改变其长度而定的。如果你GetBuffer以后程序自函数就退出,局部变量都不存在了,调用不调用ReleaseBuffer没什么意义了。

最典型的应用就是读取文件:

CFile file;

// FILE_NAME 为实现定义好的文件名称

if(file.Open(FILE_NAME,CFile::modeRead))

{

       CString szContent;

       int nFileLength = file.GetLength();

       file.Read(szContent.GetBuffer(nFileLength),nFileLength);

       szContent.ReleaseBuffer();

       // 取得文件內容放在szContent中,我们之后可以对其操作

}

三.测试

以下就CString::GetBuffer,做简单测试:

测试1:

// example for CString::GetBuffer

 

#include <stdio.h>

#include <afx.h>

 

void main(void)

   

       CString s( "abcd" );

       printf("(1)before GetBuffer:\n");

       printf("CString s.length=%d\n",s.GetLength());

       printf("CString s=%s\n",s);

      

       LPTSTR p = s.GetBuffer( 2 );

      

       printf("(2)after GetBuffer and before ReleaseBuffer:\n");

       printf("LPTSTR p=%s\n",p);    

       printf("p.length=%d\n",strlen(p));

printf("CString s=%s\n",s);      

       printf("CString s.length=%d\n",s.GetLength());

      

 

       s.ReleaseBuffer( );

       printf("(3)after ReleaseBuffer:\n");

       printf("LPTSTR p=%s\n",p);    

       printf("p.length=%d\n",strlen(p));

printf("CString s=%s\n",s);

       printf("CString s.length=%d\n",s.GetLength());    

}

测试结果1:

(1)before GetBuffer:

CString s.length=4

CString s=abcd

(2)after GetBuffer and before ReleaseBuffer:

LPTSTR p=abcd

p.length=4

CString s=abcd

CString s.length=4

(3)after ReleaseBuffer:

LPTSTR p=abcd

p.length=4

CString s=abcd

CString s.length=4

Press any key to continue

测试2:

将LPTSTR p = s.GetBuffer( 2 ); 修改为:LPTSTR p = s.GetBuffer( 10 );

测试结果同1。

测试3:

在测试二的LPTSTR p = s.GetBuffer( 10 );后添加  p[5]='f';

测试结果同1。

测试4:

将测试三的p[5]='f';修改为p[4]='e';

测试结果4:

(1)before GetBuffer:

CString s.length=4

CString s=abcd

(2)after GetBuffer and before ReleaseBuffer:

LPTSTR p=abcde屯屯?

p.length=10

CString s=abcde屯屯?

CString s.length=4

(3)after ReleaseBuffer:

LPTSTR p=abcde屯屯?

p.length=10

CString s=abcde屯屯?

CString s.length=10

Press any key to continue

很显然(2)after GetBuffer and before ReleaseBuffer:中 CString s.length=4结果有问题。

注意:以上测试是在_MBCS环境下,如果换成_UNICODE则结果有可能不同。

参考:

《CString GetBuffer()》

http://blog.csdn.net/hbyh/archive/2007/09/15/1786574.aspx

CString之GetBuffer问题

http://game.tongji.net/thread-379834-1-1.html

《CString的GetBuffer》

http://www.programfan.com/blog/article.asp?id=40755

《CString GetBuffer() and ReleaseBuffer()》

http://blog.csdn.net/guanchanghui/archive/2006/09/13/1217096.aspx

《CString::GetBuffer()与CString::ReleaseBuffer到底有什么用?》

http://topic.csdn.net/t/20060313/22/4612156.html

 

 

 

 

 

GetBuffer()主要作用是将字符串的缓冲区长度锁定,releaseBuffer则是解除锁定,使得CString对象在以后的代码中继续可以实现长度自适应增长的功能。

是否需要在GetBufer后面调用ReleaseBuffer(),是根据你的后面的程序是否需要继续使用该字符串变量,并且是否动态改变其长度而定的。不是什么好地编程习惯,之类的原因。

如果你GetBuffer以后程序自函数就退出,局部变量都不存在了,调用不掉用ReleaseBuffer没什么意义了。

    还有其它作用~比如

   char* temp;

   CString str="hello";

 怎么样让temp指向str呢?~

   temp = str.GetBuffer(0);

  str.releaseBuffer();

呵呵 我们知道csting对象用char是无法直接指向的 now 用getbuffer就更改了啊~ 不过要注意 紧跟后边一定加releaseBuffer(),否者str对象不能动态增长了!

 

 

 

GetBuffer和ReleaseBuffer是一套需要配合使用的函数, 与GetBufferSetLength相比, 优点是如果分配的空间大于实际保存的字符串(0结尾), ReleaseBuffer会把多余申请的空间释放, 归还给系统; 但使用时需要注意以下问题: 如果要保存的字符串为abc(0结尾), 则GetBuffer参数应至少为3; 如果要保存的内容不是以0结尾, 比如是读取文件数据, 则GetBuffer参数如果大于文件长度时, ReleaseBuffer参数一定要为文件长度(如果GetBuffer参数为文件长度的话不存在问题, ReleaseBuffer参数可以为默认-1)!

CString csStr;

LPTSTR lpsz = csStr.GetBuffer(100);

lpsz[0] = 'a';

lpsz[1] = 'b';

lpsz[2] = '\0';

csStr.ReleaseBuffer();

int nLength = csStr.GetLength();

 

 

GetBufferSetLength相对比较容易理解, 它申请一个指定长度的空间, 即使里面最终保存的字符串长小于申请空间长度, 也不会将多余空间释放.

CString csStr

LPTSTR lpsz = csStr.GetBufferSetLength(100);

lpsz[0] = 'a';

lpsz[1] = 'b';

lpsz[2] = '\0';

int nLength = csStr.GetLength();

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值