bubbleSort vector template class - c++

I am working on an assignment where I need to sort vectors using a template so I can pass different data types to my class and sort them not using std::sort. so I am very stuck so far,
I don't really get how to use the template to accept my input from main().
PS. this is for Homework, that is why i am not using arrays and the sort function.
Here is my code so far.
using namespace std;
template <class T>
class SortableVector
{
private:
T a =0;
public:
SortableVector(); // constructor
~SortableVector(); // destructor
void bubble_sort(vector<T>, a)
{
for (int i = a.size(); i > 0;i--)
{
for (int j = 0, k = 1; k < i;j++, k++)
{
if (a[j] > a[k])
{
int swap = a[j];
a[j] = a[k];
a[k] = swap;
}
}
}
}
};
And my main is looking like this:
int main()
{
int alen, val;
vector<int> a;
cout << "Enter the number of elements : ";
cin >> alen;
for(int i = 0; i < alen; i++)
{
cin >> val;
a.push_back(val);
}
SortableVector::bubble_sort(a);
cout << "List of sorted elements: " << endl;
for(int i = 0; i < alen; i++)
{
cout << a[i] << " ";
}
cout << endl;
}
Any help will be welcome :)
Ok...
So I made some changes thanks to Namfuak
now I have a totally different problem
command line output;
Hw8_3.cpp:(.text+0x11): undefined reference to SortableVector<int>::SortableVector()'
Hw8_3.cpp:(.text+0x138): undefined reference toSortableVector::~SortableVector()'
Hw8_3.cpp:(.text+0x170): undefined reference to `SortableVector::~SortableVector()'
collect2: error: ld returned 1 exit status
I am really not getting this one. This is the code I have so far;
template <class T>
class SortableVector
{
private:
vector<T> vec;
public:
SortableVector(); // constructor
~SortableVector(); // destructor
void push_back(T push) {vec.push_back(push);}
T bubble_sort(vector<T> a);
};
template <class T>
T SortableVector<T>::bubble_sort(vector<T> a)
{
for (int i = a.size(); i > 0;i--)
{
for (int j = 0, k = 1; k < i;j++, k++)
{
if (a[j] > a[k])
{
T swap = vec[j];
vec[j] = vec[k];
vec[k] = swap;
}
}
}return 0;
}
And my main() ;
{
SortableVector<int> L;
int alen, val;
vector<int> a;
cout << "Enter the number of elements : ";
cin >> alen;
for(int i = 0; i < alen; i++)
{
cin >> val;
L.push_back(val);
}
L.SortableVector<int>::bubble_sort(a);
cout << "List of sorted elements: " << endl;
for(int i = 0; i < alen; i++)
{
cout << a[i] << " ";
}
}
Any other Idea? I am really lost here...

If you are using a template, your swap variable needs to be of that template type. IE:
T swap = a[j];
EDIT: Looking through, I don't think you are using the correct design. Your SortableVector should probably have a vector<T> as a member, IE:
template <class T>
class SortableVector
{
private:
std::vector<T> vec;
public:
SortableVector();
~SortableVector();
void push_back(T push) {vec.push_back(push);}
void bubble_sort() //You could also return a sorted version of vec
}
Otherwise, there is no reason for a SortableVector class, you can just take the function and put it in the global space as a templated function.

You need to provide definitions for the constructor and destructor.
If you don't declare them, the compiler will automatically create them for you. The constructor will call the default constructor on each element (and the base class if there is one) and the destructor will call the destructor of each class element.
However, since you have declared them, you also need to provide definitions.

The error is pretty clear:
Hw8_3.cpp:(.text+0x11): undefined reference to SortableVector<int>::SortableVector()'
Hw8_3.cpp:(.text+0x138): undefined reference toSortableVector::~SortableVector()' Hw8_3.cpp:(.text+0x170): undefined reference to `SortableVector::~SortableVector()' collect2: error: ld returned 1 exit status
You're not defining the constructor and the destructor...
SortableVector() { }
~SortableVector() { }
Or if you want:
template<class T>
SortableVector::SortableVector()
{
...
}
template<class T>
SortableVector::~SortableVector()
{
...
}
Also, this line L.SortableVector<int>::bubble_sort(a); why not just L.buble_sort(a);
Also, here:
template <class T>
T SortableVector<T>::bubble_sort(vector<T> a)
Did you know you're passing a copy of a instead of a reference? This means you any modifications to that vector will not be live in vector<int> a; in your main function or whatever function you're calling it from:
template <class T>
T SortableVector<T>::bubble_sort(vector<T>& a)
Notice the &
This:
vec[j] = vec[k];
vec[k] = swap;
Did you mean a?
This class member is useless:
vector<T> vec;
I'd suggest providing functions for appending to that member instead and remove the vector<T>& a parameter from the bubble_sort function in the class, then instead of making another vector in your main or w/e, use push on your SortableVector class instance.

