How do I sort an array of objects according to enum value?

I have to create a function called 'void SortStks (Stock stks[], int size)'.
This function is to sort the array of passed Stock objects according to increasing sector (enum) value. This function does not have friendship status with the Stock class.

How can I do this?
Any examples will be extremely helpful!
Thanks!

So here is StockMain.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#include "Stock.h"
//function prototype
void SortStks(Stock[], int);
void CalculatePortfolio(Stock[], int);

void main()
{
	const int MAX_SIZE = 25;
	Stock StockInfo[MAX_SIZE];
	cout << "\nNumber of 'Stock' Objects in StockInfo Array: " << ReadStkData(StockInfo, MAX_SIZE) << endl;
}

int ReadStkData(Stock stks[], int maxSize)
{
	string filename, Trade = " ", Company = " ";
	int Shares = 0, sctr = 0;
	double pPrice = 0, cPrice = 0;;
	fstream inFile;
	int indexTotal = 0;
	cout << "User, please enter the name of the file to be read: ";
	cin >> filename; //correct filename for testing sample file is StockData.txt

	inFile.open(filename, ios::in);

	if (inFile.fail()){
		cout << "Error opening file! Exiting Program!" << endl;
		exit(-1);
	}

	while (getline(inFile, Trade, ' ')) //this loop condition acts as eof bit flag, will terminate loop once there are no more Trade Symbols to read
	{
		stks[indexTotal].setTradingSymbol(Trade);
		getline(inFile, Company, '#');
		stks[indexTotal].setCompanyName(Company);
		inFile >> sctr;
		stks[indexTotal].setSector(sctr);
		inFile >> Shares;
		stks[indexTotal].setNUMofShares(Shares);
		inFile >> pPrice;
		stks[indexTotal].setPurchasePrice(pPrice);
		inFile >> cPrice;
		stks[indexTotal].setCurrentPrice(cPrice);
		inFile.ignore(100000, '\n');
		indexTotal++;
	}

	inFile.close();

	return indexTotal;
}

void SortStks(Stock stks[], int size)
{


}

void CalculatePortfolio(Stock stks[], int size)
{


}


Stock.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#include <iostream>
#include <string>
#include <iomanip>
#include <fstream>
using namespace std;

#ifndef STOCK_H
#define STOCK_H

class Stock
{
private:
	string TradingSymbol;
	string CompanyName;
	static enum Sector { Technology, Health, Financial, Consumer_Goods, Utilities }; //static
	static enum Status { GAIN, LOSS, BREAKEVEN };
	Sector sctr;
	Status status;
	int NUMofShares;
	double PurchasePrice;
	double CurrentPrice;
	double CurrentValue; //used with CurrValue (public method)

public:
	//default constructor
	Stock();
	
	//public static named constant for tax gain
	static const double TaxOnGain; 
	
	//mutator functions declared in-line
	void setTradingSymbol(string trade) { TradingSymbol = trade; }
	void setCompanyName(string compName) {CompanyName = compName; }
	void setSector(int);
	void setNUMofShares(int shares) { NUMofShares = shares; }
	void setCurrentPrice(double currentPr) { CurrentPrice = currentPr; }
	void setPurchasePrice(double purchPr) { PurchasePrice = purchPr; }

	//accessor functions
	string getTradingSymbol() const {return TradingSymbol;}
	string getCompanyName() const {return CompanyName;}
	string getSector() const;
	int getNUMofShares() const {return NUMofShares;}
	double getPurchasePrice() const {return PurchasePrice;}
	double getCurrentPrice() const {return CurrentPrice;}
	
	// other public methods
	double CurrValue() const;
	enum Status CurrStatus(); // must return enumerated type of GAIN, LOSS, or BREAKEVEN
	double GainAmt();
	double TaxGainAmt();

	//friend function that reads stock data from file
	friend int ReadStkData(Stock stks[], int maxSize);
};

#endif  


Stock.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#include "Stock.h"
using namespace std;

Stock::Stock()
{
	TradingSymbol = "AAA";
	CompanyName = "Company Not Found";
	sctr = Technology;
	NUMofShares = 0;
	PurchasePrice = 0.0;
	CurrentPrice = 0.0;
	CurrentValue = 0.0;
}

void Stock::setSector(int sctrInt)
{
	if (sctrInt == 10)
		sctr = Technology;
	else if (sctrInt == 20)
		sctr = Health;
	else if (sctrInt == 30)
		sctr = Financial;
	else if (sctrInt == 40)
		sctr = Consumer_Goods;
	else if (sctrInt == 50)
		sctr = Utilities;
}

