Tags

, , ,


Introduction

Today’s C++ guide is about sorting an STL vector that contains objects representing end of day stock price data. Normally the STL sort() method is used on numeric values, but with so much data encapsulated into objects and then those objects being passed around in containers, methods like sort() can be used in a variety of ways to handle all different data types.

Sorting objects requires a comparison method to return a boolean value for each pair sent to it. In our case we want to compare on a number of values held in the object. The object represents the end of day movements of shares, specifically 1 share – 1 Object. The share price object contains a share stock code, an opening price, a closing price, the days low and high values and the total volume traded. We will implement the default sort based on the closing price, so the object includes an operator<() function.

I did a bit of research to come up with a working solution that did not require the latest C++11 compiler. This code was tested on Ubuntu desktop version 3.11.0-18-generic #32-Ubuntu SMP.

The files:

    • StockCode.h
    • StockCode.cpp
    • main.cpp

StockCode.h File:

This represents a single share price:

#ifndef __STOCK_CODE_CLASS__
#define __STOCK_CODE_CLASS__

#include <functional>
#include <algorithm>
#include <string>

using namespace std; 

class StockCode
{
public:
StockCode();
StockCode(string code);
~StockCode();

string getCode();
void setCode(string code);
double getClose();
void setClose(double v);

bool operator<(const StockCode &R) const { return ( this->_close < R._close); }

string _code;
double _open;
double _close;
long _vol;
double _high;
double _low;
};

#endif

The STL sort() method will use the operator<() method to find which object has the smaller value, so the code is fairly simple:

bool operator<(const StockCode &R) const { return ( this->_close < R._close); }

For simplicity I have left the class values “public”, normally they are “private” and an accessor such as getClose() is used to get the value.

StockCode.cpp


#include <string>
#include “StockCode.h”

using namespace std;

StockCode::StockCode() {}
StockCode::StockCode(string code) : _code(code) {}
StockCode::~StockCode(){}

string StockCode::getCode() { return _code; }
void StockCode::setCode(string code) { _code = code; }
double StockCode::getClose() { return _close; }
void StockCode::setClose(double v) { _close = v; }

Test Application

The test application creates a number of StockCode objects, initializes them with values and stores them into a vector STL container, sort is then called to sort the list and the output of the vector is shown before and after the sort.

/*
 * Test application to test sorting objects in a vector
 */
#include <string>
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
#include "StockCode.h"

using namespace std;

int main(int argc, char **argv)
{
vector cv;

    StockCode c1;
    c1.setCode("BHP");
    c1.setClose(38.50);
    StockCode c2;
    c2.setCode("ANZ");
    c2.setClose(34.0);
    StockCode c3;
    c3.setCode("RIO");
    c3.setClose(65);
    StockCode c4;
    c4.setCode("COH");
    c4.setClose(57.57);
    StockCode c5;
    c5.setCode("NMC");
    c5.setClose(11.98);

    cv.push_back(c1);
    cv.push_back(c2);
    cv.push_back(c3);
    cv.push_back(c4);
    cv.push_back(c5);

    int len = cv.size();
    for(int i=0; i<len; i++)
    {
        cout<<"Vector "<< cv.at(i).getCode()<< " = " << cv.at(i).getClose()<<endl;
    }

    sort(cv.begin(), cv.end() );

    for(int i=0; i<len; i++)
    {
        cout<<"sorted Vector "<< cv.at(i).getCode()<< " = " << cv.at(i).getClose()<<endl;
    }
    return 0;
}

Compiling

$g++ -g -Wall -c StockCode.cpp
$g++ -g -Wall -c main.cpp
$g++ -g -Wall main.o StockCode.o -o main

Program Output

$./main

Vector BHP = 38.5
Vector ANZ = 34
Vector RIO = 65
Vector COH = 57.57
Vector NMC = 11.98
sorted Vector NMC = 11.98
sorted Vector ANZ = 34
sorted Vector BHP = 38.5
sorted Vector COH = 57.57
sorted Vector RIO = 65

Future Enhancements

Sorting on Volume

I added an addition method to main.cpp to enable me to sort on highest volume, the function is as follows:

struct SortVol
{
 inline bool operator()(const StockCode &L, const StockCode &R)
 {
 return (L._vol < R._vol);
 }
};

At the bottom of the main loop I added some code to display the volume of each stock and during initialization I added code to set some values, then I added the call to std::sort() with the name of the sort operator. So the new main() look like so:

int main(int argc, char **argv)
{
vector<StockCode> cv;
StockCode c1;
 c1.setCode("BHP");
 c1.setClose(38.50);
 c1.setVol(1800);
 StockCode c2;
 c2.setCode("ANZ");
 c2.setClose(34.0);
 c2.setVol(1000);
 StockCode c3;
 c3.setCode("RIO");
 c3.setClose(65);
 c3.setVol(2000);
 StockCode c4;
 c4.setCode("COH");
 c4.setClose(57.57);
 c4.setVol(1500);
 StockCode c5;
 c5.setCode("NMC");
 c5.setClose(11.98);
 c5.setVol(1100);
cv.push_back(c1);
 cv.push_back(c2);
 cv.push_back(c3);
 cv.push_back(c4);
 cv.push_back(c5);
int len = cv.size();
 for(int i=0; i<len; i++)
 {
 cout<<"Vector "<< cv.at(i).getCode()<< " = " << cv.at(i).getClose()<< "VOL: "<<cv.at(i).getVol()<<endl;
 }
 sort(cv.begin(), cv.end() );
 for(int i=0; i<len; i++)
 {
 cout<<"sorted Vector "<< cv.at(i).getCode()<< " = " << cv.at(i).getClose()<< "VOL: "<<cv.at(i).getVol()<<endl;
 }
 sort(cv.begin(), cv.end(), SortVol() );
 for(int i=0; i<len; i++)
 {
 cout<<"Vol sorted Vector "<< cv.at(i).getCode()<< " = " << cv.at(i).getClose()<< "VOL: "<<cv.at(i).getVol()<<endl;
 }
return 0;
}

New ouput:

Vector BHP = 38.5  VOL: 1800
Vector ANZ = 34  VOL: 1000
Vector RIO = 65  VOL: 2000
Vector COH = 57.57  VOL: 1500
Vector NMC = 11.98  VOL: 1100
sorted Vector NMC = 11.98  VOL: 1100
sorted Vector ANZ = 34  VOL: 1000
sorted Vector BHP = 38.5  VOL: 1800
sorted Vector COH = 57.57  VOL: 1500
sorted Vector RIO = 65  VOL: 2000
Vol sorted Vector ANZ = 34  VOL: 1000
Vol sorted Vector NMC = 11.98  VOL: 1100
Vol sorted Vector COH = 57.57  VOL: 1500
Vol sorted Vector BHP = 38.5VOL: 1800
Vol sorted Vector RIO = 65  VOL: 2000

Sorting a vector of object pointers

After some experimentation I implemented a vector of pointers to my objects which is more in-line with how most of my code is built, as a result I added some new comparator functions for the sorting and I added a new constructor to the StockCode class, the code additions are as follows:

Inside the main() function:

vector<StockCode *> cv2;

cv2.push_back(new StockCode(“CSL”,76.55,76.60,76.55,76.65,23500));
cv2.push_back(new StockCode(“CBA”,56,57,56.10,57.5,355500));
cv2.push_back(new StockCode(“RIO”,72,72.60,71.55,73.65,3500));

len = cv2.size();
sort(cv2.begin(), cv2.end(), PtrSortClose() );
for(int i=0; i<len; i++)
{
cout<<“sorted Vector “<< cv2.at(i)->getCode()<< ” = ” << cv2.at(i)->getClose()<< ” VOL: “<<cv2.at(i)->getVol()<<endl;
}

The new function to compare the closing prices is:

struct PtrSortClose
{
inline bool operator()(const StockCode *L, const StockCode *R)
{
return (L->_close < R->_close);
}
};

So now I can create objects with “new” and save the pointers into the vector, then when sort is called, it passes the pointers to the compare function which use pointer logic.

Enjoy!

Advertisements