2

I am new to c++ , I was trying to print the fields of a structure using an array.

I know the compiler is not able to understand what is inside deck[1] in the line for(int x:deck[1]), since deck[1] is an unknown data type (a structure datatype defined as 'card'). So x is not able to scan the elements within this data type.

I wish to know, how may I print the elements within this deck[1], i.e {1,1,1}.

#include <iostream>
using namespace std;

struct card
{
    int face;
    int shape;
    int color;
};

int main()
{
    
    struct card deck[52];
    
    deck[1].face=1;
    deck[1].shape=1;
    deck[1].color=1;
    
    cout<< sizeof(deck)<<endl;
    
    for(int x:deck[1])
    {
        cout<<x<<endl
    }

    return 0;
}
Anshuman Sinha
  • 157
  • 1
  • 9
  • 1
    The same way you populated them. `cout << deck[1].face << endl << deck[1].shape << endl << deck[1].color << endl;` – Igor Tandetnik Mar 06 '22 at 17:40
  • 1
    Better yet, overload `<<` for your `card` struct. – Chris Mar 06 '22 at 17:41
  • 1
    Also note that C++ is not "C with classes" and you can just write `card deck[52]` rather than `struct card deck[52]`, but better is `std::array deck`. – Chris Mar 06 '22 at 17:42
  • Hey @Chris, thanks for your reply. How to overload '<<' ? and why is writing 'std::array' deck better? – Anshuman Sinha Mar 06 '22 at 17:45
  • @IgorTandetnik thanks a lot for your reply, can you please tell me how to write this using a 'for' loop? , because at the moment I am having only 3 entries in card. What if I have large number of entries in this structure? – Anshuman Sinha Mar 06 '22 at 17:47
  • For operator overloading: https://stackoverflow.com/questions/4421706/what-are-the-basic-rules-and-idioms-for-operator-overloading – Chris Mar 06 '22 at 17:47
  • @AnshumanSinha You **can't loop through** the data members of an object of a class type such as `card`. That is you can't use a `for` loop for iterating over the data member of an object of `card`. You can access the data member individually. – Jason Mar 06 '22 at 17:48
  • As for `std::array` vs. raw arrays: there are a number of advantages. A couple: Behavior of arrays as function parameters is confusing. Using `std::array` makes it clearer. You get the `size` member function, which raw arrays don't give you. – Chris Mar 06 '22 at 17:51
  • C++ doesn't have reflection facilities at this time. There's no way to iterate over data members. – Igor Tandetnik Mar 06 '22 at 17:51
  • "What if I have large number of entries in this structure?" How much is large? Are those all int numbers? You could have a list of member pointers or you could store the properties differently or you could use the visitor pattern. Give more information about what (type) and how many properties to expect and what operations you want to do on them. There is (nearly) always a solution in C++, most other languages are written in C++. – Sebastian Mar 06 '22 at 20:59

3 Answers3

1

Note that you can't loop through the data members of an object of a class type such as card. You can only print out the data members individually. So you can use operator overloading to achieve the desired effect. In particular, you can overload operator<< as shown below.

#include <iostream>

struct card
{
    int face;
    int shape;
    int color;
    
    //overload operator<<
    friend std::ostream& operator<<(std::ostream &os, const card& obj);
};

std::ostream& operator<<(std::ostream &os, const card& obj)
{
    os << obj.face << " " << obj.shape << " " << obj.color;
    return os;
}

int main()
{ 
    card deck[52] = {};
    
    deck[1].face = 1;
    deck[1].shape = 1;
    deck[1].color = 1;
    
    std::cout << deck[1].face << " " << deck[1].shape << " " << deck[1].color << std::endl;
    
    //use overloaded operator<<
    std::cout << deck[1] << std::endl;\
}

The output of the above program can be seen here:

1 1 1
1 1 1
Chris
  • 26,361
  • 5
  • 21
  • 42
Jason
  • 36,170
  • 5
  • 26
  • 60
0

There are many ways to do this. Here's two ways.

1.

cout << deck[1].face << " " << deck[1].shape << " " << deck[1].color << endl;
  1. Overload the << operator to support printing card to cout:
std::ostream &operator<<(std::ostream &os, card const &c) { 
    return os << c.face << " " << c.shape << " " << c.color << endl;
}

Then you can just do

cout << deck[1] << endl;
kwsp
  • 1,184
  • 7
  • 26
-1

I would probably add a method for getting a string representation of a card object:

#include <sstream>

struct card
{
    // ...
    std::string toString() const
    {
        std::stringstream str;
        str << "card[face=" << face << ", shape=" << shape << ", color=" << color << ']';
        return str.str();
    }
};

Then just print the result:

int main()
{
    // ...
    std::cout << deck[1].toString() << '\n';
    // ...
}

(Note that I use '\n' instead of std::endl, because std::endl flushes the output buffer, which has a slight performance impact.)

You could also overload operator<< to remove the toString() method call:

std::ostream& operator<<(std::ostream& os, const card& c)
{
    return os << c.toString();
}

Now you could probably do some pointer hackery if you really want to treat your card object as an array, but I wouldn't recommend it as such workarounds often result in just messier and less safe code.

https://en.cppreference.com/w/cpp/io/basic_stringstream https://en.cppreference.com/w/cpp/language/operators#Stream_extraction_and_insertion

Debaug
  • 452
  • 4
  • 14