string Stock::getSector() const
{
	if (sctr == Technology)
		return "Technology";
	else if (sctr == Health)
		return "Health";
	else if (sctr == Financial)
		return "Financial";
	else if (sctr == Consumer_Goods)
		return "Consumer Goods";
	else if (sctr == Utilities)
		return "Utilities";
	else
		return "ERROR";
}

enum Stock::Status Stock::CurrStatus() //returns enumerated type
{
	if (CurrentPrice > (PurchasePrice + 0.05))
		status = GAIN;
	else if (CurrentPrice < (PurchasePrice - 0.05))
		status = LOSS;
	else if (CurrentPrice >= (PurchasePrice - 0.05) && CurrentPrice <= (PurchasePrice + 0.05))
		status = BREAKEVEN;

	return status;
}

double Stock::CurrValue() const
{
	return NUMofShares * CurrentPrice; 
}

double Stock::GainAmt()
{

	if (CurrStatus() == GAIN)
	{
		return (NUMofShares * (CurrentPrice - PurchasePrice));
	}
	else
		return 0.0;
}

double Stock::TaxGainAmt()
{
	double gainAmount = GainAmt();

	if (gainAmount > 0)
		return (gainAmount * TaxOnGain);
	else
		return 0.0;
}

//public static named constant
//must be initialized outside of class definition
//therefore it's in the implementation file for 'Stock' class
const double Stock::TaxOnGain = 0.15; 


and the data file I am reading from called StockData.txt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
RDEN Elizabeth Arden Inc# 40 25 13.25 9.8
AVP Avon Products Inc# 40 12 5.0 5.03
COH Coach Inc# 40 16 39.0 41.2
BAC Bank of America Corp# 30 23 20.5 14.25
WFC Wells Fargo & Co# 30 9 48.2 48.21
V Visa# 30 12 83.4 80.1
JNJ Johnson & Johnson# 20 3 105.2 109.82
LLY Eli Lilly and Company# 20 5 73.2 75.19
RPTP Raptor Pharmaceutical Corp# 20 18 5.6 5.64
CA CA Inc# 10 10 30.0 30.05
SYMC Symantec Corp# 10 7 20.8 17.9
TWTR Twitter Inc# 10 12 15.25 17.7
EIX Edison International# 50 2 71.03 71.0
HE Hawaiian Electric Industries Inc# 50 22 25.5 32.60
POR Portland General Electric# 50 9 43.6 39.54  
Is it really sorted by sector numeric value, or the string representation returned by getSector()? Doing it with the latter is easy.

Do you have to implement the sort algorithm yourself or can you use std::sort()? With std::sort(), all you have to write is the comparison function.
It should be sorted by sector numeric value. Lowest to Highest. I tried and got the string representation to work but the display is incorrect as it just displayed exactly how it was read initially into the array of objects. I bet the instructor set the sectors like this way on purpose so that we couldn't use string representation when sorting.

I don't think I am allowed to use the sort algorithm. I should use selection method or bubble sort or something along those lines.

However I would love to see the code for using std::sort(). It could prove useful for me outside of class.
Last edited on
I would love to see the code for using std::sort().
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>

enum Sector { Technology, Health, Financial, Consumer_Goods, Utilities };

std::ostream& operator << (std::ostream& os, const Sector& s)
{
    switch(s)
    {
        case Technology: os << "Technology"; break;
        case Health: os << "Health"; break;
        case Financial: os << "Financial"; break;
        case Consumer_Goods: os << "Consumer Goods"; break;
        case Utilities: os << "Utilities"; break;
    }
    return os;
}

struct Stock
{
    std::string m_name;
    Sector m_sec;
    Stock (std::string name, Sector sec)
        : m_name(name), m_sec(sec) {}
};
bool operator < (const Stock& lhs, const Stock & rhs)
{
    return lhs.m_sec < rhs.m_sec;
}
std::ostream& operator << (std::ostream& os, const Stock& s)
{
    os << s.m_name << " " << s.m_sec;
}

int main()
{
    std::vector<Stock> myStocks{};
    myStocks.emplace_back(Stock("Johnson & Johnson", Health));
    myStocks.emplace_back(Stock("Elizabeth Arden", Consumer_Goods));
    myStocks.emplace_back(Stock("Bank of America", Financial));
    myStocks.emplace_back(Stock("Avon", Consumer_Goods));
    myStocks.emplace_back(Stock("Twitter", Technology));

    std::sort(myStocks.begin(), myStocks.end());
    for (const auto& elem : myStocks)std::cout << elem << "\n";
}
This is my updated code including my sorting function. This is not exactly what I want. This sorts by the string representation of the enum. I need to do it by enum value in order to get the proper display I think. How could I do this?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#include "Stock.h"
//function prototype
void SortStks(Stock[], int);
void CalculatePortfolio(Stock[], int);

