210 lines
7.1 KiB
Markdown
210 lines
7.1 KiB
Markdown
# Lab 5 — Vec Implementation
|
||
|
||
## Checkpoint 1
|
||
*estimate: 20 minutes*
|
||
|
||
- Team up with one student in your lab section. MEET SOMEONE NEW! You may not work
|
||
with someone who was on your team for Lab 4. Ask a TA or mentor to help you find a partner.
|
||
If the number of students in the room is not even, the graduate TA will approve a single team with 3
|
||
members.
|
||
- Introduce yourself to your teammate. Ask them to share something about themselves (e.g. hobbies,
|
||
sports, favorite music, etc.) Learn something new about your teammate (even if you already know
|
||
them).
|
||
- There are two sets of functions below. Each student in your team takes one set and working on it.
|
||
|
||
For each function below, assign different letters to each of the data sizes that at first glance might have impact
|
||
on the running time of the function. Be sure to consider integer value, size of vector, and length of string.
|
||
Then give the big O notation of the function in terms of those variables.
|
||
|
||
### Student 1
|
||
|
||
```cpp
|
||
int foobar (const std::vector<std::string> &a, int b) {
|
||
int answer = 0;
|
||
for (int i = 0; i < a.size(); i+=b) {
|
||
answer++;
|
||
}
|
||
return answer;
|
||
}
|
||
```
|
||
|
||
```cpp
|
||
void foo2 (const std::vector<int> &a, std::string &b) {
|
||
b.clear();
|
||
for (int i = 0; i < a.size(); i++)
|
||
{
|
||
if (a[i] > 0)
|
||
b.push_back('+');
|
||
else
|
||
b.push_back('-');
|
||
}
|
||
}
|
||
```
|
||
|
||
```cpp
|
||
std::vector<int> foo3 (const std::vector<int> &a, const std::string &b) {
|
||
return std::vector<int>(b.size(),a.size());
|
||
}
|
||
```
|
||
|
||
```cpp
|
||
int foo3 (const std::vector<std::string> &a, const std::string& b) {
|
||
int ret = 0;
|
||
for (int i=0; i<a.size(); i++){
|
||
ret += (a[i] == b);
|
||
}
|
||
return ret;
|
||
}
|
||
```
|
||
|
||
```cpp
|
||
std::vector<int> foo4 (const std::vector<int> &a) {
|
||
std::vector<int> answer = a;
|
||
for (int i = 0; i < a.size(); i++) {
|
||
if(a[i] < (a[a.size()-1]*a[a.size()-1])){
|
||
answer.erase(answer.end()-1);
|
||
}
|
||
}
|
||
return answer;
|
||
}
|
||
```
|
||
|
||
```cpp
|
||
std::vector<int> foo5 (const std::vector<int> &a, int b) {
|
||
std::vector<int> ret;
|
||
for(int i=0; i<a.size(); i++){
|
||
if(a[i] < b){
|
||
ret.insert(ret.end(),a[i]);
|
||
}
|
||
}
|
||
return ret;
|
||
}
|
||
```
|
||
|
||
### Student 2
|
||
|
||
```cpp
|
||
int foobar (const std::vector<std::string> &a, int b) {
|
||
int answer = 0;
|
||
for (int i = 0; i < a.size(); i+=b) {
|
||
answer++;
|
||
}
|
||
return answer;
|
||
}
|
||
```
|
||
|
||
```cpp
|
||
std::vector<int> bar2 (const std::vector<std::string> &a) {
|
||
std::vector<int> answer;
|
||
for (int i = 0; i < a.size(); i++) {
|
||
answer.push_back(a[i].size());
|
||
}
|
||
return answer;
|
||
}
|
||
```
|
||
|
||
```cpp
|
||
std::vector<std::string> bar3 (const std::vector<int> &a) {
|
||
std::vector<std::string> answer;
|
||
for (int i = 0; i < a.size(); i++) {
|
||
answer.push_back(std::string(a[i],'+'));
|
||
}
|
||
return answer;
|
||
}
|
||
```
|
||
|
||
```cpp
|
||
void bar3 (std::vector<std::string> &a, const std::string &b) {
|
||
for (int i = 0; i < a.size(); i++) {
|
||
a[i] = b;
|
||
}
|
||
}
|
||
```
|
||
|
||
```cpp
|
||
std::vector<int> bar4 (const std::vector<std::string> &a) {
|
||
std::vector<int> answer;
|
||
if(!a.empty()){
|
||
for (int i = 0; i < std::min(a[0].size(), a.size()); i++) {
|
||
answer.insert(answer.begin(),a[i].size());
|
||
}
|
||
}
|
||
return answer;
|
||
}
|
||
```
|
||
|
||
```cpp
|
||
void bar5 (std::vector<int> &a) {
|
||
for (int i = 0; i < a.size(); i++){
|
||
if (a[i] > 0){
|
||
a.erase(a.begin() + i);
|
||
i--;
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
When you finish, discuss these problems with your teammate. If your teammate hasn’t finished, please help
|
||
them (but without just doing the problems for them).
|
||
|
||
Once you are both finished, type these examples into your C++ editor, add print statements, and confirm
|
||
your answers are correct. What print statements will be most helpful? In your terminal, instead of running
|
||
just ./a.out try running time ./a.out and reading the real time, which is how long your program took to
|
||
run. How does this change as you increase or decrease each of the data size variables you identified above?
|
||
|
||
**To complete this checkpoint**, as a team, present your work to a TA/mentor.
|
||
|
||
## Checkpoint 2
|
||
*estimate: TBD*
|
||
|
||
Write a templated non-member function named remove_matching_elements that takes in two arguments,
|
||
a vector of type Vec<T> and an element of type T, and returns the number of elements that matched the
|
||
argument and were successfully removed from the vector. The order of the other elements should stay
|
||
the same. For example, if v, a Vec<int> object contains 6 elements: 11 22 33 11 55 22 and you call
|
||
remove_matching_elements(v,11), that call should return 2, and v should now contain: 22 33 55 22.
|
||
You should not create a new vector in your function.
|
||
Add several test cases to test_vec.cpp to show that the function works as expected. What is the order
|
||
notation of your solution in terms of n the size of the vector, and e the number of occurences of the input
|
||
element in the vector?
|
||
|
||
*Note*: when you are in a non-member function, and you want to use the iterator, which is a member type of the Vec<T> class, you have to use the typename keyword before the Vec<T>:: scope. For example, if you want to define an iterator named *itr*, you can do it like this:
|
||
|
||
```console
|
||
typename Vec<T>::iterator itr
|
||
```
|
||
|
||
without this typename keyword, if you define the iterator *itr* like this:
|
||
|
||
```console
|
||
Vec<T>::iterator itr
|
||
```
|
||
|
||
you will get a compiler error saying:
|
||
|
||
```console
|
||
error: need ‘typename’ before ‘Vec<T>::iterator’ because ‘Vec<T>’ is a dependent scope
|
||
```
|
||
|
||
And the reason that this keyword typename is needed, is because without it, the compiler would think that Vec<T>::iterator is a member variable of the Vec<T> class, but this *typename* explicitly tells the compiler that Vec<T>::iterator is a type, rather than a member variable.
|
||
|
||
**To complete this checkpoint**, show a TA your debugged solution for remove_matching_elements and
|
||
be prepared to discuss the order notation of the function.
|
||
|
||
## Checkpoint 3
|
||
*estimate: TBD*
|
||
|
||
Add a print member function to Vec to aid in debugging. (Note, neither remove_matching_elements nor
|
||
print are part of the STL standard for vector). You should print the current information stored in the
|
||
variables capacity, m_size, and m_data. Use the print function to confirm your remove_matching_elements
|
||
function is debugged. Also, write a test case that calls push_back many, many times (hint, use a for loop!)
|
||
and observe how infrequently re-allocation of the m_data array is necessary.
|
||
To verify your code does not contain memory errors or memory leaks, use Valgrind and/or Dr. Memory on
|
||
your local machine – see instructions on the course webpage: Memory Debugging. Also, submit your code
|
||
to the homework server (in the practice space for lab 4), which is configured to run the memory debuggers
|
||
for this exercise. To verify that you understand the output from Valgrind and/or Dr. Memory, temporarily
|
||
add a simple bug into your implementation to cause a memory error or memory leak.
|
||
|
||
**To complete this checkpoint**, show a TA your tested & debugged program. Be prepared to demo and
|
||
discuss the Valgrind and/or Dr. Memory output: with and without memory errors and memory leaks AND
|
||
on your local machine and on the homework server.
|