#include "Array.hpp" #include #include ///////////////////////////////////////////////// // This file contains all function definitions // // - All function declarations are in // // the file Array.hpp // ///////////////////////////////////////////////// // This example extends the previous Array project by // introducing operator overloading. Refer to the previous // project for a discussion of dynamic memory allocation, // initialization, clean-up, resetting entries, and the // other array operations. // // The focus here is on overloading the stream insertion // operator <<. This allows us to write // // std::cout << array; // // instead of // // std::cout << to_string( array ); // // The expression std::cout << array results in a call to // // operator<<( std::cout, array ) // // The overloaded operator behaves in the same general way // as the << operator used to output built-in types. ////////////////////////////////////// // Initialization and modification // ////////////////////////////////////// // Initialize 'array' with the given capacity and initial // value. // // If 'array' already refers to a dynamically allocated // array, first deallocate that array. // // Before calling this function for the first time, the // Array object must have been initialized, for example: // // Array array{}; // // so that array.array_ is initially nullptr. void array_init( Array &array, std::size_t const capacity, double const initial_value ) { if ( array.array_ != nullptr ) { delete[] array.array_; array.array_ = nullptr; array.capacity_ = 0; } array.capacity_ = capacity; array.array_ = new double[array.capacity_]; for ( std::size_t k{0}; k < array.capacity_; ++k ) { array.array_[k] = initial_value; } } // Deallocate the dynamically allocated array and reset the // member variables. // // In C++, it is acceptable to call delete[] on nullptr. void array_clean_up( Array &array ) { delete[] array.array_; array.array_ = nullptr; array.capacity_ = 0; } // Reset every entry in 'array' to 'new_value'. // // If there is no dynamically allocated array, there is // nothing to reset. void array_reset( Array &array, double const new_value ) { if ( array.array_ == nullptr ) { return; } for ( std::size_t k{0}; k < array.capacity_; ++k ) { array.array_[k] = new_value; } } ////////////////////// // Array operations // ////////////////////// // Calculate the average of the entries in 'array'. // // Return 0.0 if there are no entries. double average( Array const &array ) { if ( (array.array_ == nullptr) || (array.capacity_ == 0) ) { return 0.0; } double sum{ 0.0 }; for ( std::size_t k{0}; k < array.capacity_; ++k ) { sum += array.array_[k]; } return sum/array.capacity_; } // Determine whether the entries in 'array' are sorted from // least to greatest. // // If the array is sorted, return its capacity. Otherwise, // return the index of the first entry that is less than the // entry immediately before it. std::size_t is_sorted( Array const &array ) { if ( (array.array_ == nullptr) || (array.capacity_ == 0) ) { return 0; } for ( std::size_t k{1}; k < array.capacity_; ++k ) { if ( array.array_[k] < array.array_[k - 1] ) { return k; } } return array.capacity_; } // Return the indices of the maximum and minimum entries. // // The first member of the returned Pair is the index of // the maximum entry and the second is the index of the // minimum entry. Pair maxmin( Array const &array ) { assert( array.capacity_ > 0 ); assert( array.array_ != nullptr ); std::size_t imax{ 0 }; std::size_t imin{ 0 }; for ( std::size_t k{1}; k < array.capacity_; ++k ) { if ( array.array_[k] > array.array_[imax] ) { imax = k; } else if ( array.array_[k] < array.array_[imin] ) { imin = k; } } return Pair{ imax, imin }; } /////////////////////////// // Output and conversion // /////////////////////////// // Return a comma-separated string containing the entries // in 'array' enclosed in braces. // // This function is essentially unchanged from the previous // Array project. std::string to_string( Array const &array ) { if ( (array.array_ == nullptr) || (array.capacity_ == 0) ) { return "{}"; } std::string result{ "{" + std::to_string( array.array_[0] ) }; for ( std::size_t k{1}; k < array.capacity_; ++k ) { result += ", " + std::to_string( array.array_[k] ); } return result + "}"; } // Insert a representation of 'array' into an output stream. // // Overloading << allows us to write // // std::cout << array; // // rather than explicitly converting the Array to a string. // // The output stream is returned by reference so that // insertions can be chained: // // std::cout << array << std::endl; std::ostream &operator<<( std::ostream &out, Array const &array ) { if ( (array.array_ == nullptr) || (array.capacity_ == 0) ) { out << "{}"; } else { out << "{" << array.array_[0]; for ( std::size_t k{1}; k < array.capacity_; ++k ) { out << ", " << array.array_[k]; } out << "}"; } return out; }