C++下操作字符串的超级容易类~~~~~
作者:中国论坛网收集 来源:http://www.51one.net 加入时间:2004-8-25
日记:
今天我做了一个类。类的名字叫JString。是用来对字符串进行常规的操作的。
这个类的特点是,几乎所有的JString都用JString&的形式引用。
来源于托管内存管理式的思想,做到变量能自由创建和释放。
创建出来的所有对象会自动释放。所以一行内要多长就可以写多长。~~
以后不需要手工分配buffer了。。~~~~
我的水平不高。希望高手指正。
下载的地方是:
http://www.lostinet.com/public/cplusplus/jstring/
http://www.lostinet.com/public/cplusplus/jstring/jstring.cpp.txt
http://www.lostinet.com/public/cplusplus/jstring/jstring.zip
相关CSDN论坛文章:
http://www.csdn.net/expert/topic/984/984638.xml?temp=.7542993
// TestLib.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
/**************************************************************** 链式委托内存管理的字符串类JString
栈头堆尾?
作者:Lostinet[迷失网络]。。(记得记住我啊。。)
\****************************************************************/
#ifndef _Lostinet_class_JString_
#define _Lostinet_class_JString_
/*
因为我是JScript的爱好者,并且很依赖JScript中的String类型
所以这个命名为JString了
工作原理:
在函数内定义一个由Stack分配的JString对象。
那么在函数返回的时候,JString对象就会释放。
JString对象对其所有操作所产生的对象,用一条链连起来。
那么当Stack生成的的JString对象释放时,
也自动释放其相关的所有JString了。
所以在类外部使用JString*指针是错误的用法
而且一条链中的对象最好不要传递到其他函数中。
通常的方法是在一个函数里定义第一个
JString js;
然后其它变量使用JString&类型
不建议在调用函数时传递JString*,和JString&
忠告:
在外面使用JString* 类型是不合法的。
千万要注意链的生存期,
特别是不同一条链的JString&+JString&时,返回的JString&属于第一条链
*/
#include <stdlib.h>
#include <string.h>
class JString
{
protected:
JString* pAllocator;
JString* pNext;
//只有链头才用pLast
JString* pLast;
char* pString;
int length;
JString(JString& pA,unsigned int initLen=0,const char* initStr="")
{
pAllocator=&pA;
if(pA.pLast)pA.pLast->pNext=this;
pA.pLast=this;
pNext=pLast=0;
length=initLen;
pString=new char[initLen+1];
strcpy(pString,initStr);
}
public:
JString(const char* str)
{
pAllocator=this;
pNext=pLast=0;
length=strlen(str);
pString=new char[length+1];
strcpy(pString,str);
}
JString()
{
pAllocator=this;
pNext=pLast=0;
pString=new char[1];
pString[0]=0;
length=0;
}
virtual ~JString()
{
delete pString;
if(pNext)delete pNext;
}
char* Detach()
{
char* str=pString;
pString=new char[1];
pString[0]=0;
length=0;
return str;
}
char* GetBuffer()
{
return pString;
}
char* GetBufferSetLength(int len)
{
//assert(len>=0);
delete pString;
length=len;
pString=new char[len+1];
return pString;
}
/****************************************************************/
int GetLength()
{
return length;
}
int IndexOf(const char * str,int start=0)
{
if(start+1>length)return -1;
char* pStart=pString+start;
char* pos=strstr(pStart,str);
if(pos==0)return -1;
return pos-pString;
}
int LastIndexOf(const char * str)
{
int len=strlen(str);
char *buf1=new char[length+1];
char *buf2=new char[len+1];
strcpy(buf1,pString);
strcpy(buf2,str);
strrev(buf1);
strrev(buf2);
char* pos=strstr(buf1,buf2);
delete buf1;
delete buf2;
if(pos==0)return -1;
return length+buf1-pos-len;
}
JString& Left(int len)
{
return Substr(0,len);
}
JString& Right(int len)
{
return Substr(length-len,len);
}
JString& Substr(int start,int len)
{
if(start<0)start=0;
if(start+1>length)
return * new JString(*pAllocator);
if(len<=0)
return * new JString(*pAllocator);
if(start+len>length)
len=length-start;
char* buf=new char[len+1];
memcpy(buf,pString+start,len);
buf[len]=0;
JString* pStr=new JString(*pAllocator,len,buf);
delete buf;
return * pStr;
}
JString& Lower()
{
JString* pStr=new JString(*pAllocator);
strcpy(pStr->GetBufferSetLength(length),pString);
strlwr(pStr->GetBuffer());
return * pStr;
}
JString& Upper()
{
JString* pStr=new JString(*pAllocator);
strcpy(pStr->GetBufferSetLength(length),pString);
strupr(pStr->GetBuffer());
return * pStr;
}
/****************************************************************/
double Number()
{
return strtod(pString,0);
}
JString& Convert(bool b)
{
return * new JString(*pAllocator,b?4:5,b?"true":"false");
}
JString& Convert(double d)
{
char buf[64];
sprintf(buf,"%g",d);
return * new JString(*pAllocator,strlen(buf),buf);
}
JString& Convert(int n)
{
char buf[64];
sprintf(buf,"%d",n);
return * new JString(*pAllocator,strlen(buf),buf);
}
JString& Convert(const char* str)
{
return * new JString(*pAllocator,strlen(str),str);
}
/****************************************************************/
//所有的char*输入,地址都必须不为0
JString& operator + (JString& Str)
{
//if(Str.pAllocator!=pAllocator)throw("JString& operator + (JString& Str) 不能使用不同一条链的对象");
//注意:两条链的元素相加,返回的元素属于第一条链
JString* pRes=new JString(*pAllocator,length+Str.length,pString);
strcat(pRes->pString,Str.pString);
return *pRes;
}
JString& operator + (const char* str)
{
JString* pRes=new JString(*pAllocator,length+strlen(str),pString);
strcat(pRes->pString,str);
return *pRes;
}
JString& operator + (bool b)
{
JString* pStr=new JString(*pAllocator,length+(b?4:5),pString);
strcat(pStr->pString,(b?"true":"false"));
return *pStr;
}
JString& operator + (double d)
{
char buf[64];
sprintf(buf,"%g",d);
return *this+buf;
}
JString& operator + (int n)
{
char buf[64];
sprintf(buf,"%d",n);
return *this+buf;
}
JString& operator += (bool b)
{
*this+=b?"true":"false";
return *this;
}
JString& operator += (double d)
{
char buf[64];
sprintf(buf,"%g",d);
*this+=buf;
return *this;
}
JString& operator += (int n)
{
char buf[64];
sprintf(buf,"%d",n);
*this+=buf;
return *this;
}
JString& operator += (const char *str)
{
length=length+strlen(str);
char* pStr=new char[length+1];
strcpy(pStr,pString);
strcat(pStr,str);
delete pString;
pString=pStr;
return *this;
}
JString& operator = (bool b)
{
if(b)
*this="true";
else
*this="false";
return *this;
}
JString& operator = (double d)
{
char buf[64];
sprintf(buf,"%g",d);
*this=buf;
return *this;
}
JString& operator = (int n)
{
char buf[64];
sprintf(buf,"%d",n);
*this=buf;
return *this;
}
JString& operator = (JString& Str)
{
delete pString;
length=Str.length;
pString=new char[length+1];
strcpy(pString,Str.pString);
return *this;
}
JString& operator = (const char* str)
{
delete pString;
length=strlen(str);
pString=new char[length+1];
strcpy(pString,str);
return *this;
}
/****************************************************************/
bool CompareNoCase(const char* str)
{
return strcmpi(pString,str)==0;
}
bool operator == (const char* str)
{
return strcmp(pString,str)==0;
}
bool operator == (int n)
{
char buf[64];
sprintf(buf,"%d",n);
return *this==buf;
}
bool operator == (double d)
{
char buf[64];
sprintf(buf,"%g",d);
return *this==buf;
}
/****************************************************************/
operator bool ()
{
return length>0?true:false;
}
operator const char* ()
{
return pString;
}
};
template <class T>
JString& operator + (T t,JString& js)
{
return js.Convert(t)+js;
}
template <class T>
JString& operator == (T t,JString& js)
{
return js==t;
}
#endif //_Lostinet_class_JString_
#include "iostream.h"
int main(int argc, char* argv[])
{
//假如在某个地方得到szURL
// const char* szURL="http://www.lostinet.com/some.asp";
// const char* szURL="http://www.lostinet.com/some.asp?id=35&style=1";
const char* szURL="http://www.lostinet.com/some.asp?id=35&page=3&style=1&page=5";
//现在目标是解析那段字符串,把page=3中的3取出来,默认为1
//如果是一般的操作,那么需要很长的代码
//注意,这个过程没有显式地分配buffer
//除去注释,不计较szURL,那么一共定义了四个变量
//其中字符先相关的是 JString jsURL 和 JString& jsParams
//代码共22行(包括3个{和3个})
int page=1;
JString jsURL(szURL);
//搜索URL中?号的地方。如果没有问号,代表没有参数
int pos=jsURL.IndexOf("?");
if(pos>-1)//IndexOf返回-1代表搜索不到"?",没有参数
{
//JString& jsParams= 是取得新的JString对象的引用
//pos+1是为了Substr得到的不包括pos所在的"?"
//jsURL.GetLength()是jsURL的长度,Substr自动识别长度。取到字符串最后
//Lower()得到小写,非正规写法是strlwr(jsParams.GetBuffer());
JString& jsParams=jsURL.Substr(pos+1,jsURL.GetLength()).Lower();
//重载了 (bool) 操作符,意思是while(jsParams.GetLength()>1)
while(jsParams)
{
//开始寻找"page="的下落
pos=jsParams.IndexOf("page=");
//找不到"page="当然退出了
if(pos==-1)
break;
//0是因为jsParams第一项就是page=....
//不是0的情况应该继续
if(pos==0)
{
//去掉"page="然后得到后面的数字
// JString("3&style=1&page=5") 的.Number() 是 3
page=jsParams.Substr(5,jsParams.GetLength()).Number();
break;//不break的话,就会继续搜索。在例子中,取得page=5
}
//找URL参数分割符
pos=jsParams.IndexOf("&");
//如果没有分割符了,代表这次的jsParams是最后一个了。
if(pos==-1)
break;
//"id=35&page=3&style=1&page=5"=>"page=3&style=1&page=5"
//如此类推
jsParams=jsParams.Substr(pos+1,jsParams.GetLength());
}
}
cout<<page;
//性能参考:
//例子代码运行后,JString对象一共分配4个,每个占20BYTE的内存。jsURL是第一个
//过程是:
//1 JString() : JString jsURL(szURL);
//2 Substr() : JString& jsParams=jsURL.Substr(pos+1,jsURL.GetLength()).Lower();
//3 Lower() : 同上
//4 Substr() : jsParams=jsParams.Substr(pos+1,jsParams.GetLength());
//5 Substr() : page=jsParams.Substr(5,jsParams.GetLength()).Number();
//
//如果把 break;//不break的话,就会继续搜索。在例子中,取得page=5
//去掉,那么JString对象一共分配8个。
//因为多了两次的jsParams=jsParams.Substr(pos+1,jsParams.GetLength());
//
//JString必须等其链头所在的函数退出,整条链才会释放。
//如果一个函数长期不退出,不断地计算字符串,
//那么要确定操作数量不多(10000次的+操作也不算多,100000次就很多了),
//那才考虑使用JString
//
cout<<"\n\n\n\n";
return 0;
}
-----------------------------------------------------------
例子去掉注释后:
#include "iostream.h"
int main(int argc, char* argv[])
{
const char* szURL="http://www.lostinet.com/some.asp?id=35&page=3&style=1&page=5";
int page=1;
JString jsURL(szURL);
int pos=jsURL.IndexOf("?");
if(pos>-1)
{
JString& jsParams=jsURL.Substr(pos+1,jsURL.GetLength()).Lower();
while(jsParams)
{
pos=jsParams.IndexOf("page=");
if(pos==-1)
break;
if(pos==0)
{
page=jsParams.Substr(5,jsParams.GetLength()).Number();
break;
}
pos=jsParams.IndexOf("&");
if(pos==-1)
break;
jsParams=jsParams.Substr(pos+1,jsParams.GetLength());
}
}
cout<<page;
cout<<"\n\n\n\n";
return 0;
}