I am trying to calculate the average based on input from a vector. How can I distinguish to the caller of my function that an empty vector was provided versus a vector with just 0 values? Can I do both in one function or do I need 2 functions?
CodePudding user response:
You could return a std::optional<T>
to signal that the your function may not return an actual value in the case of an empty vector.
std::optional<double> avg(const std::vector<int>& n) {
if(n.size() < 1)
return std::nullopt;
return std::accumulate(n.begin(), n.end(),0) / static_cast<float>(n.size());
}
int main() {
std::vector<int> numbers;
auto average = avg(numbers);
if(average) {
std::cout << "the average is" << average.value() << std::endl;
}else {
std::cout << "Could not compute average!" << std::endl;
}
}
CodePudding user response:
You can use templates to do what you want as follows:
#include <iostream>
#include <vector>
using namespace std;
template<typename T>
T average(const std::vector<T> &vec)
{
if(vec.empty())
{
throw std::runtime_error("Vector passed is empty");//throw if the vector is empty because we don't want to operate on an empty vector
}
T sum{};
for(T elem: vec)
{
sum = elem;
}
return sum/vec.size();
}
int main()
{
std::vector<float> myvec1{1,2,3.4};
std::cout<<"average is: "<<average(myvec1);
std::vector<int> myvec2;
average(myvec2);//this will (terminate)print "vector passed is empty"
return 0;
}
CodePudding user response:
An empty vector has no average, it is undefined, just like 0/0 is undefined. It is the caller's responsibility not to calculate 0/0, and it is the caller's responsibility not to calculate an empty vector average.
There is no good way to deal nicely with undefined calculations such as 0/0 or empty vector average in C . The usual approach is to let the users sort it out. The caller should check the length of the vector before trying to call your function. Otherwise the callee would need to check the length, return a special value, and then the caller would need to check that the returned value is special. This is unneeded complexity. If the user needs to check every call, let them check every call before making it, not after. Just add an assert
to help debugging.
Alternative approaches would be to return a NaN or to throw an exception. This allows the users to validate calculation results with whatever granularity they want.