feat: finish program 4

This commit is contained in:
Youwen Wu 2025-02-14 17:04:47 -08:00
parent 6d5b3eddc1
commit 8922656c61
Signed by: youwen5
GPG key ID: 865658ED1FE61EC3
4 changed files with 378 additions and 1 deletions

View file

@ -45,4 +45,21 @@ c_5_lab_5_1 = executable(
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,
)

View 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--;
}

View 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);
};

View 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;
}