views:

177

answers:

4

Why cannot initialize my array of strings in my constructor? I get the following error: internal compiler error: Segmentation fault|

at these two lines in the constructor: suits = {"Clubs", "Diamonds", "Hearts", "Spades"}; denominations = {"Ace","2","3","4","5","6","7","8","9","10","Jack","Queen","King"};

class Card
    {
      public:
        Card(int n);
        Card(string d, string s);
        int getNumber();
        string getDenomination();
        string getSuit();
        void setNumber(int n);
        void setDenomination(string d);
        void setSuit(string s);
        void printMe();
        void compareMe(Card c);

      private:
        int number;
        string denomiation;
        string suit;
        string suits [4];
        string denominations [13];
    };


    Card::Card(int n)
    {
        suits = {"Clubs", "Diamonds", "Hearts", "Spades"};
        denominations = {"Ace","2","3","4","5","6","7","8","9","10","Jack","Queen","King"};

        int denIndex, suitIndex;

        denIndex = 51 % 13;
        suitIndex = 51 / 13;

        number = n;
        denomiation = denominations[denIndex];
        suit = suits[suitIndex];

    }
+4  A: 

use std::vector or boost::array, a simplified example of your code is below

#include <boost/assign/list_of.hpp>

#include <boost/array.hpp>

#include <iostream>
#include <string>

class Card
{
public:
    explicit Card( unsigned n ) :
        _number( n ),
        _suits( boost::assign::list_of( "Clubs" )( "Diamonds" )( "Hearts" )( "Spades" ) ),
        _denominations( boost::assign::list_of( "Ace" )( "2" )( "3" )( "4" )( "5" )( "6" )( "7" )( "8" )( "9" )( "10" )( "Jack" )( "Queen" )( "King" ) )
    {

    }

private:
    unsigned _number;
    boost::array<std::string, 4> _suits;
    boost::array<std::string, 13> _denominations;
};

int
main()
{
    Card foo( 5 );

    return 0;
}
Sam Miller
That's good advice but it doesn't help with the issue at hand, which is that you can't assign an array literal like that. You'd have the same problem if you tried to do that sort of thing with a vector.
Ferruccio
@Ferruccio: not true, the syntax is called "initializer list", and will be fully supported within c++0x. Using std::vector is still the better choice here.
nebukadnezzar
Incomplete answer
0A0D
to the down votes: I've updated my answer with some example code
Sam Miller
I see. Without the example it seemed like you were saying to keep the code as is but use vectors instead of built-in arrays.
Ferruccio
+4  A: 

You can only use literal array initialization at construction, not assignment.

int good[3] = { 1, 2, 3 }; // OK
int bad[3];
bad = { 1, 2, 3 }; // not so good

You will have to copy the array manually (or use a container like vector or boost::array.

Motti
+4  A: 

From the code you posted, I guess that the menbers suits and denominations should be static data member, that is they will always have the same data for every Card instance.

So I suggest you make them static and initialize them at file scope in your cpp file (outside of your class declaration):

Declaration:

class Card
{
  public:
    Card(int n);
    Card(string d, string s);
    int getNumber();
    string getDenomination();
    string getSuit();
    void setNumber(int n);
    void setDenomination(string d);
    void setSuit(string s);
    void printMe();
    void compareMe(Card c);

  private:
    int number;
    string denomiation;
    string suit;
    static const string suits [4];                 // static const
    static const string denominations [13];        // static const
};

Definition:

const string Card::suits[4] = {"Clubs", "Diamonds", "Hearts", "Spades"};
const string Card::denominations[13] = {"Ace","2","3","4","5","6","7","8","9","10","Jack","Queen","King"};

EDIT: As Robert S. Barnes stated, making them static const is even better.

Hope that helps.

Frank Bollack
How does this work with complex types? I know with simple types like `char*` the compiler takes the data, puts it in a read only section and then sets the pointer to point to it. Does this do something similar but instead call the `=` operator at run time? Shouldn't the declaration be `static const`?
Robert S. Barnes
This one calls the array initializer (invokes the single-argument constructor for each element), which works with the compound initialization syntax. There is no compound assignment syntax.
Ben Voigt
+1, the list of suits and denominations is not specific to each card in a deck, it is specific to the deck itself.
dreamlax
Good point, I would remove the explicit size specification, you can let the compiler deduce it for you `string Card::suits[] = {/*.*/};`
Motti
@Robert S. Barnes: `static const` is even better. Changed that.
Frank Bollack
+4  A: 

If you're getting an ICE (internal compiler error), then you really should report the code to whoever wrote your compiler. Compilers are supposed to print out warnings and errors, but not segmentation fault.

sharth