I'm trying to figure out how do i print a distinct enum value by using a conditional statement in my construction of array.

I have a enum declaration

enum Animal {Rat, Ox, Tiger, Rabbit, Dragon, Snake, Horse, Sheep, Monkey, Rooster, Dog, Pig};

And i construct my array using a voidptr

void constructSet(VoidPtr* animalArray, int size)
{
 int k = 0;  

   for(int i = 0; i < size; i++)
   {
     animalArray[i] = getAnAnimal();

     while ((k < i) || (animalArray[i] == animalArray[k]))
     {   
        if (animalArray[i] == animalArray[k])
            animalArray[i] = getAnAnimal();   

        k++;
    }        
}

}

Then i have to use some static cast to revive the value of my enum

VoidPtr getAnAnimal()
 {
VoidPtr anAnimal;

Animal *a = new Animal;

int k = rand() % 12;

*a = static_cast<Animal>(k);

anAnimal = a;

return anAnimal;
}

Unfortunately, they still return me the same values.

I'm thinking your problem has little to do with enumerated types versus integers and converting between the two. Instead it probably has to do with using pointers incorrectly. Assuming VoidPtr is typedefed as void*, VoidPtr* would be void** and thus animalArray[i] would be a void*. Thus your comparison of whether animalArray[i] is equal to animalArray[k] would be comparing addresses, not the animal types.

I'm not sure what you're trying to do here, but I'm guessing you are trying to create an array of animals where there are never two of the same animal types back to back (i.e. if element 3 is a tiger, element 4 cannot be a tiger)? That's just a guess.

I think if there isn't a good reason not to, have a plain old array of type Animal rather than the void** stuff.

Why not something like this:

enum Animal{ Rat, Cow };

static const char * AnimalStrs[] = { "Rat", "Cow" };

const char * GetAnimalStr( int enumVal )
{
  return AnimalStrs[enumVal];
}

Also, instead of constantly iterating over the array to check for duplicates, you should find it more efficient to use a vector<int> of indexes. Once you've chosen a random index, erase it from the vector. This way even if the same number is chosen it will point to a different index:

enum Animal { Rat, Ox, Tiger, Rabbit, Dragon, Snake, Horse, Sheep, Monkey, Rooster, Dog, Pig };
void MakeUniqueRandomCollection(Animal randomAnimals[12])
{
    vector<int> indexes = { 0,1,2,3,4,5,6,7,8,9,10,11 };
    for (int i = 0; i < 12; i++)
    {
        int randIndex = rand() % indexes.size();
        randomAnimals[i] = (Animal)indexes[randIndex];
        indexes.erase(indexes.begin()+randIndex);
    }
    return;
}
int main()
{

    Animal randomAnimals[12];
    MakeUniqueRandomCollection(randomAnimals);
    for (int i = 0; i < 12; i++)
    {
        cout << randomAnimals[i] << '\n';
    }
    return 0;
}

Now, this will print out a list of random integers. To get a list of names, one way you could go is a map<int, string>. Depending on how big the collection is going to be a map should give you very efficient lookup to get the names:

map<int, string> Animal
{
    {0,"Rat"},
    {1,"Ox"},
    {2,"Tiger"},
    {3,"Rabbit"},
    {4,"Dragon"},
    {5,"Snake"},
    {6,"Horse"},
    {7,"Sheep"},
    {8,"Monkey"},
    {9,"Rooster"},
    {10,"Dog"},
    {11,"Pig"}
};
void MakeUniqueRandomCollection(string randomAnimals[12])
{
    vector<int> indexes = { 0,1,2,3,4,5,6,7,8,9,10,11 };
    for (int i = 0; i < 12; i++)
    {
        int randIndex = rand() % indexes.size();
        randomAnimals[i] = Animal[indexes[randIndex]];
        indexes.erase(indexes.begin()+randIndex);
    }
    return;
}
int main()
{

    string randomAnimals[12];
    MakeUniqueRandomCollection(randomAnimals);
    for (int i = 0; i < 12; i++)
    {
        cout << randomAnimals[i] << '\n';
    }
    return 0;
}

