views:

153

answers:

5

Hi,

I need to store a char array inside a class and then return it. I have to admit that I'm a bit confused about pointers and have tried everything I can think of but can't get it to work. Here's what I have:

#include <iostream>
using namespace std;

class Test {
public:
    void setName(char *name);
    char getName();
private:
    char m_name[30];
};

void Test::setName(char *name) {
    strcpy(m_name, name);
}

char Test::getName() {
    return *m_name;
}

void main() {

    Test foobar;
    char name[] = "Testing";
    foobar.setName(name);
    cout << foobar.getName();
}

Of course, I expect setName() to store the string "Testing" inside the class, and getName() should return "Testing". But instead, I get only the first letter T. What am I doing wrong?

I guess I should be using std strings but first I would like to understand why this does not work. As far as I know, this should work with char arrays as well?

+4  A: 

Just return a pointer:

const char* Test::getName() const
{
    return m_name;
}

and add a constructor for the class Test that would null-terminate the encapsulated array:

Test::Test()
{
    m_name[0] = 0;
}

so that you don't ask for trouble if someone instantiates class Test and doesn't call setName() on the instance.

sharptooth
I'd also suggest using strncpy() instead of strcpy(), and since this is C++, you should be using std::string instead of char pointers, which are a holdover from C
iWerner
+1 regarding the use of `std::string`. If you must use a C-string for some reason, you can return a C-string by using the `c_str()` member function of `std::string`.
Charles Salvia
+1  A: 

In Test::getName() you are just returning one character (first character). Instead you should return the address of the first character from where the string begins i.e. change the return type to char* and the return statement to return m_name;

Naveen
A: 

And it is safer to use strncpy() than strcpy() in void Test::setName()

skwllsp
+1  A: 

When you have a pointer, p, the pointer dereferencing operator * "follows" the pointer so the expression *p evaluates to whatever object the pointer is pointing at.

In many situations, the name of an array such as m_name, can behave like a pointer. Thus, *m_name evaluates to the first char in the array, since that is the type the array name, when interpreted as a pointer, points at.

Since strings in C are represented as pointers to characters, you should not dereference the pointer, but return it intact.

Many have suggested you use strncpy() to write the input string into your array, since it does (sort of) bounds checking. However, it is not optimal, it's semantics are odd and copying a string into a limited buffer is really not what it was designed for. It is better to investigate if you have a variety of the snprintf() function in your environment, and use that like so:

snprintf(m_name, sizeof m_name, "%s", name);
unwind
A: 

If you want this to be C++ simply dont use char pointers unless you have a very, very specific reason to do so!

Switch from char pointer to std::string and see if that solves your problem:

#include <iostream>
#include <string>
using namespace std;

class Test {
public:
    void setName(std::string name);
    std::string getName();
private:
    std::string m_name;
};

void Test::setName(std::string name) {
    m_name = name;
}

std::string Test::getName() {
    return m_name;
}

void main() { 
    Test foobar;
    foobar.setName("Testing");
    cout << foobar.getName();
}

For bonus points, make the parameter type in setName a const std::string&.

mizipzor