Click here to Skip to main content
15,891,567 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
C++
#include< iostream > 
#include< string >
#include< cstring >
using namespace std;
class string1
{
  char *name;
  int length;

public:
  string1 ()
  {
    length = 0;
    name = new char[length + 1];
  }
 
  string1 (char const *s)
  {
    length = strlen (s);
    name = new char[length + 1];
    strcpy (name, s);
  }

  void display (void)
  {
    cout << name << endl;
  }

  ~string1();
  int join (const string1 &a, const string1 &b);
};

int string1::join (const string1 &a, const string2 &b)
{
  string1 c;
  c.length = a.length + b.length;
  delete name;
  c.name = new char[c.length + 1];
  strcpy (c.name, a.name);
  strcat (c.name, b.name);
  return c;
}

string1 :: ~string1()
{
  delete name ;
}

int main ()
{
  char const *str1 = "myname ";
  string1 name1 (str1);
  string1 name2 ("anupam ");
  string1 name3 ("sinha ");
  string1 s1;
  string1 s2;
  s1.join (name1, name2);
  s2.join (s1, name3);
  name1.display ();
  name2.display ();
  name3.display ();
  s1.display ();
  s2.display ();
}
Posted
Updated 4-Dec-13 10:15am
v3

I think you are referring to the function:
C++
int string1::join (const string1 &a, const string2 &b)
{
  string1 c;
  c.length = a.length + b.length;
  delete name;
  c.name = new char[c.length + 1];
  strcpy (c.name, a.name);
  strcat (c.name, b.name);
  return c;
}

which is no copy constructor, but a simple member function. It is the only function containing the "return c" statement, so you must be referring to that.

The most obvious reason why this can't work is that the join function returns an int, but your variable c is a string1. So let's assume for a moment that you meant to write:
C++
string1 string1::join (const string1 &a, const string2 &b)

In that case the join function should not alter the object it is called for, but simply concattenate a and b and return the result. Then you should actually declare join as a static function, as it does not need a class object.
C++
class string1
{
  ...
  static string1 join (const string1& a, const string2& b);
  ...

You should also correct the delete statement, which should read:
C++
delete [] c.name;


The other alternative is to assign the concattenation of a and b to the string, which you call join on. The test code in your main function actually shows that this was your intention. Then the join function does not need a string1 c at all and should read:
C++
void string1::join (const string1 &a, const string2 &b)
{
  length = a.length + b.length;
  delete [] name;
  name = new char[c.length + 1];
  strcpy (name, a.name);
  strcat (name, b.name);
}


Besides, the naming of variable name is not very clever, as a string may contain not only names, but all kind of things. Buffer would probably a better name for it.

And the rest of your code contains another bug: The default constructor does not initialize the allocated buffer of 1 byte.

Hope that helps you out.
 
Share this answer
 
v2
Comments
Philippe Mori 4-Dec-13 18:18pm    
By the way, it should be delete[] name; that is with square brackets.
nv3 5-Dec-13 2:14am    
Ohhh yes! Thanks Philippe!
Philippe Mori 4-Dec-13 18:24pm    
Also join function code should be put Inside a private constructor to avoid the useless initial allocation, simplify the code somehow and make it a bit more robust...
kumar_11 5-Dec-13 1:31am    
I am so sorry for my wrong words as I write constructor in place of function and yes, thanks a lot for the solution.I will try the whole concept and will let you know if anything left.
In addition to what nv3 said, whenever you're doing any low level resource management task like this (you're essentially managing a variable sized array of characters) make sure you take exception safety into account.

Looking at nv's modifications:

C++
void string1::join (const string1 &a, const string2 &b)
{
  length = a.length + b.length;
  delete [] name;
  name = new char[c.length + 1];
  strcpy (name, a.name);
  strcat (name, b.name);
}


ask yourself what happens to the object you've called the function on if the new throws? The answer is you'll end up with the object having a screwy state - the length suggests that there's a valid string but it's got a pointer to some deleted memory. Ugh. Makes recovery impossible and you have to bin the object.

How to get around this is hinted in SA's answer: Write a constructor. A handy guideline is do all news in a constructor and all deletes in the destructor. You won't be able to manage it all the time but it's a handy rule to keep in mind when you code.

Why? If constructors fail then the object never exists and the rest of the program state can stay the same. That makes it far easier to recover or report errors - you haven't scrambled anything apart from the object you were constructing.

So how could you implement join using a constructor? Well first off write a two argument constructor:

C++
string1( const string1 &a, const string1 &b )
{
	length_ = a.length + b.length;
	data_ = new char[ length + 1 ];
	std::copy( a.name, a.name + a.length,  name            );
	std::copy( b.name, b.name + b.length_, name + a.length );
	name[ length ] = 0;
}


Then define a swap function:

C++
void swap( string1 &swap_with )
{
	std::swap( length, swap_with.length );
	std::swap( name,   swap_with.name   );
}


and your join becomes:

C++
void join( const string1 &a, const string1 &b )
{
	string1 temp( a, b );
	swap( temp );
}


If the constructor goes horribly wrong your original object is still intact and in a usable state, hurrah!

This copy and swap is useful in other places as well - e.g. when you're writing assignment operators - so getting it fixed in your mind isn't a waste of time for any C++ programmer.

PS: In reply to comment...

Your ambition for join seems to be += in most string implementations. You can do it with the two argument constructor and swap:

C++
void join( const string1 &to_append )
{
	string1 temp( *this, to_append );
	swap( temp );
}


Scarily similar isn't it?

Basically sort out the constructors, a destructor and non-throwing swap and most copying operations become a doddle - and exception safe as well.
 
Share this answer
 
v2
Comments
Philippe Mori 5-Dec-13 8:28am    
Well, I would prefer a static join function that returns a new object or a member append function that would take one argument and append it to the end of the current string. Otherwise, it is really good.
[no name] 5-Dec-13 8:48am    
"append function that would take one argument and append it to the end of the current string". I agree - that is a standard concatenation that could be implemented by overloading the addition operator.
This is because constructor code don't return anything, it does not have return type; this is designed so on purpose, to avoid such situations.

While constructing, you always work with the implicit parameter "this" (which you can use explicitly and sometime had to do so, to avoid naming conflicts), exactly as it is done with non-constructor instance functions. This parameter represents the pointer to the object being constructed. The purpose of construction is to modify the object accessed by this pointer in some required way. The call to a constructor returns the object and assigns the result to l-value, or, if the operator new is used in the constructor call, "this" pointer itself is returned; in this case, the object is allocated on heap, and allocation itself can be customized, which is a whole different story.

—SA
 
Share this answer
 
Comments
kumar_11 4-Dec-13 15:01pm    
thanks for the answer. Is it doable through friend function ?
Sergey Alexandrovich Kryukov 4-Dec-13 15:33pm    
Doable what, and why? What's the problem with writing a constructor, to start with?
—SA

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900