A frequency function using template - c++

I am trying to write a template-based function frequency that will return the count of the occurrences of an item in an array of items.
So far I have
#include <iostream>
using namespace std;
template <class T>
T frequency(T array[], T arraySize, T item) {
int count = 0;
for (int i = 0; i < arraySize; i++) {
if (array[i] == item) {
count++;
}
}
return count;
}
int main() {
// Testing template with int
int intArray[10] = { 1, 2, 3, 3, 14, 3, 2, 7, 99, 2 };
cout << "{ ";
for (int i = 0; i < 10; i++) {
cout << intArray[i] << " ";
}
cout << "}" << endl;
cout << "Frequency of 3: " << frequency(intArray, 10, 3) << endl;
cout << "Frequency of 2: " << frequency(intArray, 10, 2) << endl;
cout << "Frequency of 99: " << frequency(intArray, 10, 99) << endl;
// Testing template with double
double doubleArray[10] = { 1.5, 2.2, 99.4, 132.11, 1.5, 2.22, 1.515, 66.2, 51.8, 34.0 };
cout << "{ ";
for (int j = 0; j < 10; j++) {
cout << doubleArray[j] << " ";
}
cout << "}" << endl;
cout << "Frequency of 1.5: " << frequency(doubleArray, 10, 1.5) << endl;
cout << "Frequency of 2.2: " << frequency(doubleArray, 10, 2.2) << endl;
cout << "Frequency of 100.1: " << frequency(doubleArray, 10, 100.1) << endl;
return 0;
}
however, I get an error of "no matching function for call to 'frequency(double [10], int, double)'" towards when I try to print out the frequency of the doubles. I am unsure what I am doing wrong.
Thank you for any help!

frequency takes parameters of element of array and arraySize with the same type, i.e. T. But you pass arguments of that with different types, i.e. double vs int. Then the type deduction fails because T can't be deduced (determined).
According to your implemantaion, the type arraySize seems fixed, you can just declare it as std::size_t or int. And same for the return type. Their types won't change then shouldn't be declared with template parameters.
template <class T>
int frequency(T array[], std::size_t arraySize, T item) {
int count = 0;
for (std::size_t i = 0; i < arraySize; i++) {
if (array[i] == item) {
count++;
}
}
return count;
}

You should not use your template parameter with arraySize. Because you compare it with i, int i = 0; i < arraySize;. And the return type should not be T too because a double is not accurate don't use it like counter. Plus you do return count and you write int count = 0;
template <class T>
int frequency(T const array[], int arraySize, T const &item);
Be aware that the standard library has a template function to this purpose. In a production code, you should use std::count_if().
int count = std::count_if(intArray.begin(), intArray.end(), [](int i){ return i == 42; });

You can crate frequency as, so that it can be used with other containers.
#include <iostream>
#include <vector>
using namespace std;
template <class outputIterator,class T>
int frequency(outputIterator b,outputIterator e ,const T& v) {
int count = 0;
while(b != e)
{
if(*b == v)
{
count++;
}
b++;
}
return count;
}
int main ()
{
std::vector<int> first={1,1,2,3,4,5,5};
std::cout<<frequency(first.begin(),first.end(),1)<<std::endl;
int arr[]={1,2,3,5,5,5};
std::cout<<frequency(std::begin(arr),std::end(arr),5)<<std::endl;
return 0;
}

Related

terminate called after throwing an instance of 'std::out_of_range' in C++

I am new to C++ and learning data structures. In the below code I am getting an "out of range warning", and do not understand what I am doing wrong.
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> numbers{100,-1,2,4,55,78,3};
int temp {};
int pass {};
pass = numbers.size();
for(int i {0} ;i<pass-1;i++){
for(int j {0} ; j<pass-1-i ; j++){
if(numbers.at(j) > numbers.at(j+1)){
temp = numbers.at(j);
numbers.at(j)=numbers.at(j+1);
numbers.at(j+1)=temp;
}
}
}
cout << numbers.at(0) << endl;
cout << numbers.at(1) << endl;
cout << numbers.at(2) << endl;
cout << numbers.at(3) << endl;
cout << numbers.at(4) << endl;
cout << numbers.at(5) << endl;
cout << numbers.at(6) << endl;
cout << numbers.at(7) << endl;
cout << numbers.at(8) << endl;
return 0;
}
It seems like you may not understand how std::vectors work.
You have only declared 7 elements in your vector which means you can only go up to the index 6. This is because std::vector's indices start at 0. This is true for std::array as well.
vector<int> numbers{100,-1,2,4,55,78,3};
However, in your code you have put these two statements:
cout << numbers.at(7) << endl;
cout << numbers.at(8) << endl;
which doesn't work because like I mentioned you can only go up to index 6.
You should also consider using a for loop like the comments mention above. It is more simple to use and is less work.
For example eith a for loop:
#include <iostream>
#include <vector>
int main()
{
std::vector<int> numbers{ 100,-1,2,4,55,78,3 };
int temp{};
int pass{};
pass = numbers.size();
for (int i{ 0 }; i < pass - 1; i++) {
for (int j{ 0 }; j < pass - 1 - i; j++) {
if (numbers.at(j) > numbers.at(j + 1)) {
temp = numbers.at(j);
numbers.at(j) = numbers.at(j + 1);
numbers.at(j + 1) = temp;
}
}
}
std::cout << "v = { ";
for (int i = 0; i < numbers.size(); i++) {
std::cout << numbers.at(i) << ", ";
}
std::cout << "}; \n";
return 0;
}
Output:
v = { -1, 2, 3, 4, 55, 78, 100, };