void main()
{
	const int MAX_SIZE = 25;
	int size;
	Stock StockInfo[MAX_SIZE];
	size = ReadStkData(StockInfo, MAX_SIZE);
	cout << "\nNumber of 'Stock' Objects in StockInfo Array: " << size << endl;
	SortStks(StockInfo, size);
	CalculatePortfolio(StockInfo, size);
}

int ReadStkData(Stock stks[], int maxSize)
{
	string filename, Trade = " ", Company = " ";
	int Shares = 0, sctr = 0;
	double pPrice = 0, cPrice = 0;;
	fstream inFile;
	int indexTotal = 0;
	cout << "User, please enter the name of the file to be read: ";
	cin >> filename; //correct filename for testing sample file is StockData.txt

	inFile.open(filename, ios::in);

	if (inFile.fail()){
		cout << "Error opening file! Exiting Program!" << endl;
		exit(-1);
	}

	while (getline(inFile, Trade, ' ')) //this loop condition acts as eof bit flag, will terminate loop once there are no more Trade Symbols to read
	{
		stks[indexTotal].setTradingSymbol(Trade);
		getline(inFile, Company, '#');
		stks[indexTotal].setCompanyName(Company);
		inFile >> sctr;
		stks[indexTotal].setSector(sctr);
		inFile >> Shares;
		stks[indexTotal].setNUMofShares(Shares);
		inFile >> pPrice;
		stks[indexTotal].setPurchasePrice(pPrice);
		inFile >> cPrice;
		stks[indexTotal].setCurrentPrice(cPrice);
		inFile.ignore(100000, '\n');
		indexTotal++;
	}

	inFile.close();

	return indexTotal;
}

//bool ValueCmp(Stock const & a, Stock const & b)
//{
//	return a.sctr > b.sctr;
//}


void SortStks(Stock stks[], int size)
{
	/*sort(stks, stks + size, ValueCmp);*/
	
	int i, j;
	int temp;   // holding variable
	int numLength = size;
	for (i = 0; i< (numLength - 1); i++)    // element to be compared
	{
		for (j = (i + 1); j < numLength; j++)   // rest of the elements
		{
			if (stks[i].getSectorSort() < stks[j].getSectorSort())          // descending order
			{
				temp = stks[i].getSectorSort();          // swap
				stks[i].getSectorSort() = stks[j].getSectorSort();
				stks[j].getSectorSort() = temp;
			}
		}
	}
	return;
}

void CalculatePortfolio(Stock stks[], int size)
{
	cout << "\nSTOCK DEMO" << endl; //testing to see if stock info is displayed correctly
	
	for (int x = 0; x < size; x++)
	{
		cout << "TradeSymbol: " << stks[x].getTradingSymbol() << endl;
		cout << "CompanyName: " << stks[x].getCompanyName() << endl;
		cout << "Sector: " << stks[x].getSector() << endl << endl;
	}

}
Last edited on
> It should be sorted by sector numeric value.

An unscoped enum is LessThanComparable; it can be directly used for the sort.


> I would love to see the code for using std::sort()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#include <iostream>
#include <string>
#include <algorithm>
#include <iterator>

class Stock
{
    public:
        enum Sector { Technology, Health, Financial, Consumer_Goods, Utilities }; //static
        enum Status { GAIN, LOSS, BREAKEVEN };

    private:
        std::string symbol = "AAA";
        std::string company;
        Sector sctr = Technology ;
        Status status = BREAKEVEN ;
        int num_shares = 0 ;
        // etc.

    public:
       Stock() = default ;
       Stock( std::string symbol, std::string company, Sector sector, Status status, int num_shares )
           : symbol(symbol), company(company), sctr(sector), status(status), num_shares(num_shares) {}

       Sector sector() const { return sctr ; }

       // ...

    friend std::ostream& operator<< ( std::ostream& stm, const Stock& stk )
    {
        static const std::string sector_names[] = { "Technology", "Health", "Financial", "Consumer_Goods", "Utilities" };
        return stm << "Stock{ symbol:" << stk.symbol
                   << ", company:" << stk.company
                   << ", sector: " << sector_names[ stk.sector() ]
                   << ", num shares:" << stk.num_shares << " }" ;
    }
};

