Home

C++/CLI Collections

 

Introduction

Like an array, a collection is a series of items of the same type. The particularity with creating an array is that you must know in advance the number of items that will make up the list. There are times when you don't know, you can't know, or you can't predict the number of items of the list. For this reason, you may want to create the list for which you don't specify the maximum number of items but you allow the user of the list to add, locate, or remove items at will.

Before creating a list, you probably should first decide or define what the list would be made of. As different as they are, one list can be made of numeric values. For example, a list that will be made of numbers. You may want a list that is made of names. Such a list can be created from a class that includes a string member variable. Another type of list can contain complex objects.

Practical LearningPractical Learning: Introducing Collections

  1. Start Microsoft Visual C++ and create a new CLR Empty Project named FlowerShop4
  2. To create a new class, in the Solution Explorer, right-click FlowerShop4 -> Add -> Class...
  3. In the Templates list, click C++ Class and click Add
  4. Set the Name of the class to CFlower and click Finish
  5. Change the Flower.h header file as follows:
     
    using namespace System;
    
    public enum FlowerType
    {
        Roses = 1,
        Lilies,
        Daisies,
        Carnations,
        LivePlant,
        Mixed
    };
    
    public enum FlowerColor
    {
        Red = 1,
        White,
        Yellow,
        Pink,
        Orange,
        Blue,
        Lavender,
        Various
    };
    Flower
    public enum FlowerArrangement
    {
        Bouquet = 1,
        Vase,
        Basket,
        Any
    };
    
    public ref class CFlower sealed
    {
    private:
        double pc;
    
    public:
        FlowerType Type;
        FlowerColor Color;
        FlowerArrangement Arrangement;
    
        property double UnitPrice
        {
            double get() { return pc; }
            void set(double value) { pc = value; }
        }
    
        CFlower();
    };
    
  6. Access the Flower.cpp source file and change it as follows:
     
    #include "Flower.h"
    
    CFlower::CFlower(void)
    {
        Type = FlowerType::Mixed;
        Color = FlowerColor::Mixed;
        Arrangement = FlowerArrangement::Vase;
        pc = 0.00;
    }
  7. To create a new class, in the Solution Explorer, right-click FlowerShop4 -> Add -> Class...
  8. In the Templates list, click C++ Class and click Add
  9. Set the Name of the class to COrderProcessing and click Add
  10. Complete the OrderProcessing.h header file as follows:
     
    #pragma once
    
    #include "Flower.h"
    
    using namespace System;
    
    public ref class COrderProcessing
    {
    public:
        CFlower ^ FlowerOrder;
       
    private:
        int qty;
    public:
    	COrderProcessing(void);
    
        property int Quantity
        {
            int get() { return qty; }
            void set(int value) { qty = value; }
        }
    
        property double TotalPrice
        {
            double get() { return Quantity * FlowerOrder->UnitPrice; }
        }
    
        void GetFlowerType();
        void GetFlowerColor();
        void GetFlowerArrangement();
        void ProcessOrder()
        void ShowOrder();
    };
  11. Access the OrderProcessing.cpp source file and change it as follows:
     
    #include "OrderProcessing.h"
    
    COrderProcessing::COrderProcessing(void)
    {
        FlowerOrder = gcnew CFlower;
    }
    
    void COrderProcessing::GetFlowerType()
    {
        int choice = 0;
    
        do {
            try {
                Console::WriteLine(L"Enter the Type of Flower Order");
                Console::WriteLine(L"1. Roses");
                Console::WriteLine(L"2. Lilies");
                Console::WriteLine(L"3. Daisies");
                Console::WriteLine(L"4. Carnations");
                Console::WriteLine(L"5. Live Plant");
                Console::WriteLine(L"6. Mixed");
                Console::Write("Your Choice: ");
                choice = int::Parse(Console::ReadLine());
            }
            catch(FormatException ^)
            {
                 Console::WriteLine(L"You failed to enter an "
                                    L"appropriate number!");
            }
    
            if ((choice < 1) || (choice > 6))
                Console::WriteLine(L"Invalid Value: Please enter "
                                   L"a value between 1 and 6");
        } while( (choice < 1) || (choice > 6) );
    
        switch(choice)
        {
        case 1:
            FlowerOrder->Type = Roses;
            break;
        case 2:
            FlowerOrder->Type = Lilies;
            break;
        case 3:
            FlowerOrder->Type = Daisies;
            break;
        case 4:
            FlowerOrder->Type = Carnations;
            break;
        case 5:
            FlowerOrder->Type = LivePlant;
            break;
        default:
            FlowerOrder->Type = Mixed;
            break;
        }
    }
    
    void COrderProcessing::GetFlowerColor()
    {
        int choice = 0;
    
        do {
            try {
                Console::WriteLine(L"Enter the Color");
                Console::WriteLine(L"1. Red");
                Console::WriteLine(L"2. White");
                Console::WriteLine(L"3. Yellow");
                Console::WriteLine(L"4. Pink");
                Console::WriteLine(L"5. Orange");
                Console::WriteLine(L"6. Blue");
                Console::WriteLine(L"7. Lavender");
                Console::WriteLine(L"8. Mixed");
                Console::Write("Your Choice: ");
    			choice = int::Parse(Console::ReadLine());
            }
            catch(FormatException ^)
            {
                Console::WriteLine(L"You didn't enter an "
                                   L"appropriate number!");
            }
    
            if( (choice < 1) || (choice > 8) )
                Console::WriteLine(L"Invalid Value: Please "
                                   L"enter a value between 1 and 8");
        } while ((choice < 1) || (choice > 8));
    
        switch(choice)
        {
        case 1:
            FlowerOrder->Color = Red;
            break;
        case 2:
            FlowerOrder->Color = White;
            break;
        case 3:
            FlowerOrder->Color = Yellow;
            break;
        case 4:
            FlowerOrder->Color = Pink;
            break;
        case 5:
            FlowerOrder->Color = Yellow;
            break;
        case 6:
            FlowerOrder->Color = Blue;
            break;
        case 7:
            FlowerOrder->Color = Lavender;
            break;
        default:
            FlowerOrder->Color = Various;
            break;
        }
    }
    
    void COrderProcessing::GetFlowerArrangement()
    {
        int choice = 0;
    
        do {
           try {
                Console::WriteLine(L"Enter the Type of Arrangement");
                Console::WriteLine(L"1. Bouquet");
                Console::WriteLine(L"2. Vase");
                Console::WriteLine(L"3. Basket");
                Console::WriteLine(L"4. Mixed");
                Console::Write("Your Choice: ");
    			choice = int::Parse(Console::ReadLine());
            }
            catch(FormatException ^)
            {
                Console::WriteLine(L"You didn't provide an "
                                   L"acceptable number!");
            }
    
            if( (choice < 1) || (choice > 4) )
                Console::WriteLine(L"Invalid Value: Please enter "
                                   L"a value between 1 and 4");
        } while ((choice < 1) || (choice > 4));
    
        switch (choice)
        {
        case 1:
            FlowerOrder->Arrangement = Bouquet;
            break;
        case 2:
            FlowerOrder->Arrangement = Vase;
            break;
        case 3:
            FlowerOrder->Arrangement = Basket;
            break;
        default:
            FlowerOrder->Arrangement = Any;
            break;
        }
    }
    
    void COrderProcessing::ProcessOrder()
    {
        GetFlowerType();
        GetFlowerColor();
        GetFlowerArrangement();
    
        try {
            Console::Write("Enter the Unit Price: ");
            FlowerOrder->UnitPrice = 
    			Math::Abs(double::Parse(Console::ReadLine()));
        }
        catch(FormatException ^)
        {
            Console::WriteLine(L"You didn't specify a valid price!");
        }
    
        try {
            Console::Write("Enter Quantity:       ");
    		Quantity = Math::Abs(int::Parse(Console::ReadLine()));
        }
        catch(FormatException ^)
        {
            Console::WriteLine(L"The quantity you entered "
                              L"is not acceptable!");
        }
    }
    
    void COrderProcessing::ShowOrder()
    {
        Console::WriteLine(L"=======================");
        Console::WriteLine(L"==-=-=Flower Shop=-=-==");
        Console::WriteLine(L"-----------------------");
        Console::Write(L"Flower Type:  ");
        switch(FlowerOrder->Type)
        {
        case 1:
            Console::WriteLine(L"Roses");
            break;
        case 2:
            Console::WriteLine(L"Lilies");
            break;
        case 3:
            Console::WriteLine(L"Daisies");
            break;
        case 4:
            Console::WriteLine(L"Carnations");
            break;
        case 5:
            Console::WriteLine(L"Live Plant");
    	break;
        default:
    	Console::WriteLine(L"Mixed");
        }
        
        Console::Write(L"Flower Color: ");
        switch(FlowerOrder->Color)
        {
        case 1:
            Console::WriteLine(L"Red");
    	break;
        case 2:
            Console::WriteLine(L"White");
    	break;
        case 3:
            Console::WriteLine(L"Yellow");
    	break;
        case 4:
            Console::WriteLine(L"Pink");
    	break;
        case 5:
            Console::WriteLine(L"Orange");
    	break;
        case 6:
            Console::WriteLine(L"Blue");
    	break;
        case 7:
            Console::WriteLine(L"Lavender");
    	break;
        default:
            Console::WriteLine(L"Various");
        }
    
        Console::Write(L"Arrangement:  ");
        switch(FlowerOrder->Arrangement)
        {
        case 1:
            Console::WriteLine(L"Bouquet");
    	break;
        case 2:
            Console::WriteLine(L"Vase");
    	break;
        case 3:
            Console::WriteLine(L"Basket");
    	break;
        default:
            Console::WriteLine(L"Any");
        }
    
        Console::Write(L"Price:        "); 
        Console::WriteLine(FlowerOrder->UnitPrice);
        Console::Write(L"Quantity:     "); 
        Console::WriteLine(Quantity);
        Console::Write(L"Total Price:  "); 
        Console::WriteLine(TotalPrice.ToString(L"C"));
        Console::WriteLine(L"=======================");
    }
  12. To create a source file, in the Solution Explorer, right-click FlowerShop4 -> Add -> New Item...
  13. In the Templates list, click C++ File (.cpp)
  14. Set the Name to Exercise and click Add
  15. Complete the file as follows:
     
    using namespace System;
    
    int main()
    {
        COrderProcessing ^ order = gcnew OrderProcessing;
    
        order->ProcessOrder();
        Console::WriteLine();
    
        order->ShowOrder();
    
        Console::WriteLine();
        return 0;
    }
  16. Execute the application and test it. Here is an example:
     
    Enter the Type of Flower Order
    1. Roses
    2. Lilies
    3. Daisies
    4. Carnations
    5. Live Plant
    6. Mixed
    Your Choice: 3
    Enter the Color
    1. Red
    2. White
    3. Yellow
    4. Pink
    5. Orange
    6. Blue
    7. Lavender
    8. Mixed
    Your Choice: 8
    Enter the Type of Arrangement
    1. Bouquet
    2. Vase
    3. Basket
    4. Mixed
    Your Choice: 1
    Enter the Unit Price: 45.50
    Enter Quantity:       3
    
    =======================
    ==-=-=Flower Shop=-=-==
    -----------------------
    Flower Type:  Daisies
    Flower Color: Various
    Arrangement:  Bouquet
    Price:        $45.50
    Quantity:     3
    Total Price:  $136.50
    =======================
    
    Press any key to continue . . .
    Daisy
  17. Close the DOS window

