What can be done better? What should I learn to make these tasks better and more efficiently?
The template (template.h):
#pragma once
#include <iostream>
template <typename TData>
class CArray
{
public:
CArray(int capacity = 0);
CArray(
const CArray & _array
);
~CArray();
void push_back(
const TData & _value
);
void insert(
unsigned int _index,
const TData & _value
);
void erase(
unsigned int _index
);
void clear();
unsigned int getSize() const;
void sortAsAscending(
int _left,
int _right
);
TData & operator[](
unsigned int _index
)
{
return buffer[_index];
}
protected:
int size;
int capacity;
TData* buffer;
private:
TData & print(
unsigned int _index
) const
{
return buffer[_index];
}
friend std::ostream & operator<<(
std::ostream & stream,
const CArray<TData> & arr
)
{
if (arr.getSize() > 0)
{
for (unsigned int i = 0; i < arr.getSize(); ++i)
{
stream << arr.print(i) << " ";
}
}
else
{
stream << "The array is empty now.";
}
stream << std::endl;
return stream;
}
};
template <typename TData>
CArray<TData>::CArray(
int _capacity = 0
)
{
capacity = _capacity;
size = 0;
buffer = new TData[capacity];
}
template <typename TData>
CArray<TData>::CArray(
const CArray & _array
)
{
size = _array.size;
capacity = _array.capacity;
buffer = new TData[capacity];
for (unsigned int i = 0; i < size; ++i)
{
buffer[i] = _array.buffer[i];
}
}
template <typename TData>
CArray<TData>::~CArray()
{
delete[] buffer;
}
template <typename TData>
void CArray<TData>::push_back(
const TData & _value
)
{
if (size >= capacity)
{
int newCapacity = 1 << capacity;
TData * newBufferForArray = new TData[newCapacity];
for (unsigned int i = 0; i < size; ++i)
{
newBufferForArray[i] = buffer[i];
}
capacity = newCapacity;
delete[] buffer;
buffer = newBufferForArray;
}
buffer[size] = _value;
size++;
}
template <typename TData>
void CArray<TData>::insert(
unsigned int _index,
const TData & _value
)
{
buffer[_index] = _value;
}
template <typename TData>
void CArray<TData>::erase(
unsigned int _index
)
{
TData * newBufferForArray = new TData[size - 1];
for (unsigned int i = 0; i < _index; ++i)
{
newBufferForArray[i] = buffer[i];
}
for (unsigned int j = _index + 1; j < size; ++j)
{
newBufferForArray[j - 1] = buffer[j];
}
delete[] buffer;
buffer = newBufferForArray;
size--;
}
template <typename TData>
void CArray<TData>::clear()
{
for (unsigned int i = 0; i < size; ++i)
{
buffer[i] = 0;
}
}
template <typename TData>
unsigned int CArray<TData>::getSize() const
{
return size;
}
template <typename TData>
void CArray<TData>::sortAsAscending(
int _left,
int _right
)
{
int i = _left;
int j = _right;
TData tmp;
TData pivot = buffer[(_left + _right) / 2];
while (i <= j) {
while (buffer[i] < pivot)
i++;
while (buffer[j] > pivot)
j--;
if (i <= j) {
tmp = buffer[i];
buffer[i] = buffer[j];
buffer[j] = tmp;
i++;
j--;
}
};
if (_left < j)
sortAsAscending(_left, j);
if (i < _right)
sortAsAscending(i, _right);
}
Testing the template in the main.cpp file:
#include <string>
#include "template.h"
#include <time.h>
int main()
{
std::cout << "1. Working with type INT:" << std::endl;
CArray<int> arr;
std::cout << arr;
std::cout << "1.1. Adding 20 random numbers in range between 0 to 100:" << std::endl;
srand(time(NULL));
for (unsigned int i = 0; i < 20; ++i)
{
arr.push_back(rand() % 101);
}
std::cout << arr;
std::cout << "1.2. Sorting elements in ascending order:" << std::endl;
arr.sortAsAscending(0, (arr.getSize() - 1));
std::cout << arr;
std::cout << "1.3. Deleting every second element: " << std::endl;
CArray<int> copiedArray;
unsigned int counter = 0;
while (arr.getSize() != 10)
{
counter++;
arr.erase(counter);
}
std::cout << arr;
std::cout << "1.4. Inserting 10 random numbers in range 0-100 into random positions: " << std::endl;
for (unsigned int i = 0; i < 10; ++i)
{
arr.insert(rand() % 10, rand() % 100 + 1);
}
std::cout << arr;
std::cout << "NOTE: as positions are random, they can repeat." << std::endl;
std::cout << "1.5. Cleaning the array up:" << std::endl;
arr.clear();
std::cout << arr;
std::cout << "2. Working with type STD::STRING:" << std::endl;
CArray<std::string> arrString;
std::cout << arrString;
std::cout << "2.1. Adding 15 random words with Latin letters in lower case: " << std::endl;
static const char letterString[] = "abcdefghijklmnopqrstuvwxyz";
std::string randomString = "";
for (unsigned int i = 0; i < 15; ++i)
{
unsigned int strLength = rand() % 10 + 3;
for (unsigned int j = 0; j < strLength; ++j)
{
randomString += letterString[rand() % (sizeof(letterString) - 1)];
}
arrString.push_back(randomString);
randomString = "";
}
std::cout << arrString;
std::cout << std::endl;
std::cout << "2.2. Sorting string elements in ascending order: " << std::endl;
arrString.sortAsAscending(0, (arrString.getSize() - 1));
std::cout << arrString;
std::cout << std::endl;
std::cout << "2.3. Deleting words, including letters a, b, c, d, e: " << std::endl;
unsigned int wordCounter = 0;
unsigned int wordLength = 0;
while (true)
{
if (wordCounter > arrString.getSize() - 1)
{
break;
}
else
{
wordLength = arrString[wordCounter].length();
}
for (unsigned int j = 0; j < wordLength; ++j)
{
if (
arrString[wordCounter][j] == 'a' ||
arrString[wordCounter][j] == 'b' ||
arrString[wordCounter][j] == 'c' ||
arrString[wordCounter][j] == 'd' ||
arrString[wordCounter][j] == 'e'
)
{
arrString.erase(wordCounter);
wordCounter--;
break;
}
}
wordCounter++;
}
std::cout << arrString;
std::cout << std::endl;
std::cout << "2.4. Inserting 3 new random words into random positions (marked as \"newValue(value)\"): " << std::endl;
CArray<std::string> newRandomWords;
std::string newRandomString = "newValue";
for (unsigned int i = 0; i < 3; ++i)
{
for (unsigned int j = 0; j < 5; ++j)
{
newRandomString += letterString[rand() % (sizeof(letterString) - 1)];
}
newRandomWords.push_back(newRandomString);
newRandomString = "newValue";
}
for (unsigned int i = 0; i < newRandomWords.getSize(); ++i)
{
arrString.insert(rand() % arrString.getSize(), newRandomWords[i]);
}
std::cout << arrString;
std::cout << "NOTE: inserting is provided only for existing positions (as previous step may leave less than 3 items in the object). As position is random, it can repeat." << std::endl;
std::cout << std::endl << std::endl << "Press Enter to close the window." << std::endl;
std::cin.get();
return 0;
}
upd: what I already know is wrong is that 1) I put the whole template into one file (header) and I could do it differently; 2) implemented incorrectly methods insert and clear (I should have added/deleted new element(s) instead of rewriting the value); 3) possibly made quicksort too simple - should have used iterators and comparators, like in an adult C++ std version of quicksort.
Any futher comments would be greatly appreciated!