How do I get my templated bubbleSort() function to display a sorted vector?

The bubblesort() function I have for my vector, fails to return a sorted version of the vector; there are times where if I do compile and execute the code in VS it gives me a runtime error when the function is called:
Expression: vector subscript out of range
I've double checked the range, and it seems alright to me; I'm unsure what the issue is: I did make sure the vector was passed by reference.
#include <iostream>
#include <algorithm>
#include <vector>
#include <ctime>
template <class T>
void fillVector(std::vector<T>& vobj, int n);
template <class T>
void displayVector(std::vector<T>& vobj);
template <class T>
void bubbleSort(std::vector<T>& vobj);
template <class T>
void fillVector(std::vector<T>& vobj, int n)
{
srand((unsigned int)time(NULL));
for (int i=0; i<n; ++i)
{
vobj.push_back(rand());
}
}
template <class T>
void displayVector(std::vector<T>& vobj)
{
const unsigned displayLimit = 10;
if (vobj.size()>displayLimit)
{
for (unsigned i=0; i<displayLimit; ++i)
{
std::cout << " " << vobj[i];
}
std::cout << " ..." << std::endl;
}
else
{
for (unsigned i = 0; i < vobj.size(); ++i)
{
std::cout << vobj[i] << " ";
}
}
}
template <class T>
void bubbleSort(std::vector<T>& vobj)
{
bool swapped = true;
for (unsigned i=0; swapped && i<vobj.size()-1; ++i)
{
swapped = false;
for (unsigned j=0; j<vobj.size()-1-i; ++j)
{
if (vobj[j]>vobj[j++])
{
swapped = true;
std::swap(vobj[j],vobj[j++]);
}
}
}
}
int main()
{
std::vector<int> vobj;
std::cout << "Enter # of objects you'd like to store in the vector object: ";
int n;
std::cin >> n;
std::cout << "\n*** Calling fillVector(...) ***" << std::endl;
fillVector(vobj,n);
std::cout << "\n*** Calling displayVector(...) ***" << std::endl;
std::cout << "Vector object contains " << n << " value(s) which are" << std::endl;
displayVector(vobj);
std::cout << "\n*** Calling bubbleSort(...) ***" << std::endl;
bubbleSort(vobj);
displayVector(vobj);
}
In your bubbleSort routine you increment the j variable 3 times! Don't you think that is twice too many?
if (vobj[j]>vobj[j++])
should be
if (vobj[j]>vobj[j+1])
and
std::swap(vobj[j],vobj[j++]);
should be
std::swap(vobj[j],vobj[j+1]);
Incrementing a variable is not the same as adding one to it.

c++ How can I count the unique elements in a vector?

