tags:

views:

132

answers:

6

I have a very simple class named person which is given below , I have a problem with only two functions , i.e setstring () function and setname() function , I am calling setstring() function from the setname function. The only problem is when in the main function I write
Object.setname(“Zia”);
The result is ok as shown in the output screen, Now when I write
Object.setname(“Zia ur Rahman”);
Nothing is displayed as you can see the output screen.

I know the problem is when I pass the name pointer to setstring () function but I am confused about it please explain it in detail that what is happening here.

#include<iostream.h>
class person
{
char* name;
public:
person();
void setname(const char*);
void setstring(const char*, char*);
void print()const;
};
person::person()
{
name=new char[3];
strcpy(name,"NILL");
name[3]='\0';
}
void person::setstring(const char* s, char*p)
{
if(s!=NULL)
{
delete[] p;
p=new char[strlen(s)];
strcpy(p,s);
p[strlen(s)]='\0';
}
}
void person::setname(const char* n)
{
setstring(n, name);//passing data member name
}
void person::print()const
{
cout<<"Name: "<<name<<endl;
}
main()
{
person object;
object.setname("Zia ur Rahman");
object.print();
system("pause");
}

alt text

alt text

+2  A: 

Have you thought about using std::string from STL?

Though first problem I see is this.

person::person()
{
name=new char[3];
strcpy(name,"NILL");
name[3]='\0';
}

Your allocating an array of char's, the size of the array is 3 characters, then your copying "NILL" into it with strcpy so your filling in the array with all the characters but without the null terminator \0. "NILL" is a const string and such has a null terminator that is implicit but not shown for example "NILL\0". The \0 is a control character that is used to indicate the end of the string. Then you have an index out of bounds when you access the 3rd element of name array,when your size of your array is 3.

To help you find out the other parts that could be going wrong, here are some of the links to the function you use.

strcpy
strlen

strcpy will copy the whole string from one buffer to the next including the null terminator control character.

Strlen will return amount of characters between the beginning of the string and the terminating null character. Though it will not count the null character as a character. Thats why you will see suggestions with strlen(string)+1 to include the null terminator.

Though your doing well keep up the work, you will understand these little gotcha when using the standard library functions.

Chad
+1 use std::string.
Daniel Daranas
+2  A: 

For starters:

name=new char[3];
strcpy(name,"NILL");
name[3]='\0';

name has three elements - you are treating it as if it had five. In a similar vein:

p=new char[strlen(s)];

should be:

p=new char[strlen(s) + 1];

In fact, that function is completely wrong - you are supposed to be copying the string into 'name', not the mysterious 'p' parameter. If you really want that function, then 'p' must be a pointer to a pointer or a reference to a pointer.

anon
O YES, ok i make it correct, but still there is the same problem
Zia ur Rahman
when i write object.setname("zia") the output is Name: ziawhen i write object.setname("Zia ur Rahman") the output is nothing
Zia ur Rahman
+2  A: 

If you want to do correct OO-oriented programming in C++ you should maybe stay away from direct pointer management but use the STL string class and use references instead of pointers. Then you should have an easier time and your source should produce the correct output.

Otherwise check your constructor of the person class, the name-array has just 3 elements but you're referencing the 4th one there (indices 0-2!). Also in the setstring() method you're not allocating enough space for the trailing '\0' in the array!

Kosi2801
Nothing wrong with pointers, I would say stay away from references they can get you into all type of problems.
Chad
Same applies to pointers of course ;) But not the place to start a flamewar here, I had good and bad experiences with both types. Just that I had more good ones with references, but that's my personal experience over the years.
Kosi2801
No problem :) Im not the style police patrol. Was just curious.
Chad
A: 

Suppose s have 5 chars. Then new char[strlen(s)]; allocates the memory of 5 chars. Then p[strlen(s)]='\0' is equivalent to p[5]=0. It's very very bad. p[5] does not exsist.

void person::setstring(const char* s, char*p) 
{ 
if(s!=NULL) 
{ 
delete[] p; 
p=new char[strlen(s)]; 
strcpy(p,s); 
p[strlen(s)]='\0';    //<<<< LOOK! Out of range
} 
} 
Alexey Malistov
+2  A: 

The specific reason that nothing is being printed is that in setstring, p is copy of the name pointer, not a reference to it. Try changing the signature of setstring to:

void setstring(const char* s, char*& p);

(note the &).

See the other answers for other significant errors in the code - unless these problems are fixed, you are likely to get crashes or strange behaviour.

And unless the purpose of the code is just to learn dynamic arrays, use std::string instead :-).

James Hopkin
Nice spot, I didn't see that until I looked again :)
Chad
A: 

It's rather C, than C++ code. There is C++ equivalent:

#include <string>
#include <iostream>

class person
{
    std::string name_;
public:
    person();
    //preferable design is to set object invariant in appropriate constructor
    explicit person(const std::string &name);
    std::string get_name() const;
    void set_name(const std::string &name);
    void print()const;
};
person::person()
 : name_("NILL")
{}

person::person(const std::string &name)
: name_(name)
{}

std::string person::get_name() const
{
    return name_;
}

void person::set_name(const std::string &name)
{
    name_ = name;
}
void person::print()const
{
    std::cout<<"Name: "<<name_<<std::endl;
}

int main()
{
    person person1;
    person1.set_name("Zia ur Rahman");
    person1.print();

    //this is better design decision
    //because after constructor we have valid object
    person person2("Zia ur Rahman");
    person2.print();
    std::cin.get();
    return 0;
}
Sergey Teplyakov