Of course for smaller collections, a simple string array would suffice:

string Animal[ 12 ] = 
{   
    "Rat",  
    "Ox",   
    "Tiger",    
    "Rabbit",
    "Dragon",
    "Snake",
    "Horse",
    "Sheep",
    "Monkey",
    "Rooster",
    "Dog",
    "Pig"
};
void MakeUniqueRandomCollection(string randomAnimals[12])
{
    vector<int> indexes = { 0,1,2,3,4,5,6,7,8,9,10,11 };
    for (int i = 0; i < 12; i++)
    {
        int randIndex = rand() % indexes.size();
        randomAnimals[i] = Animal[indexes[randIndex]];
        indexes.erase(indexes.begin()+randIndex);
    }
    return;
}
int main()
{

    string randomAnimals[12];
    MakeUniqueRandomCollection(randomAnimals);
    for (int i = 0; i < 12; i++)
    {
        cout << randomAnimals[i] << '\n';
    }
    return 0;
}

Edited 1 Month Ago by tinstaafl

One of the critieria for this is to use a voidpointer but not any typical plain array or a vector. that is the issue i'm facing.

I've changed my conditional statement by deferencing with my enum values

     while ((k < i) || (animalArray[i] == animalArray[k]))
     {   
             if (animalArray[i] == animalArray[k])
            {
                  animalArray[i] = getAnAnimal();   
                  k++;
            }
       }                    
}

to

   while((k < i) && ((*(static_cast<Animal *>(animalArray[i]))) == (*(static_cast<Animal *>(animalArray[k])))))
   {
        animalArray[i] = getAnAnimal();                
        k++;    
   }

However, it still doesn't seems to work.

One of the critieria for this is to use a voidpointer

You have a pointer to a void pointer, or a void**. Is THAT required? If not, I see no reason to have any code with VoidPtr*.

I'll reiterate that my guess is that the problem isn't converting enumerated types to integers and vice-versa (hard to tell since I don't see that code), but rather the pointers. This code seems overly complicated to me. It may work, but I doubt it's necessary. It's still unclear to me what you are trying to accomplish in that loop. You might want to throw a comment or two in there.

while((k < i) && ((*(static_cast<Animal *>(animalArray[i]))) == (*(static_cast<Animal *>(animalArray[k])))))

However, it still doesn't seems to work.

More details needed. WHAT doesn't work? What is supposed to happen? What does happen? Your initial statement says you are trying to print something out, but I see no print code anywhere in your posts.

I think your main problem is that, you can't assign a value to or read the value of a void* without telling the compiler what data type is being stored at that pointer. I've fixed the code you started with. Since the compiler will try to translate (T) as static_cast<T>() before any of the other cast functions, I used that as a shortcut, since there is a lot of casting needed:

enum Animal { Rat, Ox, Tiger, Rabbit, Dragon, Snake, Horse, Sheep, Monkey, Rooster, Dog, Pig };

void constructSet(void* animalArray, int size)
{
    for (int i = 0; i < size; i++)
    {
        bool uniqueAnimal = false;
        while (!uniqueAnimal)
        {
            Animal* tempAnimal = new Animal((Animal)(rand() % 12));
            int k = 0;
            for (; k < i; k++)
            {
                if (((Animal*)animalArray)[k] == *tempAnimal)
                {
                    break;
                }
            }
            if (k == i)
            {
                ((Animal*)animalArray)[i] = *tempAnimal;
                uniqueAnimal = true;
            }
        }

    }
}

int main()
{
    //This will help to randomize the seed for rand.  
    //This way you won't get the same sequence each time you start
    //the program.
    srand (time(NULL));
    void* randomAnimals = new Animal[12];
    constructSet(randomAnimals,12);
    for (int i = 0; i < 12; i++)
    {
        cout << ((Animal*)randomAnimals)[i] << '\n';
    }
    return 0;
}

You'll notice I eliminated one function. Other than casting between Animal and void* all it was doing was creating a random animal. By keeping it as an Animalit eliminated the extra casting.

Edited 1 Month Ago by tinstaafl

The article starter is a financial contributor. Sponsored articles offer a bounty for quality replies.