Implementing a Collection

After deciding what each item of the list would be made of, you can create a class that would manage the list. This class would be responsible for all operations that can be performed on the list. Here is an example:

using namespace System;

public ref class CNumbers
{
};

int main()
{
    CNumbers ^ nbrs = gcnew CNumbers;

    return 0;
}
Animation

If the list will be made of objects, you can first create a class that specifies those types of items and then declare its variable in the list class. Here is an example of a simple class that holds a double-precision value:

using namespace System;

public ref class CNumber
{
public:
    double Item;
};

public ref class CNumbers
{
    CNumber ^ Sample;
};

int main()
{
    CNumbers ^ nbrs = gcnew CNumbers;

    return 0;
}

When creating a list, one of the aspects you should pay attention to is to keep track of the number of items in the list. To do this, you can create a property that holds the number. The value of this property would increase as the items are added to the list and the value would decrease as the items are removed from the list. Here is how this can be done:

using namespace System;

public ref class CNumber
{
public:
    double Item;
};

public ref class CNumbers
{
private:
    int size;
    CNumber ^ Sample;

public:
    CNumbers()
    {
        size = 0;
    }

    property int Count
    {
        int get() { return size; }
    }
};

int main()
{
    CNumbers ^ nbrs = gcnew CNumbers;

    Console::WriteLine(L"Number of Items: {0}", nbrs->Count);

    return 0;
}

