Home > Software design >  Performing calculations on elements, and retrieving index the index of an element in a vector
Performing calculations on elements, and retrieving index the index of an element in a vector

Time:10-25

Here I am trying to perform calculations and comparisons on elements in a vector, finding average, lower value, higher value and difference. I am also having issues printing the index of elements in a vector.

#include <iostream>
#include <string>
#include <vector>

enum class OrderBookType{bid, ask};

class OrderBookEntry{
public:
    double price;
    double amount;
    std::string timestamp;
    std::string product;
    OrderBookType orderType;
    
    double computeAveragePrice(std::vector<OrderBookEntry>& entries);
    
    OrderBookEntry(double _price,
                   double _amount,
                   std::string _timestamp,
                   std::string _product,
                   OrderBookType _orderType):
    price(_price),
    amount(_amount),
    timestamp(_timestamp),
    product(_product),
    orderType(_orderType) {
    }
        
//*    Other kinds of functions I hope to implement for this program. */
//    double computeLowPrice(std::vector<OrderBookEntry>& entries);
//    double computeHighPrice(std::vector<OrderBookEntry>& entries);
//    double computePriceSpread(std::vector<OrderBookEntry>& entries);

};

double OrderBookEntry::computeAveragePrice(std::vector<OrderBookEntry> &entries) {
        return 5.5; // Just trying to test a for an output here
}

int main() {
    // Declaring vector entries
    std::vector<OrderBookEntry> entries;
        
    // Adding entries into entries
    entries.push_back(OrderBookEntry{
        10000,
        0.001,
        "2020/03/17 17:01:24.88492",
        "BTC/USDT",
        OrderBookType::bid
    });
    entries.push_back(OrderBookEntry{
        20000,
        0.002,
        "2020/03/17 17:01:24.88492",
        "BTC/USDT",
        OrderBookType::bid
    });

    // Prints prices of all entries
    for (OrderBookEntry& entry : entries) {
        std::cout << "The price entry " << &entry << " is " << entry.price << std::endl;
    }
    
    std::cout << "The lower price is " << entries.computeAveragePrice() << std::endl;
        
    return 0;
}

There are three issues I am having here.

Firstly I am unable to call the computeAveragePrice() function to obtain the value that it is returning–in this case just a value of 5.5 for testing.

enter image description here

The image above is the error message for the line of code below.

std::cout << "The lower price is " << entries.computeAveragePrice() << std::endl;

Secondly, I am getting a weird value printed when I'm trying to print the index of elements in the vector.

enter image description here

The above is the output I got. I was expecting to get the respective indexes of the elements but got this instead. Here's the code that I used to iterate through the vector.

for (OrderBookEntry& entry : entries) {
    std::cout << "The price entry " << &entry << " is " << entry.price << std::endl;
}

Lastly, I could use some reference to any article that teaches me how to perform arithmetic on values within a vector such as averages, comparisons and finding differences.

Thank you in advance!

CodePudding user response:

computeAveragePrice is a member function in OrderBookEntry but entries is a std::vector<OrderBookEntry>, not a OrderBookEntry so it doesn't have such a member function.

I suggest that you move computeAveragePrice out of the class OrderBookEntry, which only holds information about one single OrderBookEntry. You could create another class to hold a collection of OrderBookEntry and put it there instead. This class can be a simple wrapper around a std::vector<OrderBookEntry>:

Example:

class OrderBook {   // A class to store a collection of OrderBookEntry:s
public:
    // A function to add an `OrderBookEntry`. You'll have to make this in
    // in the way you want. This is just an example:

    template<class... Args>
    decltype(auto) add(Args&&... args) {
        return entries.emplace_back(std::forward<Args>(args)...);
    }
    
    double computeAveragePrice() const;              // move it here

    // some member functions that just call the vector's member functions:
    size_t size() const { return entries.size(); }

    OrderBookEntry& operator[](size_t idx) { return entries[idx]; }
    const OrderBookEntry& operator[](size_t idx) const { return entries[idx]; }

    auto cbegin() const { return entries.cbegin(); }
    auto cend() const { return entries.cend(); }
    auto begin() const { return entries.cbegin(); }
    auto end() const { return entries.cend(); }    
    auto begin() { return entries.begin(); }
    auto end() { return entries.end(); }

private:
    std::vector<OrderBookEntry> entries;    // put the vector in here
};

double OrderBook::computeAveragePrice() const {
    // you need to #include <numeric> to use the accumulate function:
    if(entries.empty()) return 0.;
    return std::accumulate(entries.begin(), entries.end(), 0.,
                           [](double tot, const OrderBookEntry& e ) {
                               return tot   e.price;
                           }) / entries.size();
}

With that, your main would look like below:

int main() {
    OrderBook entries;            // use the new collection class
        
    // Adding entries into entries
    entries.add(                  // using the add() member function
        10000,
        0.001,
        "2020/03/17 17:01:24.88492",
        "BTC/USDT",
        OrderBookType::bid
    );

    entries.add(
        20000,
        0.002,
        "2020/03/17 17:01:24.88492",
        "BTC/USDT",
        OrderBookType::bid
    );

    // Prints prices of all entries
    for (OrderBookEntry& entry : entries) {
        std::cout << "The price entry " << &entry << " is " << entry.price << '\n';
    }
    
    std::cout << "The average price is " << entries.computeAveragePrice() << '\n';
        
    return 0;
}

Note though that printing &entry will print the address of the OrderBookEntry. If you want to print something meaningful you need to add an overload for operator<< that takes an OrderBookEntry as input.

Example:

std::ostream& operator<<(std::ostream& os, const OrderBookEntry& e) {
    return os << e.product;
}

You could then print the entry, but not by taking its address:

for (const auto& entry : entries) {
    std::cout << "The price entry " << entry << " is " << entry.price << '\n';
    //                                 ^^^^^
}
  • Related