/* These files (spstring.h, spstring.cpp) contain the class String, which is a simple implementation of strings, mostly a wrapping of type functions in a C++ class. The purpose for making these classes is portability. The library libg++ that comes with gcc has a very good String, as does Borland C++. But they're not the same. In addition, I needed strings on Solaris and couldn't find any. ,mostly due to the fact that the server was never set up to provide me with documentation --- there probably are strings there somewhere. I hope these will work in every setting. If there's going to be lots of strings made and destroyed, it'd be worth being more careful about memory allocation. I included a allocated_size in each string and only delete and reallocate the block of characters if it needs to be larger. Otherwise it is reused. Depending on the nature of "new" it might be better to round all the allocations to standard sizes --- powers of 2 +1, say --- so that old blocks can all be reused. */ #include #include "spstring.h" StringTokenizer::StringTokenizer(const String& Source) : String(Source) { CurrentStart= s; Buffer = new char[sz]; assert(Buffer !=0); Buffer[0]='\0'; } StringTokenizer::StringTokenizer(int size) : String(size) { CurrentStart= s; Buffer = new char[sz]; assert(Buffer!=0); Buffer[0]='\0'; } StringTokenizer::StringTokenizer() : String() { CurrentStart= s; Buffer = new char[sz]; assert(Buffer!=0); Buffer[0]='\0'; } StringTokenizer::~StringTokenizer() { delete [] s; delete [] Buffer; s=0; Buffer=0; } int StringTokenizer::Empty(){ if(*CurrentStart=='\0') return 1; return 0;} void StringTokenizer::ReSet(const String& S) { if(sz >= S.sz) { strcpy(s,S.s); len=strlen(s); } else { delete [] s; delete [] Buffer; sz= strlen(S.s)+1; s=new char[sz]; assert(s!=0); strcpy(s,S.s); len=strlen(s); Buffer = new char[sz]; assert(Buffer!=0); } CurrentStart=s; Buffer[0]='\0'; } String StringTokenizer::Next(const String &S) { if(*CurrentStart == '\0') { String Ans(0); return Ans; } char *ptr =CurrentStart,*ptr2; ptr2=Buffer; *ptr2='\0'; while( !(S.BelongsTo(*ptr)) && *ptr != '\0') ptr++; while(CurrentStart < ptr) *(ptr2++) = *(CurrentStart++); *ptr2 = '\0'; if(*ptr != '\0') CurrentStart++; String Ans(Buffer); return Ans; } String StringTokenizer::Next(char *t) { String S=t; if(*CurrentStart == '\0') { String Ans(0); return Ans; } char *ptr =CurrentStart,*ptr2; ptr2=Buffer; *ptr2='\0'; while( !(S.BelongsTo(*ptr)) && *ptr != '\0') ptr++; while(CurrentStart < ptr) *(ptr2++) = *(CurrentStart++); *ptr2 = '\0'; if(*ptr != '\0') CurrentStart++; String Ans(Buffer); return Ans; } //Create a String under various conditions String::String() { s= new char [DEFAULT_ALLOC+1]; assert(s!=0); s[0]='\0'; sz=DEFAULT_ALLOC+1; len=0; } String::String(int n) { s= new char [n+1]; assert(s!=0); s[0]='\0'; sz=n+1; len=0; } String::String(char *t) { len=strlen(t); sz=len+1; s= new char [sz]; assert(s!=0); strcpy(s,t); } String::String(int n, char c) { sz=n+1; s=new char[sz]; assert(s!=0); len=n; for(int i=0;i= S.len+1)//enough space already allocated { strcpy(s,S.s); len=S.len; } else { len=S.len; delete []s; if(S.s==0) { s=0; len=0; sz=0; } else { sz=len+1; s= new char[sz]; assert(s !=0); strcpy(s,S.s); } } } return *this; } String& String::operator=(const char * S) { if(s != S) { if(sz >= strlen(S)+1)//enough space already allocated { strcpy(s,S); len=strlen(S); } else { len=strlen(s); delete []s; if(S==0) { s=0; len=0; sz=0; } else { sz=len+1; s= new char[sz]; assert(s !=0); strcpy(s,S); } } } return *this; } char & String::operator[](unsigned i) { if( i < len) return s[i]; cerr << "Error in String: index out of bound." << i << ", "<>(istream& InStream,String&S) { char Buffer[String::MaxLength]; InStream>>Buffer; S.len=strlen(Buffer); delete []S.s; S.s=new char[S.len+1]; S.sz=S.len+1; assert(S.s !=0); strcpy(S.s,Buffer); return InStream; } ostream& operator <<(ostream& OutStream,const String& S) { OutStream << S.s; return OutStream; } istream& String::ReadLine(istream& In,char Until) { char Buffer[String::MaxLength+1]; In.getline(Buffer,String::MaxLength,Until); len=strlen(Buffer); if( sz >= len+1) { strcpy(s,Buffer); } else { sz=len+1; delete [] s; s = new char[sz]; assert(s !=0); strcpy(s,Buffer); } return In; } /** This function plays the role of fgets() in that it reads from a file until EOF or endline ('\n') is reached. It is different from fgets() in that it strips any '\r' and '\n' that appear at the end of the line. */ void String::ReadLine(FILE *fp) { char Buffer[String::MaxLength]; int c,n=String::MaxLength; char *cp; cp=Buffer; while(--n >0 && (c=getc(fp)) !=EOF) if((*cp++=c)=='\n') break; //that is: while(...){ *cp=c; cp++; if(c=='\n') break;} *cp='\0'; //if c==EOF and cs=Buffer we read nothing c=strlen(Buffer)-1; while(c >= 0 && Buffer[c]== '\n' || Buffer[c]=='\r') Buffer[c--]='\0'; len=strlen(Buffer); if(sz >= len+1)// enough space already allocated { strcpy(s,Buffer); } else { delete [] s; sz=len+1; s=new char[sz] ; assert(s!=0); strcpy(s,Buffer); } } /** String::Print() is really only useful for debugging purposes*/ void String::Print() { cout << "String: len = " << len << " sz = " << sz << " *s = " << s << endl; } int String::Length() const { return len; } char * String::chars() { return s; } int String::Delete(unsigned Start, unsigned End) { if( Start > End || End+1 > len) { cerr << "Error in String::Delete(). Start = " << Start << " End = " << End << endl; cerr << *this; return 0; } End++; while(s[End] != '\0') s[Start++] = s[End++]; s[Start]='\0'; len=strlen(s); return 1; } int String::Insert(const String& S,unsigned Start) { int i; if(Start >len) { cerr << "Error in String::Insert(). Index out of bounds\n"; cerr << Start << endl; cerr << *this; cerr << "Inserting " << S << endl; return -1; } //size of resulting char string is len + S.len char *temp = new char[len+S.len+1]; assert(temp !=0); for(i=0;i End || End > len) { cerr << "Error in String::Replace(). Start = " << Start << " End = " << End << endl; cerr << *this; cerr << "Inserting " << S << endl; return -1; } Delete(Start,End); Insert(S,Start); return 0; } void String::Replace(const String& Target,const String& Source) { int Start=Locate(Target); if(Start==-1) return; // Target isn't a substring int End=Start + Target.len-1; Replace(Source,Start,End); } void String::Replace(char * T,char * S) { String Source,Target; Source=S; Target=T; int Start=Locate(Target); if(Start==-1) return; // Target isn't a substring int End=Start + Target.len-1; Replace(Source,Start,End); } void String::Replace(char * T,const String& Source) { String Target; Target=T; int Start=Locate(Target); if(Start==-1) return; // Target isn't a substring int End=Start + Target.len-1; Replace(Source,Start,End); } void String::Replace(const String& Target,char * S) { String Source; Source=S; int Start=Locate(Target); if(Start==-1) return; // Target isn't a substring int End=Start + Target.len-1; Replace(Source,Start,End); } int String::Locate(const String& S) const { for(int i=0;i(const String& S, const String& T) { if(S.s==T.s) return 0; else if (S.s==0) return 0; else if (T.s==0) return 1; else return(strcmp(S.s,T.s)>0); } operator>(const String& S, char * T) { if(S.s==T) return 0; else if(T==0) return 1; else if(S.s==0) return 0; else return (strcmp(S.s,T)>0); } operator>(char * T, const String& S) { if(S.s==T) return 0; else if(T==0) return 0; else if(S.s==0) return 1; else return ( strcmp(T,S.s) > 0); } operator>=(const String& S, const String& T){return !(S=(const String& S, char * T){return !(S=(char * T, const String& S){return !(ST);} operator<=(const String& S, char * T){return !(S >T);} operator<=(char * T, const String& S){return !(S >T);} void String::UpperCase() { for(int i=0;i0) { x.Print(); cout << x << endl; x.ReadLine(fin); } cout << "THE END" << endl; fclose(fin); return 1; } */