#include <vector>
#include <algorithm> //This library give us some handy function swap
#include <iostream>
#include <random>
// This is a function to create random number between 1 and 10
static int random_int(){
static std::random_device rd;
static std::mt19937 prng{ rd() };
static std::uniform_int_distribution<> d10{1, 10};
return d10(prng);
}
template<class T>
class SortableVector{
//By default element define in classes are private so no need to specify
std::vector<T> v_;
public:
//You dont need to specify constructor
//Also, you dont need to specify destructor.
//This is because the default constructor and destructor are ok.
//The default constructor use item to item copy. In this case it's gonna copy the vector val_ wich is ok.
//For the destructor, we don't need to do anything
//Usually you use const T& to avoid copy
void push_back(const T& val){
v_.push_back(val);
}
//Here i don't really know what u want to do.
//Do you want to sort your inner vector and return it ?
//Or do you want to make a copy and return it ?
//Let's make a static method so it helps us covering both cases.
//This method is static so it can be used outside of an instance.
//It's like a function that is define inside the scope of this class.
static void bubble_sort(std::vector<T>& v){
//Using the correct type is always better.
//In this case it's the type that define the size of this particular vector is :
size_t size = v.size();//Or with c++11 : auto size = v.size()
bool change;
do{
change = false;
for(int i = 0; i < size - 1; ++i){
if(v[i-1] > v[i]){
std::swap(v[i-1],v[i]);
change = true;
}
}
}
while(change);
}
//This is the method version using the static one.
std::vector<T>& bubble_sort(){
bubble_sort(v_);
return v_;
}
};
int main() {
SortableVector<int> ss;
for(int k = 0; k < 10; ++k){
ss.push_back(random_int());
}
for(auto& elem : ss.bubble_sort()){//C++ 11 foreach
std::cout << elem << std::endl;
}
}

Related

class template for handling dynamic arrays of objects - C++

I'm just getting started with the use of templates and class templates in university, and honestly it's getting a little confusing for me.
I have to create a Vector class (custom class not std::vector) that can take an array of objects and handle operations on that array, and also automatically increase the size of the array by *2 which you can see in my addData method in Vector. My Registration class creates an array of Vector (class) by taking inputs from a file, passing them into Results so that they read in the data from the file as required.
My Vector class is meant to set the data from Registration into results and increase the size of the array if needed. How would I have to make the input and output operators in my Vector class in order to do this, similarly to how I've done it for my Registration class as it uses file input?
Vector.h:
#ifndef VECTOR_H
#define VECTOR_H
#include <iostream>
#include <string>
#include <sstream>
template <class T>
class Vector
{
public:
Vector(int arraysize1): arraysize(arraysize1), data(new T[arraysize1]){};
Vector<T> *addData(T dataToAdd){
Vector<T> *temp = new Vector<T> (this->arraysize);
temp->data = this->data;
Vector<T> *newData = new Vector<T> (this->arraysize*2);
for (int x = 0; this->arraysize; x++){
if(x < this->arraysize){
newData->setData(temp->getData()[x],x);
}
else
newData->setData(dataToAdd, x);
}
return newData;
};
void initArray(){
for(int x = 0; x<this->arraysize; x++){
this->setData(x ,x);
}
};
void printArray(){
std::ostringstream oss;
for (int i = 0; i < this->arraysize; ++i){
oss << this->data[i] + " ";
}
};
T* getData(){
return this->data;
};
int getSize(){
return this->arraysize;
}
void setData(T data, int index){
this->getData()[index] = data;
}
private:
int arraysize;
T* data;
};
#endif // VECTOR_H
Registration.h(class that makes array of 'results' which is another class)
This is how my array of objects was declared before in my header file, and now I must use my vector class so I change the declaration:
Vector<Result> results;
Registration.cpp:
Here I use input stream and osteam operator overloading to read from the file. Now that Im using my vector class for Results, what syntax do I need to change?
void Registration::readFile(istream &input){
long studentid1;
unsigned semester1;
input >> studentid1 >> semester1 >> count;
input.ignore(100, '\n');
SetStudentID(studentid1);
SetSemester(semester1);
for(unsigned i = 0; i < count; i++)
input >> results[i];
}
void Registration::writeFile(ostream & os) const{
os << "Student ID: " << GetStudentID() << '\n'
<< "Semester: " << GetSemester() << '\n';
for(unsigned i = 0; i < count; i++)
os << results[i] << '\n';
}
If my Result class is needed and any other details do let me know.