I have this c++ code:
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <cstdlib>
#include <cmath>
using namespace std;
struct szemelyadat {
string vnev;
string knev;
int szulev;
int szulhonap;
int szulnap;
};
int vfmeret(const char* fajlnev)
{
string temp;
int merettemp = 0;
ifstream meretBE(fajlnev);
while (!meretBE.eof()) {
meretBE >> temp;
merettemp++;
}
meretBE.close();
return merettemp;
}
void vfbeolv(szemelyadat* vek, int elemszam, const char* fajlnev)
{
int i, j;
string stemp, stempresz;
ifstream adatBE(fajlnev);
for (i = 0; i < elemszam; i++) {
adatBE >> stemp;
istringstream sorfolyam(stemp);
j = 0;
while (getline(sorfolyam, stempresz, ';')) {
if (j == 0)
vek[i].vnev = stempresz;
if (j == 1)
vek[i].knev = stempresz;
if (j == 2)
vek[i].szulev = atoi(stempresz.c_str());
if (j == 3)
vek[i].szulhonap = atoi(stempresz.c_str());
if (j == 4)
vek[i].szulnap = atoi(stempresz.c_str());
j++;
}
}
adatBE.close();
}
void vfkiir(szemelyadat* vek, int elemszam)
{
cout << "Vezeteknev "
<< "Keresztnev "
<< "Szuletesiev "
<< "Szuletesihonap "
<< "Szuletesinap " << endl;
for (int i = 0; i < elemszam; i++)
cout << vek[i].vnev << " " << vek[i].knev << " " << vek[i].szulev << ". " << vek[i].szulhonap << ". " << vek[i].szulnap << endl;
}
int main()
{
int n = vfmeret("szuletesi_nevlista.txt");
szemelyadat* vektor;
vektor = new szemelyadat[n];
vfbeolv(vektor, n, "szuletesi_nevlista.txt");
vfkiir(vektor, n);
delete[] vektor;
cin.get();
cin.get();
return 0;
}
I need to cout the count of the unique elements which is in the "vek[i].szulev"
please help me somebody, how can I do this ?
Here's one simple way to count the unique values in a vector:
using Size = ptrdiff_t;
template< class Item >
auto n_unique_items( vector<Item> const& v )
-> Size
{ return set<Item>{ v.begin(), v.end() }.size(); }
Since you insisted on using "your code", you can still utilize std::set to do the counting.
It all boils down to this:
#include <set>
#include <iostream>
void count_items(szemelyadat* vek, int elemszam)
{
std::set<int> counter;
for (int i = 0; i < elemszam; i++)
counter.insert(vek[i].szulev);
std::cout << "The number of unique items is " << counter.size();
}
If you call the count_items once you fill your "vektor", then this will give you then unique number of szulev in the vektor.

C++ Hamming Function

This program is supposed to create three arrays of class object My_array. The first array is filled with random numbers. The second array is an exact copy of the first. The third array is entered by the user. The program checks to make sure that the first two arrays indeed equal each other and then it check to the hamming distance of the first and third array. The professor defines the hamming distance as each part off the array that is different.
My problem has been getting hamming to work. I actually have a hard time with operating overloading so I am surprised that works (well I have no errors showing in VS Studio) but not the hamming part. Any help would be appreciated. There are three files in order: main.cpp, my_array.cpp, and my_array.h. Function definitions and declarations were provided by professor. I am required to insert how each function operates.
#include "my_array.h"
#include <iostream>
using namespace std;
int main()
{
int size;
cout << "How big of an array shall we work with? ";
cin >> size;
My_array a(size);
My_array b(size);
My_array c(size);
a.randomize(100);
b = a;
c.input();
cout << a << endl;
cout << b << endl;
cout << c << endl;
cout << "a != b: " << (a != b) << endl;
cout << "a == b: " << (a == b) << endl;
cout << "The hamming distance is: " << a.hamming(c);
return 0;
}
#include "my_array.h"
#include <iostream>
using namespace std;
#include <stdlib.h>
#include <time.h>
// Constructor
My_array::My_array(int the_size)
{
array = NULL;
size = 0;
resize(the_size);
}
// Destructor.
My_array::~My_array()
{
empty();
}
// Copy constructor
My_array::My_array(My_array &data)
: size(data.size)
{
array = new int[size];
for (int i = 0; i<size; i++)
array[i] = data.array[i];
}
// Overloaded assignment operator.
My_array &My_array::operator=(My_array &data)
{
if (this != &data) {
resize(data.size);
for (int i = 0; i<size; i++)
array[i] = data.array[i];
}
else
cout << "Attempt to copy an object on itself. "
<< "Operation ignored." << endl;
return *this;
}
void My_array::input()
{
int j;
cout << "Please enter " << size << " numbers.\n";
for (int i = 0; i < size; i++)
{
cout << "Number " << i + 1 << ": ";
cin >> j;
array[i] = j;
}
}
void My_array::randomize(int limit)
{
srand(time(NULL));
for (int i = 0; i < size; i++)
array[i] = rand() % limit + 1;
}
bool My_array::operator ==(My_array &data)
{
if(this->size != data.size)
return false;
for (int i = 0; i <size; i++)
{
if (*this[i].array != data.array[i])
return false;
}
return true;
}
bool My_array::operator !=(My_array &data)
{
if (*this == data)
return false;
return true;
}
int My_array::hamming(My_array &data)
{
int ham = 0;
for (int i = 0; i < size; i++)
if (*this[i].array != data[i].array)
ham++;
return ham;
}
// This function will empty the target object
void My_array::empty()
{
if (size != 0 && array != NULL) {
size = 0;
delete[] array;
}
}
// Resize the array.
void My_array::resize(int the_size)
{
if (size >= 0) {
empty();
if (the_size != 0) {
size = the_size;
array = new int[size];
}
}
else
cout << "Resize attepmted with a negative size. "
<< "Operation ignored." << endl;
}
// Access an element of the array.
int &My_array::operator[](int index)
{
if (index < size)
return array[index];
else {
cerr << "Illegal access to an element of the array." << endl
<< "The size of the array was " << size
<< " and the index was " << index << endl;
exit(1);
}
}
// Accessor
int My_array::get_size()
{
return size;
}
void My_array::output()
{
cout << "The array of size " << size
<< " contains the elements:" << endl;
for (int i = 0; i<size; i++)
cout << array[i] << ' ';
cout << endl;
}
//overloading the << operator.
ostream &operator<<(ostream &out, My_array &data)
{
out << "The array of size " << data.size
<< " contains the elements:" << endl;
for (int i = 0; i<data.size; i++)
out << data.array[i] << ' ';
out << endl;
return out;
}
#ifndef MY_ARRAY_H
#define MY_ARRAY_H
#include <iostream>
using namespace std;
class My_array {
protected:
int size;
int *array;
public:
// Constructor
My_array(int the_size = 0);
// Destructor
~My_array();
// Copy constructor
My_array(My_array &data);
// Assignment operator
My_array &operator=(My_array &data);
void input();
void randomize(int limit);
bool operator ==(My_array &data);
bool operator !=(My_array &data);
int hamming(My_array &data);
// Deletes the array
void empty();
// Resize the array.
void resize(int the_size = 0);
// Access an element of the array.
int &operator[](int index);
// Returns the size of the array.
int get_size();
// Output the elements of the array.
void output();
friend ostream &operator<<(ostream &out, My_array &data);
};
#endif
This:
*this[i].array != data[i].array
should be this:
array[i] != data.array[i]
or this:
array[i] != data[i]
The *this is unnecessary, and data[i] is a reference to an int (the same one you get by calling data.array[i], thanks to your operator[]), and an int has no member called "array".

