banner
Nanomoa

Nanomoa's Blog

"Bytes and Brackets: My Journey in Go and C++ Exploration."
github
zhihu
telegram
twitter

CS106L 2024年春季作業

課程首頁: CS106L

作業列表#

作業序號作業標題作業連結
Assignment 1SimpleEnroll前往完成
Assignment 2Marriage Pact前往完成
Assignment 3Make a class!前往完成
Assignment 4Weather Forecast前往完成
.........

Assignment 1: SimpleEnroll#

目前做不了,這個作業的網盤不對外開放 (大概

Assignment 2: Marriage Pact#

知識點: STL 的容器和指針

簡介#

start code:

  • main.cpp - 源代碼文件
  • students.txt - 所有學生的姓名,一行一個,形如 Xxxxx Xxxxx

本次作業需要從所有名字中找出與自己名字匹配的一項,當且僅當某個名字的首字母縮寫和自己名字相同時匹配,然後採用任意策略從所有匹配項中找到唯一的一項

Part 1: Get all applicants#

本部分需要讀取文件中所有名字到 std::set<std::string>std::unordered_set<std::string>

思路:

std::ifstream 配合 std::stringstream 即可

代碼:

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#

本部分需要找出所有匹配項放入 std::queue<const std::string*>

思路:

std::set 有序可二分,我名字縮寫為TG, 故,先二分找到 T 開頭的名字的左右邊界,而後遍歷該區間找到匹配項即可

代碼:

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


然後要從匹配項中取出唯一一項,我這裡隨機取出一項

完整代碼:

/* 
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#

知識點: class, constructor overloading, const-correctness

簡介#

start code:

  • class.h - 類的定義文件 (頭文件)
  • class.cpp - 類的實現
  • main.cpp - 主要文件 (實例化並運行)

本次作業需要自行實現一個類,並滿足如下要求:

  1. 必須有一個自定義的構造函數
  2. 必須有一個默認構造函數
  3. 必須有私有成員
  4. 必須有共有成員
  5. 必須有至少一個getter方法以及一個setter方法

const-correctness#

const-correctness 是一個原則,鼓勵使用 const 關鍵字來防止改變不應該 / 不需要被改變的值,有助於減少錯誤以及提高代碼可讀性 (清晰度), 還有獲得編譯器優化的機會

在本次作業中,主要反映在 getter 方法以及 setter 方法的參數上

代碼#

  • 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#

知識點: template function, lambda

簡介#

start code:

  • main.cpp 主要代碼文件
  • output,txt 輸出文件

已知某周中每天不同时段的華氏溫度,本次作業需要配合template functionlambda 對其做一些處理

Part 1: Temperature Converter#

使用 Template Function 實現函數 convert_f_to_c, 將華氏溫度轉換為攝氏溫度,返回一個double 類型的值

注意: 傳入華氏溫度的類型未知

轉換公式: (Fahrenheit32)×5÷9( Fahrenheit - 32) \times 5 \div 9

代碼:

template<typename Type>
double convert_f_to_c(Type f) {
    return (static_cast<double>(f) - 32) * 5 / 9;
}

Part 2: The Weekly Forecast#

完善實現函數 get_forecast 完成結果統計

函數模板:

template<typename Function>
std::vector<double> get_forecast(std::vector<std::vector<double>> readings, Function fn) {
  // TODO
}

注意: 此處的 fn 需要接受一個lambda作為參數

我們只需要遍歷每一天,之後調用fn計算後存入結果即可

代碼:

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#

我們需要在 main 函數中調用上面實現的函數完成如下功能:

  1. readings 轉為攝氏溫度並輸出到output.txt
  2. 統計出每天的最高溫度並輸出到output.txt
  3. 統計出每天的最低溫度並輸出到output.txt
  4. 統計出每天的平均溫度並輸出到output.txt

其中2~4條需要實現對應的lambda作為參數傳入get_forecast函數

代碼:

    // 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();
    }

完整代碼:#

/* 
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;
}
載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。