What is right way to access elements of std::array by passing as a pointer to function in C++?

The code snippet is as follows. The error is in foo function for the cout line:
typedef struct Datatype {
int first;
int second;
} Datatype;
void foo(std::array<Datatype, 100>* integerarray){
cout << *integerarray[0].first << endl; //ERROR: has no member first
}
void main() {
std::array<Datatype, 100> newarray;
for(int i=0; i<100; i++)
newarray[i] = i;
}
foo(&newarray);
}
Because of operator precedence, *integerarray[0].first is translated as *(integerarray[0].first), which is not what you want. You need to use (*integerarray)[0].first.
cout << (*integerarray)[0].first << endl;
You can make your life simpler by passing a reference.
void foo(std::array<Datatype, 100>& integerarray){
cout << integerarray[0].first << endl;
}
Also, you don't need to use typedef struct DataType { ... } DataType; in C++. You can use just struct DataType { ... };
newarray[i] = i;
In this line you have missed adding value to structure variables.
Also you have passed array as a reference to function. Removing it and passing just the name of array will pass base address of array.
I am adding following code for your reference:
#include<iostream>
#include <array>
struct Datatype{
int first;
int second;
}
typedef Datatype varInts;
void display(std::array<varInts,20> &dummy)
{
int b =5;
for(int i=0; i<20; i++)
{
dummy[i].first =b++;
dummy[i].second = b+5; //Give any logic you wish.just adding different values;
b++;
}
}
int main()
{
std::array<varInts,20> data;
int a =1;
for(int i=0;i<20;i++)
{
data[i].first = a++;
data[i].second = a+5;
a++; //Just adding values for example
}
display(data);
return 0;
}
It runs without error.Hope it helps!!

Template T Class Array

