Course Homepage: CS106L
Assignment List#
Assignment Number | Assignment Title | Assignment Link |
---|---|---|
Assignment 1 | SimpleEnroll | Go to complete |
Assignment 2 | Marriage Pact | Go to complete |
Assignment 3 | Make a class! | Go to complete |
Assignment 4 | Weather Forecast | Go to complete |
... | ... | ... |
Assignment 1: SimpleEnroll#
Currently unavailable, this assignment's cloud storage is not open to the public (probably)
Assignment 2: Marriage Pact#
Key Points: STL's containers and pointers
Introduction#
start code:
main.cpp
- Source code filestudents.txt
- Names of all students, one per line, in the form of Xxxxx Xxxxx
This assignment requires finding a match from all names that corresponds to your own name, only matching when the initials of a name are the same as your own, and then using any strategy to find a unique match from all matches.
Part 1: Get all applicants#
This part requires reading all names from the file into std::set<std::string>
or std::unordered_set<std::string>
.
Approach:
Using std::ifstream
in conjunction with std::stringstream
.
Code:
std::set<std::string> get_applicants(std::string filename) {
std::set<std::string> result;
std::ifstream ifs(filename);
if (ifs.is_open()) {
std::stringstream ss;
ss << ifs.rdbuf();
std::string line;
while (std::getline(ss, line)) {
result.insert(line);
}
}
return result;
}
Part 2: Find matches#
This part requires finding all matches and placing them into std::queue<const std::string*>
.
Approach:
std::set
is ordered and can be binary searched. My initials are TG, so first, I will binary search to find the left and right boundaries of names starting with T, and then traverse that range to find matches.
Code:
std::queue<const std::string*> find_matches(std::set<std::string> &students) {
std::queue<const std::string*> result;
std::string Prefix("T");
auto itLeft = students.lower_bound(Prefix);
std::string nextPrefix("U");
auto itRight = students.lower_bound(nextPrefix);
for (auto it = itLeft; it != itRight; it++) {
const std::string& name = *it;
std::stringstream ss(name);
std::string first, last;
ss >> first >> last;
if(last[0] != 'G') {
continue;
}
result.push(&name);
}
return result;
}
Then, I will randomly select one unique match from the matches.
Complete Code:
/*
Assignment 2: Marriage Pact
This assignment asks you to discover your one true love using containers and pointers.
There are two parts: implement get_applicants and find_matches.
Submit to Paperless by 11:59pm on 2/1/2024.
*/
#include <iostream>
#include <string>
#include <queue>
#include <set>
#include <fstream>
#include <sstream>
#include <random>
std::set<std::string> get_applicants(std::string filename) {
std::set<std::string> result;
std::ifstream ifs(filename);
if (ifs.is_open()) {
std::stringstream ss;
ss << ifs.rdbuf();
std::string line;
while (std::getline(ss, line)) {
result.insert(line);
}
}
return result;
}
std::queue<const std::string*> find_matches(std::set<std::string> &students) {
std::queue<const std::string*> result;
std::string Prefix("T");
auto itLeft = students.lower_bound(Prefix);
std::string nextPrefix("U");
auto itRight = students.lower_bound(nextPrefix);
for (auto it = itLeft; it != itRight; it++) {
const std::string& name = *it;
std::stringstream ss(name);
std::string first, last;
ss >> first >> last;
if(last[0] != 'G') {
continue;
}
result.push(&name);
}
return result;
}
int main() {
auto students = get_applicants("students.txt");
for (const auto& name : students) {
std::cout << name << std::endl;
}
auto matches = find_matches(students);
std::default_random_engine generator;
std::uniform_int_distribution<int> distribution(1, static_cast<int>(matches.size()));
int rand_int = distribution(generator);
int position = 1;
std::string trueLove;
while (!matches.empty()) {
const std::string* name = matches.front();
matches.pop();
trueLove = *name;
if (position == rand_int) {
break;
}
position++;
}
std::cout << "Your true love is " << trueLove << '\n';
return 0;
}
Assignment 3: Make a Class#
Key Points: class, constructor overloading, const-correctness
Introduction#
start code:
class.h
- Class definition file (header file)class.cpp
- Class implementationmain.cpp
- Main file (instantiation and execution)
This assignment requires you to implement a class that meets the following requirements:
- Must have a custom constructor
- Must have a default constructor
- Must have private members
- Must have public members
- Must have at least one getter method and one setter method
const-correctness#
const-correctness is a principle that encourages the use of the const
keyword to prevent changing values that should not/need not be changed, helping to reduce errors and improve code readability (clarity), as well as gaining opportunities for compiler optimization.
In this assignment, it is mainly reflected in the parameters of getter and setter methods.
Code#
- class.h
// Blank header file
#include <string>
class Student {
private:
std::string name;
int age;
std::string id;
std::string dept;
public:
Student();
Student(const std::string& _name, int _age, const std::string& _id, const std::string& _dept);
void setName(const std::string& _name);
const std::string& getName() const;
void setAge(int _age);
int getAge() const;
void setId(const std::string& _id);
const std::string& getId() const;
void setDept(const std::string& _dept);
const std::string& getDept() const;
};
- class.cpp
// Blank cpp file
#include "class.h"
Student::Student() = default;
Student::Student(const std::string& _name, int _age, const std::string& _id, const std::string& _dept) {
this->name = _name;
this->age = _age;
this->id = _id;
this->dept = _dept;
}
void Student::setName(const std::string& _name) {
this->name = _name;
}
const std::string &Student::getName() const {
return this->name;
}
void Student::setAge(int _age) {
this->age = _age;
}
int Student::getAge() const {
return this->age;
}
void Student::setId(const std::string &_id) {
this->id = _id;
}
const std::string &Student::getId() const {
return this->id;
}
void Student::setDept(const std::string &_dept) {
this->dept = _dept;
}
const std::string &Student::getDept() const {
return this->dept;
}
- main.cpp
#include <memory>
#include <iostream>
#include "class.h"
/*
* Assigment 3: Make a class!
* Requirements:
* Must have a custom constructor
* Must have a default constructor
- i.e. constructor overloading
* Must have private members (functions and/or variables)
* Must have public members (functions)
* Must have at least one getter function
* Must have at least one setter function
*/
int main() {
// initialize class and run this file
auto stu = std::make_unique<Student>("Nanomoa", 20, "12345678", "Computer Science");
std::cout << "Name: " << stu->getName() << '\n';
std::cout << "Age: " << stu->getAge() << '\n';
std::cout << "ID: " << stu->getId() << '\n';
std::cout << "Dept: " << stu->getDept() << '\n';
// or
auto stu1 = std::make_unique<Student>();
stu1->setName("Nanomoa");
stu1->setAge(20);
stu1->setId("12345678");
stu1->setDept("Computer Science");
std::cout << "Name: " << stu1->getName() << '\n';
std::cout << "Age: " << stu1->getAge() << '\n';
std::cout << "ID: " << stu1->getId() << '\n';
std::cout << "Dept: " << stu1->getDept() << '\n';
return 0;
}
Assignment 4: Weather Forecast#
Key Points: template function, lambda
Introduction#
start code:
main.cpp
Main code fileoutput.txt
Output file
Given the Fahrenheit temperatures at different times of the day for a week, this assignment requires using template function
and lambda
to process them.
Part 1: Temperature Converter#
Use Template Function
to implement the function convert_f_to_c
, which converts Fahrenheit temperatures to Celsius, returning a double
type value.
Note: The type of the input Fahrenheit temperature is unknown.
Conversion formula:
Code:
template<typename Type>
double convert_f_to_c(Type f) {
return (static_cast<double>(f) - 32) * 5 / 9;
}
Part 2: The Weekly Forecast#
Complete the implementation of the function get_forecast
to perform result statistics.
Function template:
template<typename Function>
std::vector<double> get_forecast(std::vector<std::vector<double>> readings, Function fn) {
// TODO
}
Note: The fn
here needs to accept a lambda
as a parameter.
We just need to iterate through each day, then call fn
to calculate and store the result.
Code:
template<typename Function>
std::vector<double> get_forecast(std::vector<std::vector<double>> readings, Function fn) {
std::vector<double> result;
result.reserve(readings.size());
for (const auto& day : readings) {
result.push_back(fn(day));
}
return result;
}
Part 3: Putting it all together#
We need to call the above-implemented functions in the main
function to achieve the following functionalities:
- Convert
readings
to Celsius and output tooutput.txt
- Calculate the highest temperature for each day and output to
output.txt
- Calculate the lowest temperature for each day and output to
output.txt
- Calculate the average temperature for each day and output to
output.txt
Among which, 2~4 need to implement corresponding lambda
to be passed to the get_forecast
function.
Code:
// TODO: Convert temperatures to Celsius and output to output.txt
for (auto& vec : readings) {
for (auto& item : vec) {
item = convert_f_to_c(item);
}
}
std::ofstream ofs("output.txt");
if (ofs.is_open()) {
for (auto& vec : readings) {
for (auto& item : vec) {
ofs << item << " ";
}
ofs << '\n';
}
ofs.close();
}
// TODO: Find the maximum temperature for each day and output to output.txt
auto maximum_temps = [](const std::vector<double>& day) -> double {
return *std::max_element(day.begin(), day.end());
};
auto max_temps = get_forecast(readings, maximum_temps);
ofs.open("output.txt", std::ios_base::app);
if (ofs.is_open()) {
for (auto& item : max_temps) {
ofs << item << " ";
}
ofs << '\n';
ofs.close();
}
// TODO: Find the minimum temperature for each day and output to output.txt
auto minimum_temps = [](const std::vector<double>& day) -> double {
return *std::min_element(day.begin(), day.end());
};
auto min_temps = get_forecast(readings, minimum_temps);
ofs.open("output.txt", std::ios_base::app);
if (ofs.is_open()) {
for (auto& item : min_temps) {
ofs << item << " ";
}
ofs << '\n';
ofs.close();
}
// TODO: Find the average temperature for each day and output to output.txt
auto average_temps = [](const std::vector<double>& day) -> double {
double sum = std::accumulate(day.begin(), day.end(), 0.0);
return sum / static_cast<double>(day.size());
};
auto avg_temps = get_forecast(readings, average_temps);
ofs.open("output.txt", std::ios_base::app);
if (ofs.is_open()) {
for (auto& item : avg_temps) {
ofs << item << " ";
}
ofs << '\n';
ofs.close();
}
Complete Code:#
/*
Assignment 4: Weather Forecast
This assignment works with template functions and lambdas to become the best weather forecaster
at the Stanford Daily. Be sure to read the assignment details in the PDF.
Submit to Paperless by 11:59pm on 5/10/2024.
*/
// TODO: import anything from the STL that might be useful!
#include <iostream>
#include <vector>
#include <fstream>
#include <algorithm>
#include <numeric>
// TODO: write convert_f_to_c function here. Remember it must be a template function that always returns
// a double.
template<typename Type>
double convert_f_to_c(Type f) {
return (static_cast<double>(f) - 32) * 5 / 9;
}
template<typename Function>
std::vector<double> get_forecast(std::vector<std::vector<double>> readings, Function fn) {
std::vector<double> result;
result.reserve(readings.size());
for (const auto& day : readings) {
result.push_back(fn(day));
}
return result;
}
int main() {
std::vector<std::vector<double>> readings = {
{70, 75, 80, 85, 90},
{60, 65, 70, 75, 80},
{50, 55, 60, 65, 70},
{40, 45, 50, 55, 60},
{30, 35, 40, 45, 50},
{50, 55, 61, 65, 70},
{40, 45, 50, 55, 60}
};
// TODO: Convert temperatures to Celsius and output to output.txt
for (auto& vec : readings) {
for (auto& item : vec) {
item = convert_f_to_c(item);
}
}
std::ofstream ofs("output.txt");
if (ofs.is_open()) {
for (auto& vec : readings) {
for (auto& item : vec) {
ofs << item << " ";
}
ofs << '\n';
}
ofs.close();
}
// TODO: Find the maximum temperature for each day and output to output.txt
auto maximum_temps = [](const std::vector<double>& day) -> double {
return *std::max_element(day.begin(), day.end());
};
auto max_temps = get_forecast(readings, maximum_temps);
ofs.open("output.txt", std::ios_base::app);
if (ofs.is_open()) {
for (auto& item : max_temps) {
ofs << item << " ";
}
ofs << '\n';
ofs.close();
}
// TODO: Find the minimum temperature for each day and output to output.txt
auto minimum_temps = [](const std::vector<double>& day) -> double {
return *std::min_element(day.begin(), day.end());
};
auto min_temps = get_forecast(readings, minimum_temps);
ofs.open("output.txt", std::ios_base::app);
if (ofs.is_open()) {
for (auto& item : min_temps) {
ofs << item << " ";
}
ofs << '\n';
ofs.close();
}
// TODO: Find the average temperature for each day and output to output.txt
auto average_temps = [](const std::vector<double>& day) -> double {
double sum = std::accumulate(day.begin(), day.end(), 0.0);
return sum / static_cast<double>(day.size());
};
auto avg_temps = get_forecast(readings, average_temps);
ofs.open("output.txt", std::ios_base::app);
if (ofs.is_open()) {
for (auto& item : avg_temps) {
ofs << item << " ";
}
ofs << '\n';
ofs.close();
}
return 0;
}