feat: finish program 4
This commit is contained in:
parent
6d5b3eddc1
commit
8922656c61
4 changed files with 378 additions and 1 deletions
19
meson.build
19
meson.build
|
@ -45,4 +45,21 @@ c_5_lab_5_1 = executable(
|
||||||
install: true,
|
install: true,
|
||||||
)
|
)
|
||||||
|
|
||||||
c_6_lab_6 = executable('c_6_lab-6', ['src/chapter_6/lab-6/main.cpp', 'src/chapter_6/lab-6/IntVector.h', 'src/chapter_6/lab-6/IntVector.cpp'], install: true)
|
c_6_lab_6 = executable(
|
||||||
|
'c_6_lab-6',
|
||||||
|
[
|
||||||
|
'src/chapter_6/lab-6/main.cpp',
|
||||||
|
'src/chapter_6/lab-6/IntVector.h',
|
||||||
|
'src/chapter_6/lab-6/IntVector.cpp',
|
||||||
|
],
|
||||||
|
install: true,
|
||||||
|
)
|
||||||
|
c_6_program_4 = executable(
|
||||||
|
'c_6_program-4',
|
||||||
|
[
|
||||||
|
'src/chapter_6/program-4/main.cpp',
|
||||||
|
'src/chapter_6/program-4/IntVector.h',
|
||||||
|
'src/chapter_6/program-4/IntVector.cpp',
|
||||||
|
],
|
||||||
|
install: true,
|
||||||
|
)
|
||||||
|
|
149
src/chapter_6/program-4/IntVector.cpp
Normal file
149
src/chapter_6/program-4/IntVector.cpp
Normal file
|
@ -0,0 +1,149 @@
|
||||||
|
#include "IntVector.h"
|
||||||
|
#include <stdexcept>
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
IntVector::IntVector(unsigned capacity, int value) {
|
||||||
|
__size = capacity;
|
||||||
|
__capacity = capacity;
|
||||||
|
|
||||||
|
if (__size > 0) {
|
||||||
|
__data = new int[__size];
|
||||||
|
} else {
|
||||||
|
__data = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < __size; i++) {
|
||||||
|
__data[i] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IntVector::~IntVector() { delete[] __data; }
|
||||||
|
|
||||||
|
const int &IntVector::at(unsigned index) const {
|
||||||
|
if (index >= __size)
|
||||||
|
throw out_of_range("IntVector::at_range_check");
|
||||||
|
|
||||||
|
return __data[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
int &IntVector::at(unsigned index) {
|
||||||
|
if (index >= __size)
|
||||||
|
throw out_of_range("IntVector::at_range_check");
|
||||||
|
|
||||||
|
return __data[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned IntVector::size() const { return __size; }
|
||||||
|
unsigned IntVector::capacity() const { return __capacity; };
|
||||||
|
bool IntVector::empty() const { return __size == 0; };
|
||||||
|
const int &IntVector::front() const { return __data[0]; }
|
||||||
|
const int &IntVector::back() const { return __data[__size - 1]; }
|
||||||
|
|
||||||
|
int &IntVector::front() { return __data[0]; };
|
||||||
|
int &IntVector::back() { return __data[__size - 1]; };
|
||||||
|
void IntVector::reserve(unsigned n) {
|
||||||
|
if (n <= __capacity) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
expand(n - __capacity);
|
||||||
|
};
|
||||||
|
|
||||||
|
void IntVector::clear() { __size = 0; };
|
||||||
|
|
||||||
|
void IntVector::expand(unsigned amount) {
|
||||||
|
__capacity += amount;
|
||||||
|
int *newVec = new int[__capacity];
|
||||||
|
for (unsigned i = 0; i < __size; i++) {
|
||||||
|
newVec[i] = __data[i];
|
||||||
|
}
|
||||||
|
delete[] __data;
|
||||||
|
__data = newVec;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IntVector::expand() {
|
||||||
|
if (__capacity == 0) {
|
||||||
|
expand(1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
expand(__capacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IntVector::push_back(int value) {
|
||||||
|
if (__size >= __capacity) {
|
||||||
|
expand();
|
||||||
|
}
|
||||||
|
__size++;
|
||||||
|
back() = value;
|
||||||
|
};
|
||||||
|
|
||||||
|
void IntVector::assign(unsigned n, int value) {
|
||||||
|
if (n > __capacity && n - __capacity > __capacity) {
|
||||||
|
expand(n - __capacity);
|
||||||
|
} else if (n > __capacity) {
|
||||||
|
expand();
|
||||||
|
}
|
||||||
|
|
||||||
|
delete[] __data;
|
||||||
|
__data = new int[__capacity];
|
||||||
|
|
||||||
|
__size = n;
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < __size; i++) {
|
||||||
|
__data[i] = value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void IntVector::pop_back() { __size--; };
|
||||||
|
|
||||||
|
void IntVector::resize(unsigned n, int value) {
|
||||||
|
if (n == __size)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (n < __size) {
|
||||||
|
__size = n;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n > __capacity) {
|
||||||
|
if (n - __capacity > __capacity) {
|
||||||
|
reserve(n);
|
||||||
|
} else {
|
||||||
|
expand();
|
||||||
|
}
|
||||||
|
|
||||||
|
int *newVec = new int[__capacity];
|
||||||
|
for (unsigned i = 0; i < __size; i++) {
|
||||||
|
newVec[i] = __data[i];
|
||||||
|
}
|
||||||
|
delete[] __data;
|
||||||
|
__data = newVec;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; __size < n; __size++) {
|
||||||
|
__data[__size] = value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void IntVector::insert(unsigned idx, int value) {
|
||||||
|
if (idx > __size) {
|
||||||
|
throw out_of_range("IntVector::insert_range_check");
|
||||||
|
}
|
||||||
|
if (__size == __capacity) {
|
||||||
|
expand();
|
||||||
|
}
|
||||||
|
__size++;
|
||||||
|
for (unsigned i = idx; i < __size - 1; i++) {
|
||||||
|
__data[i + 1] = __data[i];
|
||||||
|
}
|
||||||
|
__data[idx] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IntVector::erase(unsigned idx) {
|
||||||
|
if (idx >= __size) {
|
||||||
|
throw out_of_range("IntVector::erase_range_check");
|
||||||
|
}
|
||||||
|
for (unsigned i = idx; i < __size - 1; i++) {
|
||||||
|
__data[i] = __data[i + 1];
|
||||||
|
}
|
||||||
|
__size--;
|
||||||
|
}
|
31
src/chapter_6/program-4/IntVector.h
Normal file
31
src/chapter_6/program-4/IntVector.h
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
class IntVector {
|
||||||
|
public:
|
||||||
|
IntVector(unsigned capacity = 0, int value = 0);
|
||||||
|
~IntVector();
|
||||||
|
unsigned size() const;
|
||||||
|
unsigned capacity() const;
|
||||||
|
bool empty() const;
|
||||||
|
const int &at(unsigned index) const;
|
||||||
|
const int &front() const;
|
||||||
|
const int &back() const;
|
||||||
|
int &at(unsigned index);
|
||||||
|
int &front();
|
||||||
|
int &back();
|
||||||
|
void assign(unsigned, int);
|
||||||
|
void push_back(int value);
|
||||||
|
void pop_back();
|
||||||
|
void clear();
|
||||||
|
void resize(unsigned n, int value = 0);
|
||||||
|
void reserve(unsigned n);
|
||||||
|
void insert(unsigned, int);
|
||||||
|
void erase(unsigned);
|
||||||
|
|
||||||
|
private:
|
||||||
|
unsigned __size;
|
||||||
|
unsigned __capacity;
|
||||||
|
int *__data;
|
||||||
|
void expand();
|
||||||
|
void expand(unsigned);
|
||||||
|
};
|
180
src/chapter_6/program-4/main.cpp
Normal file
180
src/chapter_6/program-4/main.cpp
Normal file
|
@ -0,0 +1,180 @@
|
||||||
|
#include "IntVector.h"
|
||||||
|
#include <cassert>
|
||||||
|
#include <iostream>
|
||||||
|
#include <stdexcept>
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
cout << "Running test bench!" << endl;
|
||||||
|
|
||||||
|
IntVector *testVec = nullptr;
|
||||||
|
|
||||||
|
testVec = new IntVector();
|
||||||
|
assert(testVec->empty());
|
||||||
|
cout << "[SUCCESS] empty() works as expected for empty vector." << endl;
|
||||||
|
assert(testVec->size() == 0);
|
||||||
|
assert(testVec->capacity() == 0);
|
||||||
|
cout << "[SUCCESS] Default constructor sets size and capacity properly."
|
||||||
|
<< endl;
|
||||||
|
|
||||||
|
delete testVec;
|
||||||
|
testVec = new IntVector(1);
|
||||||
|
assert(!testVec->empty());
|
||||||
|
cout << "[SUCCESS] empty() works as expected for nonempty vector." << endl;
|
||||||
|
assert(testVec->at(0) == 0);
|
||||||
|
cout << "[SUCCESS] Basic vector initialization works." << endl;
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < 100; i++) {
|
||||||
|
delete testVec;
|
||||||
|
testVec = new IntVector(i, 50 - i);
|
||||||
|
|
||||||
|
assert(testVec->capacity() == i);
|
||||||
|
assert(testVec->size() == i);
|
||||||
|
|
||||||
|
for (unsigned j = 0; j < testVec->size(); j++) {
|
||||||
|
assert(testVec->at(j) == 50 - static_cast<int>(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cout << "[SUCCESS] Size and capacity work as expected" << endl;
|
||||||
|
cout << "[SUCCESS] Initializing values getting values at indices work."
|
||||||
|
<< endl;
|
||||||
|
|
||||||
|
delete testVec;
|
||||||
|
testVec = new IntVector(5, 2);
|
||||||
|
|
||||||
|
bool failed = false;
|
||||||
|
try {
|
||||||
|
testVec->at(5);
|
||||||
|
} catch (const out_of_range &e) {
|
||||||
|
failed = true;
|
||||||
|
}
|
||||||
|
assert(failed);
|
||||||
|
cout << "[SUCCESS] at() correctly throws for out of range access." << endl;
|
||||||
|
|
||||||
|
assert((testVec->front() == testVec->at(0)));
|
||||||
|
cout << "[SUCCESS] Output of front() is consistent with output of at(0)."
|
||||||
|
<< endl;
|
||||||
|
|
||||||
|
assert(testVec->front() == 2);
|
||||||
|
cout << "[SUCCESS] Output of front() is correct." << endl;
|
||||||
|
|
||||||
|
assert((testVec->back() == testVec->at(testVec->size() - 1)));
|
||||||
|
cout
|
||||||
|
<< "[SUCCESS] Output of back() is consistent with output of at(size - 1)."
|
||||||
|
<< endl;
|
||||||
|
|
||||||
|
assert(testVec->front() == 2);
|
||||||
|
cout << "[SUCCESS] Output of back() is correct." << endl;
|
||||||
|
|
||||||
|
delete testVec;
|
||||||
|
testVec = new IntVector(5);
|
||||||
|
assert(testVec->capacity() == 5);
|
||||||
|
testVec->reserve(20);
|
||||||
|
assert(testVec->capacity() == 20);
|
||||||
|
testVec->reserve(5);
|
||||||
|
assert(testVec->capacity() == 20);
|
||||||
|
cout << "[SUCCESS] reserve() works as expected." << endl;
|
||||||
|
|
||||||
|
testVec->clear();
|
||||||
|
assert(testVec->capacity() == 20);
|
||||||
|
assert(testVec->size() == 0);
|
||||||
|
assert(testVec->empty());
|
||||||
|
cout << "[SUCCESS] clear() works as expected." << endl;
|
||||||
|
|
||||||
|
delete testVec;
|
||||||
|
testVec = new IntVector(5);
|
||||||
|
testVec->at(3) = 2;
|
||||||
|
assert(testVec->back() == 0);
|
||||||
|
testVec->pop_back();
|
||||||
|
assert(testVec->size() == 4);
|
||||||
|
assert(testVec->back() == 2);
|
||||||
|
cout << "[SUCCESS] pop_back() works as expected." << endl;
|
||||||
|
|
||||||
|
delete testVec;
|
||||||
|
testVec = new IntVector(5);
|
||||||
|
testVec->push_back(5);
|
||||||
|
assert(testVec->size() == 6);
|
||||||
|
assert(testVec->back() == 5);
|
||||||
|
cout << "[SUCCESS] push_back() works as expected." << endl;
|
||||||
|
|
||||||
|
delete testVec;
|
||||||
|
testVec = new IntVector(5);
|
||||||
|
testVec->resize(3, 2);
|
||||||
|
assert(testVec->size() == 3);
|
||||||
|
assert(testVec->capacity() == 5);
|
||||||
|
assert(testVec->front() == 0);
|
||||||
|
cout << "[SUCCESS] resize() to lesser capacity works." << endl;
|
||||||
|
testVec->resize(8);
|
||||||
|
assert(testVec->size() == 8);
|
||||||
|
assert(testVec->capacity() == 10);
|
||||||
|
assert(testVec->back() == 0);
|
||||||
|
cout << "[SUCCESS] resize() doubles capacity when appropriate." << endl;
|
||||||
|
testVec->resize(100, 5);
|
||||||
|
assert(testVec->size() == 100);
|
||||||
|
assert(testVec->capacity() == 100);
|
||||||
|
assert(testVec->back() == 5);
|
||||||
|
testVec->resize(500);
|
||||||
|
assert(testVec->capacity() == 500);
|
||||||
|
assert(testVec->size() == 500);
|
||||||
|
assert(testVec->back() == 0);
|
||||||
|
cout << "[SUCCESS] resize() increases capacity when appropriate." << endl;
|
||||||
|
|
||||||
|
delete testVec;
|
||||||
|
testVec = new IntVector(5);
|
||||||
|
testVec->assign(3, 10);
|
||||||
|
assert(testVec->size() == 3);
|
||||||
|
assert(testVec->capacity() == 5);
|
||||||
|
assert(testVec->at(1) == 10);
|
||||||
|
testVec->assign(8, 0);
|
||||||
|
assert(testVec->capacity() == 10);
|
||||||
|
assert(testVec->front() == 0);
|
||||||
|
testVec->assign(50, 2);
|
||||||
|
assert(testVec->capacity() == 50);
|
||||||
|
assert(testVec->front() == 2);
|
||||||
|
cout << "[SUCCESS] assign() works as expected." << endl;
|
||||||
|
|
||||||
|
delete testVec;
|
||||||
|
testVec = new IntVector(5);
|
||||||
|
testVec->insert(3, 3);
|
||||||
|
assert(testVec->at(3) == 3);
|
||||||
|
assert(testVec->size() == 6);
|
||||||
|
testVec->insert(3, 3);
|
||||||
|
assert(testVec->size() == 7);
|
||||||
|
assert(testVec->capacity() == 10);
|
||||||
|
failed = false;
|
||||||
|
cout << "[SUCCESS] Basic insertion works" << endl;
|
||||||
|
try {
|
||||||
|
testVec->insert(10, 3);
|
||||||
|
} catch (const out_of_range &e) {
|
||||||
|
failed = true;
|
||||||
|
}
|
||||||
|
assert(failed);
|
||||||
|
cout << "[SUCCESS] insert() correctly throws exception when out of range"
|
||||||
|
<< endl;
|
||||||
|
|
||||||
|
delete testVec;
|
||||||
|
testVec = new IntVector(5);
|
||||||
|
testVec->erase(3);
|
||||||
|
assert(testVec->size() == 4);
|
||||||
|
cout << "[SUCCESS] erase() modifies size properly." << endl;
|
||||||
|
testVec->insert(3, 4);
|
||||||
|
testVec->erase(3);
|
||||||
|
assert(testVec->at(3) == 0);
|
||||||
|
cout << "[SUCCESS] erase() removes the correct element." << endl;
|
||||||
|
assert(testVec->capacity() == 5);
|
||||||
|
cout << "[SUCCESS] erase() doesn't modify capacity" << endl;
|
||||||
|
failed = false;
|
||||||
|
try {
|
||||||
|
testVec->erase(10);
|
||||||
|
} catch (const out_of_range &e) {
|
||||||
|
failed = true;
|
||||||
|
}
|
||||||
|
assert(failed);
|
||||||
|
cout << "[SUCCESS] insert() correctly throws exception when out of range"
|
||||||
|
<< endl;
|
||||||
|
|
||||||
|
delete testVec;
|
||||||
|
testVec = nullptr;
|
||||||
|
cout << "All tests passed!" << endl;
|
||||||
|
}
|
Loading…
Reference in a new issue