I have a (what should be simple) assignment in my C++ class.
Here is the assignment:
Create a class template that contains two private data members: T * array and int size. The class uses a constructor to allocate the array based on the size entered. There is member function that allows the user to fill in the array based on the size. In addition, there is a member function that sorts the array and displays the sorted elements. Use the destructor to delete the array. Develop the main( ) to create two objects to call member functions. As a result, the first object will hold its array of double type, and the other will hold its array of the int type.
Here is what I have came up with but coming up with an error of "Allocation of incomplete type 'T'":
#include <iostream>
#include <new>
#include <vector>
using namespace std;
template <class T>
class DynArray {
protected:
int size;
T ** DynamicArray = new T[size];
public:
DynArray(){
void CreateArray(){
cout << "Enter size of Array: ";
cin >> size;
for (int i = 0; i < size; ++i){
DynamicArray[i] = new T();
}
for (int i = 0; i<size; i++) {
cout << "Element " << i << ": ";
cin >> DynamicArray[i];}
}
//Sort Array
void Sort(T a[], int size)
{
int idx, pass;
for (pass=0; pass<size; ++pass){
for (idx=0; idx<size-1; ++idx){
if (a[idx] > a[idx+1])
swap(a[idx], a[idx+1]);}
}
for (int i=0; i<size; ++i) {
for (idx = 0; idx<size-1; ++idx) {
cout << a[idx] << " ";
}
}
}
void DeleteArray(){
for (int i = 0; i < size; ++i){
delete DynamicArray[i];
}
delete[] DynamicArray;
}
};
int main() {
DynArray<class T>();
return 0;
}
Not sure if I am a complete retard in my line of thinking or if I am just missing a small element. Any help is great.
Thank you #jblixr and #user3655463 for your help. I got it worked out I think after your hints and help.
Here is what I came up with for reference if anyone else is working on this.
#include <iostream>
#include <new>
#include <algorithm>
using namespace std;
//Template Class T
template <class T>
class DynArray {
protected:
int size;
T * DynamicArray;
public:
DynArray(){};
DynArray(size_t s): size(s) {
DynamicArray = new T[size];
for (int i = 0; i<size; i++) {
cout << "Element " << i << ": ";
cin >> DynamicArray[i];
}
}
//Sort Array
void Sort(){
sort(DynamicArray, DynamicArray+size);
for (int i=0; i<size; i++) {
cout << DynamicArray[i] << endl;
}
}
//Clear Heap
~DynArray() {
delete []DynamicArray;
}
};
int main() {
int sizeOfArry;
cout << "Enter size of Array: ";
cin >> sizeOfArry;
//Use as an int Array;
DynArray<int> intArray = DynArray<int>(sizeOfArry);
intArray.Sort();
}
From description you have provided looks to me you want to do sth like that:
#include <iostream>
#include <algorithm>
using namespace std;
template <class T>
class DynArray {
protected:
int size;
T * DynamicArray;
public:
DynArray(size_t s): size(s) {
DynamicArray = new T[s];
}
void CreateArray(){
size_t size;
cout << "Enter size of Array: ";
cin >> size;
if(size > this->size)
size = this->size;
for (int i = 0; i<size; i++) {
cout << "Element " << i << ": ";
cin >> DynamicArray[i];
}
}
//Sort Array
void Sort()
{
std::sort(DynamicArray, DynamicArray+size);
}
DynArray() {
delete []DynamicArray;
}
};
int main() {
DynArray<double> dob(3);
DynArray<int> di(3);
dob.CreateArray();
di.CreateArray();
dob.Sort(); di.Sort();
}
I am wondering that whether you are creating a one dimensional array or 2D array, your initial requirements states one dimensional array but you are using 2D array in your code. Anyway, I play along with one dimensional array.
error: allocation of incomplete type 'T'
T *DynamicArray = new T[size];
What you are trying to do here is in-class initialization which can be done for static data members and it is an c++11 extension for non-static data member. So I suggest you not to do so since you are learning. You can only declare the members and don't initialize here.
Even if you make static it cannot be allocated because the template type T is known only after object creation, So the compiler isn't aware of the type it is going to allocate during the compile time.
So it should be simply as
T *DynamicArray;
Nested functions
C++ doesn't support nested functions, learn C++ syntax.
Usage of constructors and destructors
A constructor will do the functionality of CreateArray() and the destructor will do the functionlaity of DeleteArray()
Instantiating a template class
You should explicitly mention the type within the angle brackets that the template class is going to use
DynArray<int> intArray; // if you want to use int
DynArray<float> floatArray;
You can also use your own custom class for type T, hope you will learn soon in your class.
DynArray<MyCustomClass> customArray;
If you correct all these things then your final skeleton will be like the below one
template <class T>
class DynArray {
protected:
int size;
T *DynamicArray ;
public:
DynArray() {
// initailize DynamicArray here
// use your CreateArray() code here
}
void sort() {
// your own sort logic
// No need to pass the size to this function, its a member function
}
~DynArray() {
// use your DeleteArray() code here
}
};
int main() {
DynArray<int> intArray;
intArray.sort()
return 0;
}
Simple, isn't it? :)

How c++ compilers extend template<> code and how does it affect speed of same?

I am little lost with templates, and how compiler processes them.
Needed some generic wrapper for std::vector<< SomeType * >>* lpVars; that is capable of performing delete on all items contained inside that vector when I delete lpVars. Something similar to the C#'s List<> (generic list class).
So I went for templates and wrote something like this:
template<class T>
class ListPtr
{
public:
std::vector<T*> items;
ListPtr()
{ }
~ListPtr()
{
size_t count = items.size();
for(size_t i=0; i<count; i++)
{
T* item = items[i];
delete item;
}
items.clear();
}
inline const int count() const
{
return (int)items.size();
}
inline T* operator[](size_t index) const
{
return items[index];
}
inline void Add(T* item)
{
items.push_back(item);
}
};
later on I declared global type lists like:
class SomeType1List : public ListPtr<SomeType1> {};
class SomeType2List : public ListPtr<SomeType2> {};
...
class SomeTypeNList : public ListPtr<SomeTypeN> {};
Here is the first part of my interest on subject:
(1) Are this classes SomeType1List, SomeType1List, ..., SomeTypeNList fully preprocessed to templates code with replaced T template type for each declaration (SomeType1, SomeType2, ..., SomeTypeN) like there is no template (are fully declared classes), or compiler performs some other magic here?
(2) And if compiler performs some other magic, how should I define this types that compiler would compile them as they are fully declared classes?
To explain usage of above code more precise:
this list instances are initialized, and returned from functions like following one:
SomeType1List* GetItems()
{
SomeType1List* items = new SomeType1List();
for(int i=0; i<1000; i++)
{
SomeType1* item = new SomeType1();
// feed item with some data
items->Add(item);
}
return items;
}
and used in other parts of code like this:
SomeType1List* items = GetItems();
int count = items->count();
for(int i=0; i<count; i++)
{
SomeType1* item = items[i];
// do something with item;
}
delete items; // all memory occupied by items released after this line
Second part of my interest on subject:
(3) Could this be written differently using only standard classes (no boost or similar sdks)? goal is speed but to keep code clean and easy to read. So this question would be is there any better way to do all of this?
Yes
No magic here
You can use std::vector<std::unique_ptr<T>> (C++11) or std::vector<std::auto_ptr<T>> (kind of deprecated)
Example:
#include <iostream>
#include <memory>
#include <vector>
class T
{
private:
unsigned int _i;
public:
void print() const
{
std::cout << "Print: " << _i << std::endl;
}
T(unsigned int i)
{
_i = i;
std::cout << "Constructor! " << _i << std::endl;
}
~T()
{
std::cout << "Destructor! " << _i << std::endl;
}
};
std::vector<std::unique_ptr<T>>* createStuff()
{
auto output = new std::vector<std::unique_ptr<T>>;
for(unsigned int i = 0; i < 5; i++)
{
output->emplace_back(new T(i));
}
return output;
}
int main()
{
std::cout << "Begin!" << std::endl;
auto stuff = createStuff();
for(std::unique_ptr<T> const& thing : *stuff)
{
thing->print();
}
delete stuff;
std::cout << "End!" << std::endl;
return 0;
}
Output:
Begin!
Constructor! 0
Constructor! 1
Constructor! 2
Constructor! 3
Constructor! 4
Print: 0
Print: 1
Print: 2
Print: 3
Print: 4
Destructor! 0
Destructor! 1
Destructor! 2
Destructor! 3
Destructor! 4
End!

Dyanamic Array Class, Program runs well but with Error

This is my Code
#ifndef INTLIST_H_INCLUDED
#define INTLIST_H_INCLUDED
#include <iostream>
using namespace std;
class intList
{
int upper_bound;
int arr[0];
public:
intList(){ arr[0] = 0; upper_bound = 0; }
void append(int x);
void sort();
friend ostream & operator << (ostream &, intList&);
inline int len(){ return upper_bound; }
inline int &operator [](int x){ return arr[x]; }
private:
void increment(int *a, int &l);
void swap(int &a, int &b);
};
void intList::swap(int &a, int &b)
{
int temp = a;
a = b;
b = temp;
}
void intList::increment(int *a, int &b)
{
b++;
a[b] = 0;
}
void intList::append(int num)
{
arr[upper_bound] = num;
increment(arr, upper_bound);
}
void intList::sort()
{
for(int i = 0; i < upper_bound; i++)
{
int minLoc = i;
for(int j = i+1; j<upper_bound; j++)
{
if(arr[j] < arr[minLoc])
minLoc = j;
}
if(minLoc != i)
swap(arr[i], arr[minLoc]);
}
}
ostream& operator << (ostream & dout, intList &a)
{
dout << "[ ";
for(int i = 0; i<a.upper_bound-1; i++)
dout << a.arr[i] << ", ";
dout << a.arr[a.upper_bound-1] << " ]";
return dout;
}
#endif // INTLIST_H_INCLUDED
The Code does its work perfectly fine. But at the end the Program Crashes. Giving some error like
process returned -1073741819 (0xC0000005) execution time : some seconds.
Just didn't get where am I going wrong.
This looks bad:
int arr[0];
First, C++ doesn't allow zero-sized fixed size arrays. Second, your code certainly needs more than a zero sized array.
Whatever use you make of this code is undefined behaviour (UB). UB includes code seemingly "working perfectly fine".
Your code has several problems.
For example, you have a fixed array of 0 size. If you want a dynamically growable array, you can use std::vector: you can add new items at the end of the vector (dynamically resizing it) using push_back() method:
#include <vector>
// Start with an empty vector
std::vector<int> v;
// Add some items to it
v.push_back(10);
v.push_back(20);
....
Note also that in header files it's not good to insert a using namespace std;. In this way you pollute the global namespace with STL classes, which is bad. Just use std:: prefix in header files.
Moreover, if you want to print the class content to an output stream, you may want to take the class as a const reference, since instances of the class are input parameters (you observe them and print their content to the stream):
std::ostream& operator<<(std::ostream& os, const IntList& a)
{
....
}