This would produce:

Number of Items: 0
Press any key to continue . . .

Practical LearningPractical Learning: Creating a CCollection Class

  1. Open the Flower.h header file and change it as follows:
     
    #pragma once
    
    using namespace System;
    
    . . . No Change
    
    public ref class CFlower
    {
    private:
        double prc;
    
    public:
        FlowerType Type;
        FlowerColor Color;
        FlowerArrangement Arrangement;
    
        property double UnitPrice
        {
            double get() { return prc; }
            void set(double value) { prc = value; }
        }
    
        CFlower(void);
    
    protected:
        int items;
    
    public:
        property int Count
        {
            int get() { return items; }
        }
    };
  2. Open the Flower.cpp source file and change it as follows:
     
    #include "Flower.h"
    
    CFlower::CFlower(void)
    {
        Type        = Mixed;
        Color       = Various;
        Arrangement = Vase;
        prc         = 0.00;
    	
        items       = 0;
    }
  3. To create a new class, in the Class View, right-click FlowerShop4 -> Add -> Class...
  4. In the Templates list, click C++ Class and click Add
  5. Set the Name to CFlowerInventory and click Finish
  6. Change the FlowerInventory.h header file as follows:
     
    #pragma once
    
    #include "Flower.h"
    
    public ref class CFlowerInventory : CFlower
    {
    public:
        CFlower ^ Inventory;
    
        CFlowerInventory(void);
    };
  7. Access the FlowerInventory.cpp source file and change it as follows:
     
    #include "FlowerInventory.h"
    
    CFlowerInventory::CFlowerInventory(void)
    {
        Inventory = gcnew CFlower;
    }

