Lecture 8, Wed 02/06
      std::map, std::unordered_map, Testing
      Maps
  - A map is an associated container containing a key / value mapping.
Example
#include <map>
map<int, string> students; // mapping studentIDs to studentNames
// Use bracket notation for creation
students[0] = "Richert";
students[1] = "John Doe";
students[2] = "Jane Doe";
cout << "students[1] = " << students[1] << endl;
Example using find()
  - Similar to a set, .find will look for a specific key and return map.end() if the key does not exist.
// Check if a student id exists
if (students.find(1) == students.end()) {
	cout << "Can’t find id = 1" << endl;
} else {
	cout << "Found student id = 1, Name = " << students[1] << endl;
}
Example using <string, double> types
map<string, double> stateTaxes;
stateTaxes["CA"] = 0.88;
stateTaxes["NY"] = 1.65;
if (stateTaxes.find("OR") == stateTaxes.end()) {
	cout << "Can't find OR" << endl;
} else {
	cout << "Found state OR" << endl;
}
Example between insert vs. []
  - .insert will add a key / value pair to the map.
    
      - If the key already exists, then .insert() will not replace the existing value.
 
- [] will map a key to a specific value.
    
      - If the key already exists, then [] will replace the existing value.
 
#include <utility> // for std::pair
// ...
students.insert(pair<int, string>(2, "Chris Gaucho")); // does not replace
students[2] = "Chris Gaucho"; // replaces
cout << students[2] << endl;
Erasing using iterators
  - The .erase() can either erase an item in a map using an iterator location OR a specific key value.
Example
// Erasing by iterator
map<int, string>::iterator p = students.find(2);
students.erase(p); // erases "Jane Doe"
// Erasing by key
students.erase(0); // erases "Richert"
// print out the entire map…
for (map<int, string>::iterator i = students.begin(); i != students.end(); i++) {
	cout << i->first << ": " << i->second << endl;
}
std::map vs std::unordered_map
  - The underlying structure of an std::map is implemented with a balanced tree structure.
    
      - Useful if you care about the ordering of keys.
 
- std::unordered_mapis used similarly to std::map, but the- std::unordered_mapis implemented with hash tables.- 
      - In the example above, replace all mapwithunordered_mapand notice they work similary on a high-level.
          - Notice the map’s key / value pairs are not printed in sorted order by keys.
 
- Better average case performance (O(1)), but data order is not guaranteed when traversing the structure with iterators.
 
  
    |  | unordered_map | map | 
  
    |  | Average | Worst-Case | Average | Worst-Case | 
  
    | Lookup | O(1) | O(n) | O(log n) | O(log n) | 
  
    | Deletion | O(1) | O(n) | O(log n) | O(log n) | 
Testing
Complete Test
  - Testing every possible path in every possible situation.
- Complete tests are infeasible!
- The best we can hope for is trying to approximate a Complete Test by testing various types of cases.
- The more rigorous testing a program can “pass”, the more confidence is gained that the program is “bulletproof” (handles every error as expected).
Unit Testing
  - Testing individual pieces (units) of a program (small and large) to ensure correct behavior.
- Good software practice is structuring your program into modular units.
- Good tests generally cover interesting cases including:
    
      - Normal Cases: Cases where the input is generally what we expect.
- Boundary Cases: Cases that test the edge values of possible inputs.
- Error Cases: Invalid cases (like passing a string instead of an int).
        
          - C++ catches most of these types of errors during the compilation process.
- Other languages, such as Python, may need to rigorously check invalid input cases.
 
 
Test Suite
  - A program containing various tests confirming certain behavior.
- A good way to automate tests.
    
      - Very important for large-scale projects where other engineers may make a change that affects functionality of other existing (or new) functionality.
 
- We’ve seen testing programs in several of our lab assignments testing students’ submissions throughout the quarter.
Example: Writing our own simple program using tddFuncs, which tests a function that takes four integers and returns the largest
#include <iostream>
#include <string>
#include "tddFuncs.h"
using namespace std;
int biggest (int a, int b, int c, int d) {
	int biggest = 0;
	if (a >= b && a >= c && a >= d)
		return a;
	if (b >= a && b >= c && b >= d)
		return b;
	if (c >= a && c >= b && c >= d)
		return c;
	return d;
}
int isPositive(int a) {
	return a >= 0;
}
int main() {
	ASSERT_EQUALS(4, biggest(1,2,3,4));
	ASSERT_EQUALS(4, biggest(1,2,4,3));
	ASSERT_EQUALS(4, biggest(1,4,2,3));
	ASSERT_EQUALS(4, biggest(4,1,2,3));
	ASSERT_EQUALS(4, biggest(4,4,4,4));
	ASSERT_EQUALS(-1, biggest(-1,-2,-3,-4));
	ASSERT_EQUALS(0, biggest(-1,0,-3,-4));
	ASSERT_TRUE(isPositive(1));
	ASSERT_TRUE(isPositive(2));
	ASSERT_TRUE(isPositive(0));
	ASSERT_TRUE(!isPositive(-1));
	ASSERT_TRUE(!isPositive(-20));
	return 0;
}