A
Andrew
I have written two classes : a String Class based on the book " C++ in
21 days " and a GenericIpClass listed below :
file GenericStringClass.h
// Generic String class
class String
{
public:
// constructors
String();
String(const char *const);
String(const String &);
~String();
// overloaded operators
char & operator[](unsigned short offset);
char operator[](unsigned short offset) const;
String operator+(const String&);
void operator+=(const String&);
String & operator= (const String &);
// General Accessors
unsigned short GetLen() const { return itsLen;}
const char * GetString() const { return itsString;}
//private members
private:
String(unsigned short);
// protected members for use in other classes
protected:
char * itsString;
unsigned short itsLen;
};
// default constructor creates a string of zero bytes
String::String()
{
itsString = new char[1];
itsString[0] = '\0';
itsLen=0;
}
// Creates a String object with predefined size "len"
// Null filled .
String::String(unsigned short len)
{
itsString = new char[len+1];
for ( unsigned short i=0; i<=len; i++)
{
itsString='\0';
}
itsLen=len;
}
// Converts an array of characters into a String object
String::String(const char * const charArray)
{
itsLen=strlen(charArray);
itsString= new char[itsLen+1];
for (unsigned short i=0; i<itsLen; i++)
{
itsString=charArray;
}
itsString[itsLen]='\0';
}
// copy constructor
String::String(const String & rhs)
{
itsLen=rhs.GetLen();
itsString = new char[itsLen+1];
for (unsigned short i=0; i<itsLen; i++)
{
itsString=rhs;
}
itsString[itsLen]='\0';
}
// destructor frees allocated memory
String::~String()
{
delete [] itsString;
itsLen=0;
}
// operator equals
String& String:perator=(const String & rhs)
{
if (this == &rhs)
return *this;
delete [] itsString;
itsLen=rhs.GetLen();
itsString=new char[itsLen+1];
for (unsigned short i=0; i<itsLen; i++)
{
itsString=rhs;
}
itsString[itsLen]='\0';
return *this ;
}
// non constant offset operator
// returns reference to a character so it can be changed
char & String:perator[](unsigned short offset)
{
if(offset > itsLen)
{
return itsString[itsLen-1];
}
else
{
return itsString[offset];
}
}
// constant offset operator
char String:perator[](unsigned short offset) const
{
if(offset > itsLen)
{
return itsString[itsLen-1];
}
else
{
return itsString[offset];
}
}
// Creates new string by adding current to rhs
String String:perator+(const String& rhs)
{
unsigned short totalLen = itsLen + rhs.GetLen();
String temp(totalLen);
for( unsigned short i=0; i<itsLen; i++)
{
temp=itsString;
}
for (unsigned short j=0; j<rhs.GetLen(); j++,i++)
{
temp=rhs[j];
printf("This is rhs ....%c \n",(char) rhs[j]);
}
temp[totalLen]='\0';
return temp;
}
// changes current String by adding another istance of the object clas
void String:perator+=(const String &rhs)
{
unsigned short rhsLen = rhs.GetLen();
unsigned short totalLen = itsLen + rhsLen;
String temp(totalLen);
for(unsigned short i=0; i<totalLen ; i++)
{
temp=itsString;
}
for(unsigned short j=0; j<rhs.GetLen(); j++, i++)
{
temp=rhs[i-itsLen];
}
temp[totalLen]='\0';
*this=temp;
}
file GenIpClass.cpp
#include <iostream.h>
#include <stdio.h>
#include <string.h>
#include "GenericStringClass.h"
// General definitions for the GenericIPClass
#ifndef __IP_STATUS_
enum __IP_STATUS_ {__ACTIVE,__INACTIVE};
#endif
#ifndef LOOPBACK
#define LOOPBACK "127.0.0.1"
#endif
#ifndef _HTTP_PREFIX
String _HTTP_PREFIX("http://");
#endif
#define DOT '.'
// GenericIpAddress Class mainly used for checking a given IP for
validity
// so you don't need to open a socket for nothing also used for
forming
// http address for requesting stats such
http://192.20.4.4/features.html
// with a given ip address of 192.20.4.4
class GenericIpAddress : public String
{
public:
// constructors ..
GenericIpAddress(); // for what reason is that used ??
GenericIpAddress(const char* const);
GenericIpAddress(String &);
~GenericIpAddress();
// Accessors
bool isIpValid();
String & GetIpAddress();
private:
String itsIpAddress;
unsigned short ipLength;
protected:
__IP_STATUS_ itsStatus;
};
// This is constructor exists only if
// you have an empty declaration by mistake
GenericIpAddress::GenericIpAddress()
{
// do nothing ...
}
GenericIpAddress::GenericIpAddress(const char * const GivenIp)
{
// Here we used the overloaded = constructor from the String
class
// GivenIp has to be a const char *
itsIpAddress=GivenIp;
}
GenericIpAddress::~GenericIpAddress()
{
// do nothing !!
}
String & GenericIpAddress::GetIpAddress(void)
{
return itsIpAddress;
}
bool GenericIpAddress::isIpValid(void)
{
String tempString=this->GetIpAddress();
cout << "DEBUG " << endl ;
cout << tempString.GetString() << endl;
cout << "DEBUG " << endl ;
unsigned short ip_length = tempString.GetLen();
unsigned short int m;
m=0;
int k[3];
int ip_part;
if((ip_length < 7 ) || (ip_length > 15))
{
cout << "Returning false ..... " << endl;
return false ;
}
for(unsigned short i=0; i<ip_length; i++)
{
if((tempString>'0') && (tempString<'9'))
{
cout << "inside first if statement " <<
tempString << endl;
k[m]=(int)tempString;
m=m+1;
}
if((tempString==DOT))
{
cout << "DEBUGGING .... entering dot if .....
" << endl;
cout << "DEBUGGING .... m is ..... "<< m <<
endl;
/* if((m==0) || (m>3))
{
return false;
} */ // this check goes to
default ??
switch(m)
{
case 1:
{
ip_part=k[0];
m=0;
}
case 2:
{
ip_part=10*k[1]+k[0];
m=0;
}
case 3:
{
ip_part=100*k[2]+10*k[1]+k[2];
m=0;
}
default:
{
cout << "DEBUGGING m=.. " << m
<< " end of DEBUGGING " ;
return false;
}
}
if((ip_part<1) || (ip_part>254))
{
return false;
}
}
else if((tempString!=DOT) || (tempString<'0') ||
(tempString>'9'))
{
cout << "this is tempString ... " <<
tempString << endl;
cout << " DEBUGGING entering the else if
sequence " ;
return false;
}
}
return true;
}
int main(void)
{
GenericIpAddress myIp("127.45.43.132");
if(myIp.isIpValid()==true)
cout << "IP IS ABSOLUTELY VALID "<< endl << endl ;
return 0;
}
The problem is in the isIpValid function . The object myIp has to
create a valid Ip but it doesn't . If you examine the output of the
program you will find out that the function enters both if statements
, not only the if((tempString>'0') && (tempString<'9')) but the
else if((tempString!=DOT) || (tempString<'0') ||
(tempString>'9')) as well which is something strange as i believe
i check every condition . Can you help me ???
(Sorry for my english .... )
21 days " and a GenericIpClass listed below :
file GenericStringClass.h
// Generic String class
class String
{
public:
// constructors
String();
String(const char *const);
String(const String &);
~String();
// overloaded operators
char & operator[](unsigned short offset);
char operator[](unsigned short offset) const;
String operator+(const String&);
void operator+=(const String&);
String & operator= (const String &);
// General Accessors
unsigned short GetLen() const { return itsLen;}
const char * GetString() const { return itsString;}
//private members
private:
String(unsigned short);
// protected members for use in other classes
protected:
char * itsString;
unsigned short itsLen;
};
// default constructor creates a string of zero bytes
String::String()
{
itsString = new char[1];
itsString[0] = '\0';
itsLen=0;
}
// Creates a String object with predefined size "len"
// Null filled .
String::String(unsigned short len)
{
itsString = new char[len+1];
for ( unsigned short i=0; i<=len; i++)
{
itsString='\0';
}
itsLen=len;
}
// Converts an array of characters into a String object
String::String(const char * const charArray)
{
itsLen=strlen(charArray);
itsString= new char[itsLen+1];
for (unsigned short i=0; i<itsLen; i++)
{
itsString=charArray;
}
itsString[itsLen]='\0';
}
// copy constructor
String::String(const String & rhs)
{
itsLen=rhs.GetLen();
itsString = new char[itsLen+1];
for (unsigned short i=0; i<itsLen; i++)
{
itsString=rhs;
}
itsString[itsLen]='\0';
}
// destructor frees allocated memory
String::~String()
{
delete [] itsString;
itsLen=0;
}
// operator equals
String& String:perator=(const String & rhs)
{
if (this == &rhs)
return *this;
delete [] itsString;
itsLen=rhs.GetLen();
itsString=new char[itsLen+1];
for (unsigned short i=0; i<itsLen; i++)
{
itsString=rhs;
}
itsString[itsLen]='\0';
return *this ;
}
// non constant offset operator
// returns reference to a character so it can be changed
char & String:perator[](unsigned short offset)
{
if(offset > itsLen)
{
return itsString[itsLen-1];
}
else
{
return itsString[offset];
}
}
// constant offset operator
char String:perator[](unsigned short offset) const
{
if(offset > itsLen)
{
return itsString[itsLen-1];
}
else
{
return itsString[offset];
}
}
// Creates new string by adding current to rhs
String String:perator+(const String& rhs)
{
unsigned short totalLen = itsLen + rhs.GetLen();
String temp(totalLen);
for( unsigned short i=0; i<itsLen; i++)
{
temp=itsString;
}
for (unsigned short j=0; j<rhs.GetLen(); j++,i++)
{
temp=rhs[j];
printf("This is rhs ....%c \n",(char) rhs[j]);
}
temp[totalLen]='\0';
return temp;
}
// changes current String by adding another istance of the object clas
void String:perator+=(const String &rhs)
{
unsigned short rhsLen = rhs.GetLen();
unsigned short totalLen = itsLen + rhsLen;
String temp(totalLen);
for(unsigned short i=0; i<totalLen ; i++)
{
temp=itsString;
}
for(unsigned short j=0; j<rhs.GetLen(); j++, i++)
{
temp=rhs[i-itsLen];
}
temp[totalLen]='\0';
*this=temp;
}
file GenIpClass.cpp
#include <iostream.h>
#include <stdio.h>
#include <string.h>
#include "GenericStringClass.h"
// General definitions for the GenericIPClass
#ifndef __IP_STATUS_
enum __IP_STATUS_ {__ACTIVE,__INACTIVE};
#endif
#ifndef LOOPBACK
#define LOOPBACK "127.0.0.1"
#endif
#ifndef _HTTP_PREFIX
String _HTTP_PREFIX("http://");
#endif
#define DOT '.'
// GenericIpAddress Class mainly used for checking a given IP for
validity
// so you don't need to open a socket for nothing also used for
forming
// http address for requesting stats such
http://192.20.4.4/features.html
// with a given ip address of 192.20.4.4
class GenericIpAddress : public String
{
public:
// constructors ..
GenericIpAddress(); // for what reason is that used ??
GenericIpAddress(const char* const);
GenericIpAddress(String &);
~GenericIpAddress();
// Accessors
bool isIpValid();
String & GetIpAddress();
private:
String itsIpAddress;
unsigned short ipLength;
protected:
__IP_STATUS_ itsStatus;
};
// This is constructor exists only if
// you have an empty declaration by mistake
GenericIpAddress::GenericIpAddress()
{
// do nothing ...
}
GenericIpAddress::GenericIpAddress(const char * const GivenIp)
{
// Here we used the overloaded = constructor from the String
class
// GivenIp has to be a const char *
itsIpAddress=GivenIp;
}
GenericIpAddress::~GenericIpAddress()
{
// do nothing !!
}
String & GenericIpAddress::GetIpAddress(void)
{
return itsIpAddress;
}
bool GenericIpAddress::isIpValid(void)
{
String tempString=this->GetIpAddress();
cout << "DEBUG " << endl ;
cout << tempString.GetString() << endl;
cout << "DEBUG " << endl ;
unsigned short ip_length = tempString.GetLen();
unsigned short int m;
m=0;
int k[3];
int ip_part;
if((ip_length < 7 ) || (ip_length > 15))
{
cout << "Returning false ..... " << endl;
return false ;
}
for(unsigned short i=0; i<ip_length; i++)
{
if((tempString>'0') && (tempString<'9'))
{
cout << "inside first if statement " <<
tempString << endl;
k[m]=(int)tempString;
m=m+1;
}
if((tempString==DOT))
{
cout << "DEBUGGING .... entering dot if .....
" << endl;
cout << "DEBUGGING .... m is ..... "<< m <<
endl;
/* if((m==0) || (m>3))
{
return false;
} */ // this check goes to
default ??
switch(m)
{
case 1:
{
ip_part=k[0];
m=0;
}
case 2:
{
ip_part=10*k[1]+k[0];
m=0;
}
case 3:
{
ip_part=100*k[2]+10*k[1]+k[2];
m=0;
}
default:
{
cout << "DEBUGGING m=.. " << m
<< " end of DEBUGGING " ;
return false;
}
}
if((ip_part<1) || (ip_part>254))
{
return false;
}
}
else if((tempString!=DOT) || (tempString<'0') ||
(tempString>'9'))
{
cout << "this is tempString ... " <<
tempString << endl;
cout << " DEBUGGING entering the else if
sequence " ;
return false;
}
}
return true;
}
int main(void)
{
GenericIpAddress myIp("127.45.43.132");
if(myIp.isIpValid()==true)
cout << "IP IS ABSOLUTELY VALID "<< endl << endl ;
return 0;
}
The problem is in the isIpValid function . The object myIp has to
create a valid Ip but it doesn't . If you examine the output of the
program you will find out that the function enters both if statements
, not only the if((tempString>'0') && (tempString<'9')) but the
else if((tempString!=DOT) || (tempString<'0') ||
(tempString>'9')) as well which is something strange as i believe
i check every condition . Can you help me ???
(Sorry for my english .... )