String class : inherited from basic_string

Updated mrnutty 2 Tallied Votes 3K Views Share

Some background.

We all used the string class, but some of you might not know that
string is just a typedef of basic_string.
In fact here is the typedef you might find when looking in the XString library.

typedef basic_string<char, char_traits<char>, allocator<char> >   string;

This code snippet shows you how to use basic_string to your
advantage. It has almost the same functionality as the string library
but it adds some functionality. It has little error checking. Again this
is shown as an example to learn from. Here is a list of things to
keep in mind :

- template class
- inheritance
- pointer function
- const correctness
- template functions
- scoped namespace
- assert function
- use of typedef

#include <cassert>
#include <sstream>
#include <cctype>
#include <cmath>
#include <algorithm>
#include <iostream>

//Extends std::basic_string and adds more functionality
class String : public std::basic_string<char>
{
public:
	typedef std::basic_string<char> string_type;
public:	
	String() : string_type() {}
	String(const char * str) : string_type(str){}
	String(const char * str, size_t n) : string_type(str,n) {}
	String(size_t n , char c ) : string_type(n,c) {}
public:
	//added functionalities
	String  toUpper()const      { return _apply(std::toupper);  }
	String  toLower()const      { return _apply(std::tolower);  }
	
	bool    isDigits()const     { return _isAllDigits();	}
	bool    isLower()const      { return _checkIf(std::islower);}
	bool    isUpper()const      { return _checkIf(std::isupper);}
	bool    isAlpha()const      { return _checkIf(std::isalpha);}

	int     toInt()	const       { return _convertTo<int>(*this);}		
	long    toLong()const       { return _convertTo<long>(*this);}	
	float   toFloat()const      { return _convertTo<float>(*this);}
	double  toDouble()const     { return _convertTo<double>(*this);}		
	size_t  toSizeT()const      { return _convertTo<size_t>(*this);}

	void    reset()             { *this = String();	}

	bool    startsWith(const String& preFix)const {
				return substr(0,preFix.size()) == preFix; 
			}
	bool    endsWith(const String& suffix)const	{
				return substr(size()-suffix.size()) == suffix; 
			}
	
	void    shuffleIt() {
				std::random_shuffle( begin(), end()); 
			}
	
	String  shuffled()const{
				String tmp = *this;
				tmp.shuffleIt();
				return tmp; 
			}
	//conversion function
	operator const char*(){
		return c_str();
	}
private:
	//helpers
	typedef int(*ApplyFunc)(int); 	
	//converts a string to a valid data type
	template<typename ReturnType>
	ReturnType _convertTo(const String& str)const{			
		_assertValidSize();
		std::stringstream convert;
		convert << str ;
		ReturnType data;
		assert(!(convert >> data).fail() ); //make sure conversion was succesful
		return data;
	}

	//takes in a function and returns a string with that function applied to the whole string
	String _apply(const ApplyFunc& Applier )const{
		_assertValidSize();
		String str;
		std::transform( begin(),end(), //from start to end
						std::back_insert_iterator<string_type>(str), //adjust str size
						Applier); //while applying a function to it
		return str;
	}	

	//takes in a function and checks if it passes the function checking
	bool _checkIf(const ApplyFunc& Applier)const{
		for(size_t indx = 0; indx != size(); ++indx){			
			if(!Applier((*this)[indx]) )return false;
		}
		return true;
	}
	//A valid digit is 0-9, with the expection of '.' for floating point, and '-' for negative digits
	//A valid here cannot end with any post-fix, ex : 3.14f or 124L is invalid!
	bool _isAllDigits()const{
		size_t start = 0;
		if((*this)[0] == '-' ) 
			start = 1;
		for(; start < size(); ++start){
			char value = (*this)[start];
			if(!isdigit( value ) && value != '.' )
				return false;
		}
		return true;
	}
	void _assertValidSize()const{
		assert(size());
	}	
};
int main ()
{	

	using namespace std;

	String str("StRinG");		
	
	cout << str.toUpper().shuffled() << endl;


	return 0;
}
mrnutty 761 Senior Poster

Whats up with the edit function ? I can't edit my own code ?

Anyways the private bool _checkIfIsDigit()const should be :

bool _checkIfIsDigit()const{
		size_t indx = 0;
		if( (*this)[0] == '-') indx = 1; //check for negative
		for(; indx != size(); ++indx){				
			if(!isdigit((*this)[indx]) && (*this)[indx] != '.') return false;
		}
		return true;
	}
CppBuilder2006 -5 Junior Poster

I think it needs a help file. for example what is Cosine() doing in a string class?! how do u use it?!

mrnutty 761 Senior Poster

Yea, its not ideal and does not belong there. I tried to show how to
use some of the material in C++. Usually, one can use Cosine, if the String
is a number. For example.

String str("3.14");
cout <<  str.Cosine();
Nick Evan 4,005 Industrious Poster Team Colleague Featured Poster

>> Whats up with the edit function ? I can't edit my own code ?
>> Anyways the private bool _checkIfIsDigit()const should be :

done

Dave Sinkula 2,398 long time no c Team Colleague

Whats up with the edit function ? I can't edit my own code ?

Ah, yes. I too miss the old days when the snippets section was first begun. There was unlimited editing time for the author, which I would still find useful today. And the formatting in this section was more readable as well (moving to this new format actually brutalized a couple of snippets of mine). Oh well, enjoy what current features are here before they too disappear. :)

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.