The Beginning of a Collection

A good collection is a list that can grow or shrink as the user wishes. When creating the list, you don't need to predict the maximum number of items that will be added to the list. When a list starts, it is empty or at least it must be considered like that, before any item is added to it. To specify this, you should declare a primary member variable. Although you can call it anything, it is usually called Head. This member can be made private if you don't intend to access it outside of the class. If you want clients of the class to access it, you can make it public. Here is an example:

public ref class CNumbers
{
private:
    int size;
    CNumber ^ Sample;

public:
    CNumber ^ Head;

    CNumbers()
    {
        size = 0;
        Head = nullptr;
    }

    property int Count
    {
        int get() { return size; }
    }
};

Linking the Items of a Collection

When using an array, each member can be accessed using its index. If the items of a collection are not indexed, you must provide a mechanism to locate an item. To do this, you can use a starting point that determines the beginning of the first. Then, to locate an item, you can check whether another item follows that starting point. If no item follows it, either you are at the end of the list or the list is empty.

To be able to scan a list from one item to another, you can declare a member variable. Although this member variable can be called anything, for the sake of clarify, you should call it Next. The member variable is the same type as its class. Here is an example:

public ref class CNumber
{
public:
    double Item;
    CNumber ^ Next;
};

Practical LearningPractical Learning: Creating a List's Monitor

  1. Access the Flower.h header file and change it as follows:
     
    using namespace System;
    
    . . . No Change
    
    public ref class CFlower
    {
    
        . . . No Change
    
    protected:
        int items;
    
    public:
        property int Count
        {
            int get() { return items; }
        }
    
        CFlower ^ Next;
    };
  2. Access the FlowerInventory.h header file and change it as follows:
     
    #pragma once
    
    #include "Flower.h"
    
    public ref class CFlowerInventory : CFlower
    { 
    public:
        CFlower ^ Inventory;
    
        CFlowerInventory(void);
        CFlower ^ Head;
    };
  3. Access the FlowerInventory.cpp source file and change it as follows:
     
    #include "FlowerInventory.h"
    
    CFlowerInventory::CFlowerInventory(void)
    {
        Head = nullptr;
        Inventory = gcnew CFlower;
    }
  4. Save all
 

Home Copyright © 2007-2012 FunctionX Next