Looping through array inside of stuct

I'm a student, learning pointers for the first time. My assignment doesn't allow the use of string classes and should be using pointer notation to access all elements within an array (no []).
Why am I not able to access an array inside of a struct via pointers? Is my syntax off?
#include <iostream>
using namespace std;
struct person
{
int favNums[4];
};
// Notation works here
void strCopy(char *from, char *to, int len)
{
for (int i = 0; i < len; i++)
{
*(to + i) = *(from + i);
}
}
// But doesn't work here
void sayNumsPointerNotation(person peep)
{
for (int i = 0; i < 4; i++)
{
//cout << peep.*(favNums + i) << endl;
}
}
// Would like to accomplish this.
void sayNums(person peep)
{
for (int i = 0; i < 4; i++)
{
cout << peep.favNums[i] << endl;
}
}
int main()
{
// Array outside of struct
char from[5] = "Word";
char to[5];
strCopy(from, to, 5);
cout << to << endl << endl;
// Array inside of struct non-pointer
person peep;
peep.favNums[0] = 0;
peep.favNums[1] = 1;
peep.favNums[2] = 2;
peep.favNums[3] = 3;
sayNums(peep);
cout << endl;
sayNumsPointerNotation(peep);
cout << endl;
}
This should work, hopefully you understand what was wrong.
#include <iostream>
using namespace std;
struct person
{
int favNums[4];
};
// Notation works here
void strCopy(char *from, char *to, int len)
{
for (int i = 0; i < len; i++)
{
*(to + i) = *(from + i);
}
}
// But doesn't work here (now it works)
void sayNumsPointerNotation(person* peep)
{
for (int i = 0; i < 4; i++)
{
cout << *(peep->favNums + i) << endl;
}
}
// Would like to accomplish this.
void sayNums(person peep)
{
for (int i = 0; i < 4; i++)
{
cout << peep.favNums[i] << endl;
}
}
int main()
{
// Array outside of struct
char from[5] = "Word";
char to[5];
strCopy(from, to, 5);
cout << to << endl << endl;
// Array inside of struct non-pointer
person peep;
peep.favNums[0] = 0;
peep.favNums[1] = 1;
peep.favNums[2] = 2;
peep.favNums[3] = 3;
sayNums(peep);
cout << endl;
sayNumsPointerNotation(&peep);
cout << endl;
}
Instead of
cout << peep.*(favNums + i) << endl;
Try this:
cout << *(peep.favNums + i) << endl;
Use
cout << *(peep.favNums + i) << endl;
.*, on the other hand, is a "member pointer", and means something different.