11

I'm having trouble declaring and initializing a char array. It always displays random characters. I created a smaller bit of code to show what I'm trying in my larger program:

class test
{
    private:
        char name[40];
        int x;
    public:
        test();
        void display()
        {
            std::cout<<name<<std::endl;
            std::cin>>x;
        }
};
test::test()
{
    char name [] = "Standard";
}

int main()
{   test *test1 = new test;
    test1->display();
}

And sorry if my formatting is bad, I can barely figure out this website let alone how to fix my code :(

x4u
  • 13,877
  • 6
  • 48
  • 58
ShengLong916
  • 159
  • 2
  • 2
  • 6
  • Related: [How can i use member initialization list to initialize it?](http://stackoverflow.com/q/5602030/636019) – ildjarn May 02 '12 at 22:28
  • Okay, so I'm using std::string now, however in the larger program this is for I was using a get function like this: void get(char prompt[], int size,char b[]) where char b[] was my char array from before. How would I modify that in order to pass a string to my get function? – ShengLong916 May 02 '12 at 22:41
  • Return a `std::string` object instead of `void`. – ildjarn May 02 '12 at 23:04

5 Answers5

10

If there are no particular reasons to not use std::string, do use std::string.

But if you really need to initialize that character array member, then:

#include <assert.h>
#include <iostream>
#include <string.h>
using namespace std;

class test
{
    private:
        char name[40];
        int x;
    public:
        test();
        void display() const
        {
            std::cout<<name<<std::endl;
        }
};

test::test()
{
    static char const nameData[] = "Standard";

    assert( strlen( nameData ) < sizeof( name ) );
    strcpy( name, nameData );
}

int main()
{
    test().display();
}
Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
6

Your constructor is not setting the member variable name, it's declaring a local variable. Once the local variable goes out of scope at the end of the constructor, it disappears. Meanwhile the member variable still isn't initialized and is filled with random garbage.

If you're going to use old-fashioned character arrays you'll also need to use an old-fashioned function like strcpy to copy into the member variable. If all you want to do is set it to an empty string you can initialize it with name[0] = 0.

Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
5

Since you are using C++, I suggest using strings instead of char arrays. Otherwise you'd need to employ strcpy (or friends).

Also, you forgot to delete the test1 instance.

#include <iostream>
#include <string>

class test
{
    private:
        std::string name;
        int x;
    public:
        test();
        void display()
        {
            std::cout<<name<<std::endl;
        }
};

test::test()
{
    name = "Standard";
}

int main()
{   
    test test1;
    test1.display();

    std::cin>>x;
}
sehe
  • 374,641
  • 47
  • 450
  • 633
  • 1
    use case for char arrays: C++ is available in places where std lib is not, like microcontrollers. – ABCD.ca Dec 03 '14 at 22:02
5

Considering you tagged the question as C++, you should use std::string:

#include <string>

class test
{
    private:
        std::string name;
        int x;
    public:
        test();
        void display()
        {
            std::cout<<name<<std::endl;
            std::cin>>x;
        }
};
test::test() : name("Standard")
{

}
mfontanini
  • 21,410
  • 4
  • 65
  • 73
  • 1
    I never quite understand how 'identical' answers posted _later_ would get more upvotes. And my answer was arguably (quite a lot) more complete from the get-go... – sehe May 02 '12 at 22:36
  • I don't really get this site yet sehe, i tried to upvote both but couldn't. Sorry. – ShengLong916 May 02 '12 at 22:40
  • @user1371155 It's ok, I wasn't actually blaming anyone :) – sehe May 02 '12 at 22:42
  • @sehe: in order not to favor the first answer, and hopefully give more visibility to the others, answers with the same score are randomly ordered. This means that instead of the first to post getting more visibility it is the first to get an upvote that does; which is arguably better, but not by much. – Matthieu M. May 03 '12 at 06:21
3

actually provides two ways of doing this. You can default the member on it's declaration line or you can use the constructor initialization list.

Example of declaration line initialization:

class test1 {
    char name[40] = "Standard";
public:
    void display() { cout << name << endl; }
};

Example of constructor initialization:

class test2 {
    char name[40];
public:
    test2() : name("Standard") {};
    void display() { cout << name << endl; }
};

You can see a live example of both of these here: http://ideone.com/zC8We9

My personal preference is to use the declaration line initialization because:

  1. Where no other variables must be constructed this allows the generated default constructor to be used
  2. Where multiple constructors are required this allows the variable to be initialized in only one place rather than in all the constructor initialization lists

Having said all this, using a char[] may be considered damaging as the generated default assignment operator, and copy/move constructors won't work. This can be solved by:

  1. Making the member const
  2. Using a char* (this won't work if the member will hold anything but a literal string)
  3. In the general case std::string should be preferred
Jonathan Mee
  • 37,899
  • 23
  • 129
  • 288