int main()
{
    Stock my_stocks[]
    {
        { "RDEN", "Elizabeth Arden Inc", Stock::Financial, Stock::GAIN, 500 },
        { "AVP", "Avon Products Inc", Stock::Consumer_Goods, Stock::BREAKEVEN, 650 },
        { "BAC", "Bank of America Corp", Stock::Financial, Stock::LOSS, 1000 },
        { "WFC", "Wells Fargo & Co", Stock::Health, Stock::GAIN, 300 },
        { "VISA", "Visa", Stock::Financial, Stock::GAIN, 700 },
        { "RPTP", "Raptor Pharmaceutical Corp", Stock::Health, Stock::LOSS, 250 }
    };

    std::sort( std::begin(my_stocks), std::end(my_stocks), // sort ascending on sector
               [] ( const Stock& a, const Stock& b ) { return a.sector() < b.sector() ; } ) ;

    std::cout << "list of my stocks sorted on sector:\n-----------------------------\n" ;
    Stock::Sector prev_sector = Stock::Sector(88) ;
    for( const Stock& stk : my_stocks )
    {
        if( stk.sector() != prev_sector )
        {
            std::cout << '\n' ;
            prev_sector = stk.sector() ;
        }
        std::cout << stk << '\n' ;
    }
}

http://coliru.stacked-crooked.com/a/f16234459e7054c2
JLBorges,
1
2
3
> It should be sorted by sector numeric value.

An unscoped enum is LessThanComparable; it can be directly used for the sort.

What do you exactly mean by the second statement? LessThanComparable???
Last edited on
LessThanComparable: The type must work with (the) < operator and the result should have standard semantics.
http://en.cppreference.com/w/cpp/concept/LessThanComparable
I still don't know what's wrong. I can't figure this out! Sad!

I have a red squiggly underline on lines 78, 79 under stks.

Also a red line on line 66 right by the (-) minus sign. Says it expected a ')'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void SortStks(Stock stks[], int size) //selection sort
{
	int startScan;
	int minIndex, minValue;
	for (startScan = 0; startScan < (size − 1); startScan++)
	{
		minIndex = startScan;
		minValue = stks[startScan].SectorSort();
		for (int index = startScan + 1; index < size; index++)
		{
			if (stks[index].SectorSort() < minValue)
			{
				minValue = stks[index].SectorSort();
				minIndex = index;
			}
		}
		stks[minIndex].SectorSort() = stks[startScan].SectorSort();
		stks[startScan].SectorSort() = minValue;
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int Stock::SectorSort() //used for sorting
{
			if (sctr == Technology)
				return 10;
			else if (sctr == Health)
				return 20;
			else if (sctr == Financial)
				return 30;
			else if (sctr == Consumer_Goods)
				return 40;
			else if (sctr == Utilities)
				return 50;
			else
				return 99; //flag that'll let the user know, there is an error
}


Basically I need the array elements and objects that have a sctr of Technology to appear first, Health second, Financial third, Consumer Goods forth, and finally Utilities last after a sort once I display them.

I don't know why this is so confusing.
Last edited on
"Red squiggly line" isn't particularly helpful. Your compiler should give you actual error messages that contain useful information. Telling us what those messages are helps us to help you.

The line:
stks[minIndex].SectorSort() = stks[startScan].SectorSort();

looks fishy. stks[minIndex].SectorSort() is a function call, and is something we call an "rvalue" - how can you possibly assign another value to it? What are you trying to achieve here?

The line that immediately follows that one has the same problem.

Also a red line on line 66 right by the (-) minus sign. Says it expected a ')'

Are you sure it's a minus sign? Are you sure you haven't accidentally put in an elongated dash symbol instead?
Last edited on
I don't know why this is so confusing.
Well, SectorSort() is completely missleading. It does not sort instead it returns a value that (I guess) is a priority (so a better name for the function would be GetPriority()). The priority cannot be changed since it tied to the sector. You need to swap the sector not the priority, hence:
1
2
3
4
5
6
			if (stks[i].getSectorSort() < stks[j].getSectorSort())          // descending order
			{
				temp = stks[i];          // swap
				stks[i] = stks[j];
				stks[j] = temp;
			}


this loop condition acts as eof bit flag
It is better to check the entire dataset before you add it to your database.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
class Stock
{
    public:
        enum Sector { Technology, Health, Financial, Consumer_Goods, Utilities }; //static
        // ...
    private:
        Sector sctr = Technology ;
        // etc.

    public:
       Sector sector() const { return sctr ; }
       // ...
    // ...
};

Stock& min_stock( Stock stocks[], std::size_t size )
{
    std::size_t minp = 0 ;
    for( std::size_t i = 1 ; i < size ; ++i )
        if( stocks[i].sector() < stocks[minp].sector() ) minp = i ;
    return stocks[minp] ;
}

void swap_stocks( Stock& a, Stock& b )
{
    const Stock temp = a ;
    a = b ;
    b = temp ;
}

void sort_stocks( Stock stocks[], std::size_t size ) // selection sort
{
    if( size > 0 )
    {
        swap_stocks( stocks[0], min_stock( stocks, size ) ) ;
        sort_stocks( stocks+1, size-1 ) ;
    }
}

http://coliru.stacked-crooked.com/a/abaf6c6bf29aec7c
Topic archived. No new replies allowed.