在奇牛软件学院的第一个学习记录

发布时间:2024年01月16日

目录

本周每日学习记录

进展

重点内容

练习用代码结构

appendix


本文仅用于记录自己在奇牛软件学习的过程,并对自己起到一个督促性的作用。(目前正在学习C/C++入门的基础语法篇)

作为一名非计算机专业的大龄工科生,我正踏上转向编程(特别是图形学领域)的旅程。在这个过程中,C++成为了我的主要工具。回顾过去一年,我时断时续地学习C++,却发现自己经常在重复相同的概念,没有明确的学习方向,常感到知识点零散且琐碎。

一次偶然的机会,我在B站上看到了Rock老师和学生的交流视频,被他负责任的态度所吸引。在与他简短的沟通后,我决定加入奇牛软件学院。通过学院的项目实践,我希望能够以更系统、实用的方式来掌握C++。同时,我也期待对计算机科学有更深入的理解,尤其是数据结构和算法。

我设定了一个明确的目标:希望在未来一年里,在技能和知识上实现显著的提升。我希望能够将过去零散的学习经历转化为对C++的全面而连贯的理解,为我明年的校园招聘打下坚实的基础。

本周每日学习记录如下:

#Day 01 Thu
2024-01-11 17:57:21: Total study time: 00:10:21
2024-01-11 22:57:21: Total study time: 03:50:21
#Day 02 Fri
2024-01-12 20:52:01: Total study time: 02:43:37
2024-01-12 22:17:46: Total study time: 01:15:15
#Day 03 Sat
2024-01-13 20:09:27: Total study time: 00:36:39
2024-01-13 21:27:45: Total study time: 01:09:28
2024-01-13 22:31:53: Total study time: 01:00:14
2024-01-13 23:58:51: Total study time: 01:26:50
#Day 04 Sun
2024-01-14 18:58:38: Total study time: 00:52:57
2024-01-14 22:11:02: Total study time: 03:00:53
2024-01-14 22:37:37: Total study time: 00:26:19

进展如下(完成视频观看和代码练习,最终代码全部运行成功)

学到的重点内容有:

  • 项目设计思想:问题描述 >> 接口设计 >> 接口实现 >> 成员变量设计

  • sstream(std::std::stringstream)

    • 示例用法:

    • ?std::string Car::description() const {
      ? ? ?std::stringstream ret;
      ? ? ?ret << "car brand: " << brand_ << "(" << model_ << ")" << "\n CURRENT MILES: " << miles_
      ? ? ? ? ?<< "\nPrice: " << getPrice()
      ? ? ? ? ?<< "\nEngine: " << engine_.description();
      ? ? ?for(int i=0; i<4; ++i){
      ? ? ? ? ?ret << "\nTire " << "[" << i ?<< "]" << tires_[0].description();
      ? ?  }
      ? ? ?ret << "\n";
      ? ? ?return ret.str();
      ?}

  • 面向对象编程三大特性封装继承多态:class >>encapsulation>> inheritance >> polymorphism

  • 构造函数constructor,析构函数destructor,拷贝构造函数copy constructor以及拷贝赋值函数copy assignment operator的调用时机和顺序。

  • this 指针

  • Static member类内静态成员的初始化不可以在类内进行,且仅初始化一次。

  • 静态成员函数以及const成员函数的用法。

  • vector中的push_back()方法是一个值拷贝, 这可能会导致设计的偏差。

    • 解决办法,采用指针构造vector

    • #include<vector>
      ?std::vector<MyClass*> vec;
      ?MyClass obj;
      ??
      ?vec.push_back(&obj); // 添加指向obj的指针
      ?vec[0]->modify(); ? ?// 修改vec中的第一个元素,实际上修改的是obj

  • 建模常用手段:组合composition聚合aggregation

    1. 组合是一种强“拥有”关系。在组合中,部分的生命周期依赖于整体的生命周期。当整体被销毁时,其部分也应该被销毁。

      • 组合通常是通过在包含类中创建另一个类的对象实现的。

      • 例子:考虑一个CarEngine的关系。汽车有一个引擎当汽车被销毁时,其引擎也不再存在。

      • ?class Engine {
        ? ? ?// Engine的实现
        ?};
        ??
        ?class Car {
        ?private:
        ? ? ?Engine engine; ?// Car包含一个Engine
        ?public:
        ? ? ?// Car的方法
        ?};

    2. 聚合是一种弱的“拥有”关系,其中一个类(称为“整体”)包含另一个类(称为“部分”)的对象,但两者的生命周期不一定相关联。换句话说,在聚合关系中,部分可以独立于整体存在。

      • 聚合通常通过在包含类中包含另一个类的对象或者指针来实现。

      • 例子:考虑一个ClassStudent的关系。一个班级包含学生,但学生可以存在于班级之外。

      • ?class Student {
        ? ? ?// Student的实现
        ?};
        ??
        ?class Class {
        ?private:
        ? ? ?std::vector<Student> students; ?// Class包含多个Student
        ?public:
        ? ? ?void addStudent(const Student& s) {
        ? ? ? ? ?students.push_back(s);
        ? ?  }
        ? ? ?// Class的其他方法
        ?};

  • 菱形继承问题diamond inheritance structure >> 继承二异性问题ambiguous error

    • solution: 显式调用或采用虚继承,起始基类被称为虚基类

    • 示例用法:

    ?#include <iostream>
    ?#include <string>
    ??
    ?class Tel{
    ?public:
    ? ? ?Tel():number_("unknown"){}
    ?protected:
    ? ? ?std::string number_;
    ?};
    ??
    ?//virtual inheritance can be used to solve the diamond inheritance structure
    ?//the base class named as virtual base class(Tel)
    ?//solving the problem of ambiguous error
    ??
    ?//class Fixedline: public Tel{
    ?class Fixedline: virtual public Tel{
    ??
    ?};
    ??
    ??
    ?//class MobilePhone:public Tel{
    ?class MobilePhone: virtual public Tel{
    ??
    ?};
    ??
    ?class Wireless: public Fixedline, public MobilePhone{
    ?public:
    ? ? ?void setNumber(const std::string& num){
    ? ? ? ? ?//ambiguous error
    ? ? ? ? ?//in diamond inheritance structure, there will be multi-members inherited,
    ? ? ? ? ?// while no way to tell from which
    ? ? ? ? ?//explicitly define the member, but too complicated
    ? ? ? ? ?//what is the solution?
    ? ? ? ? ?//virtual inheritance
    ? ? ? ? ?this->number_ = num;
    ?// ? ? ?  this->Fixedline::number_ = num;
    ? ?  }
    
    ? ? ?std::string getNumber(){
    ?// ? ? ?  return this->Fixedline::number_;
    ? ? ? ? ?return this->number_;
    ? ?  }
    ?};
    ??
    ??
    ?int main() {
    ? ? ?Wireless w;
    ? ? ?w.setNumber("1000000");
    ? ? ?std::cout << w.getNumber() << std::endl;
    ? ? ?return 0;
    ?}
    ??
  • 类继承的几种模式public, protected, private

  • 位图算法Bitmap algorithm(空间换速度)

    • 开辟一个足够大小的char型数组初始化为0, 遍历数组存储相应的数据

    • 首先按照8位一组的方式采样数据并访问相应的单元,在单元内采用位运算存储和判断是否存在

    • 具体代码如下所示:

    • ?#include <iostream>
      ?#include <cstring>
      ?/*
      ? * bit map algorithm
      ? * space -> time
      ? * 4 billion finding issue
      ? * */
      ??
      ?void init(char* data, int len){
      ? ? ?//design following the real problem
      ? ? ?//assuming only (int number % 3 == 0) are stored
      ? ? ?unsigned int n = len*8; //total number of datas
      ? ? ?for (unsigned int i = 0; i < n; ++i){
      ? ? ? ? ?//find the number
      ? ? ? ? ?if ((i % 3) == 0){
      ? ? ? ? ? ? ?//access the pointer -> find the place -> set the value to 1
      ? ? ? ? ? ? ?//using the bit binary operator << and |
      ? ? ? ? ? ? ?//to be noticed here, the | operator cannot change the value, while |= should be used here
      ? ? ? ? ? ? ?*(data + (i/8)) |= (1 << (i % 8 ));
      ?// ? ? ? ? ?  data[i / 8] |= (1 << (i % 8));
      ? ? ? ?  }
      ? ?  }
      ??
      ?}
      ??
      ?bool checkMap(int value, int len, char* dataMap){
      ? ? ?if(((value/8) > len) || (value < 0))
      ? ? ? ? ?return false;
      ? ? ?int ind = value/8;
      ? ? ?char temp = 1 << (value%8);
      ? ? ?//using bit and operation to check if the value is activated in the map or not
      ? ? ?return ((dataMap[ind] & temp)!=0);
      ? ? ?//0000 0000
      ? ? ?//0010 0000
      ?}
      ??
      ?int main() {
      ? ? ?//assign one enough memory for Bitmap
      ? ? ?//8000000001
      ? ? ?//2147483647 >> signed int
      ? ? ?//4294967295 >> unsigned int
      ? ? ?unsigned int n = 4000000000;
      ??
      ? ? ?// one more promising length < 8, eg: 0, 1, 2, 3, 4, 5, 6
      ? ? ?int len = n / 8 + 1;
      ? ? ?char *data = static_cast<char*> (malloc(len));
      ? ? ?//initialize the data at value zero across the Bitmap
      ? ? ?memset(data, 0, len);
      ? ? ?//load the data set(only once)
      ? ? ?init(data, len);
      ? ? ?
      ? ? ?/*=================testing=================*/
      ? ? ?
      ? ? ?while(true){
      ? ? ? ? ?std::cout << "please enter the value for searching(-1 for quit): ";
      ? ? ? ? ?unsigned int value;
      ? ? ? ? ?std::cin >> value;
      ? ? ? ? ?if(value == -1)
      ? ? ? ? ? ? ?break;
      ? ? ? ? ?if(checkMap(value, len, data)){
      ? ? ? ? ? ? ?std::cout << "found~" << std::endl;
      ? ? ? ?  }else{
      ? ? ? ? ? ? ?std::cout << "no such one value~" << std::endl;
      ? ? ? ?  }
      ? ?  }
      ? ? ?//always there is one free(delete) operation following the malloc(new)
      ? ? ?free(data);
      ??
      ??
      ? ? ?return 0;
      ?}
       
      ?#结果展示
      ?please enter the value for searching(-1 for quit): 1
      ?no such one value~
      ?please enter the value for searching(-1 for quit): 0
      ?found~
      ?please enter the value for searching(-1 for quit): 3
      ?found~
      ?please enter the value for searching(-1 for quit): 6
      ?found~
      ?please enter the value for searching(-1 for quit): 9
      ?found~
      ?please enter the value for searching(-1 for quit): 999999
      ?found~
      ?please enter the value for searching(-1 for quit): 

    • 潜在问题:以上代码无法处理数据越界的问题,上述代码在数据越界时会导致std::cin的失效,这在极限测试中被发现例如输入数字8000000001,这会造成无限循环(int),或者直接退出(unsigned int)。

    #8000000001
    #2147483647 >> signed int
    #4294967295 >> unsigned int
    #signed int value
    please enter the value for searching(-1 for quit): 8000000001
    please enter the value for searching(-1 for quit): no such one value~
    please enter the value for searching(-1 for quit): no such one value~
    please enter the value for searching(-1 for quit): no such one value~
    please enter the value for searching(-1 for quit): no such one value~
    please enter the value for searching(-1 for quit): no such one value~
    please enter the value for searching(-1 for quit): no such one value~
    please enter the value for searching(-1 for quit): no such one value~
    please enter the value for searching(-1 for quit): no such one value~
    please enter the value for searching(-1 for quit): no such one value~
    please enter the value for searching(-1 for quit): no such one value~
    please enter the value for searching(-1 for quit): no such one value~
    ...
    #unsigned int value
    please enter the value for searching(-1 for quit): 8000000001
    
    Process finished with exit code 0
    • 解决方法:在循环末尾对cin进行判断,采用一个来自<limits>库中的模板类numeric_limits

    • #include <limits>
      //...other codes...
      //this is for the failure on cin
      if (std::cin.fail()) {
          // clear the error
          std::cin.clear();  
          // solve the error
          std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); 
          continue; 
      }

    • 问题解决(值得注意的是unsigned int 直接退出循环了,并没有给cin反映的时间。所以unsigned 类型没有得到纠正)结果如下:

    • please enter the value for searching(-1 for quit): 8000000001
      no such one value~
      please enter the value for searching(-1 for quit): 8000000001
      no such one value~
      please enter the value for searching(-1 for quit): 8000000001
      no such one value~
      please enter the value for searching(-1 for quit): 8000001
      found~
      please enter the value for searching(-1 for quit):

  • 项目数据的永久存储 >> 存储到文件或存储到数据库中

    • c++中的 流对象 输出至 文件 or 控制台 or 特殊数据类型如 stringstream

    • 流对象的继承关系如下图所示:

    • ostream 输出(cout), istream 输入(cin

    • ofstream 文件输出, ifstream文件输入

    • ostringstream字符串输出, istringstream字符串输入

    • iostream {fstream, stringstream} 通用输入输出流

    • std::fsteam 是可读可写的,但是在其使用过程中要注意其默认模式是直接覆盖文件, 使用专业的方法会有利于代码的维护。

    • 写出二进制类型时要注意int类型的强行转换

    //        of << age << "\n";
    of.write((char*)(&age), sizeof(age));
    • 读取二进制时除相应的运用成员方法以外,还应注意 \t space 等无法跳过的问题。

    //still there is problem for type translation, also the `\t` cannot be identified
    //using read() member function to read one more to ignore this character.
    char tmp;
    ifs.read((char*)&tmp, sizeof(tmp));
    // ifs >> age;
    ifs.read((char*)&age, sizeof(age));
    std::cout << age << std::endl;
    • 按照制定格式来写出文本文件(使用<sstream>中的 stringstream

    std::stringstream s;
    s << "name: " << name << "\t age: " << age << std::endl;
    of << s.str();

    本周练习用代码结构如下:

    $ tree -L 2
    .
    ├── project01
    │?? ├── Boy.cpp
    │?? ├── Boy.h
    │?? ├── cmake-build-debug
    │?? ├── CMakeLists.txt
    │?? ├── Girl.cpp
    │?? ├── Girl.h
    │?? ├── main.cpp
    │?? ├── Person.cpp
    │?? ├── Person.h
    │?? └── readme.md
    ├── project02
    │?? ├── Character.cpp
    │?? ├── Character.h
    │?? ├── cmake-build-debug
    │?? ├── CMakeLists.txt
    │?? ├── main.cpp
    │?? ├── Toy.cpp
    │?? └── Toy.h
    ├── project03
    │?? ├── Car.cpp
    │?? ├── Car.h
    │?? ├── cmake-build-debug
    │?? ├── CMakeLists.txt
    │?? ├── Engine.cpp
    │?? ├── Engine.h
    │?? ├── main.cpp
    │?? ├── Tire.cpp
    │?? └── Tire.h
    ├── project04
    │?? ├── cmake-build-debug
    │?? ├── CMakeLists.txt
    │?? └── main.cpp-
    ├── project05
    │?? ├── cmake-build-debug
    │?? ├── CMakeLists.txt
    │?? └── main.cpp
    ├── project06
    │?? ├── cmake-build-debug
    │?? ├── CMakeLists.txt
    │?? └── main.cpp
    ├── project07
    │?? ├── Book.cpp
    │?? ├── Book.h
    │?? ├── cmake-build-debug
    │?? ├── CMakeLists.txt
    │?? ├── main.cpp
    │?? ├── SellBook.cpp
    │?? └── SellBook.h
    ├── project08
    │?? ├── cmake-build-debug
    │?? ├── CMakeLists.txt
    │?? ├── main.cpp
    │?? ├── ODU330.cpp
    │?? ├── ODU330.h
    │?? ├── ODU.cpp
    │?? └── ODU.h
    └── project09
        ├── biwriting.cpp
        ├── cmake-build-debug
        ├── CMakeLists.txt
        └── main.cpp
    
    18 directories, 44 files

  • 心得:

    • 虽然有过一些学习cpp的经历,但是经过这几天的学习发现自己还是有很多的不足,很多的点扣的不够细致。 目前的知识点单纯凭借代码练习还是可以记住的。

    • 我的计划是在现阶段一些简单的内容倍速快速过一遍,为之后的数据结构算法以及linux系统编程抢出一部分时间。(因为不太敢轻易跳过rock老师的课,毕竟在代码练习里面可能会穿插一些我不了解的知识点)

    • 以后会尽量单日内完成学习总结,并做好文件管理和问题分类,避免特别长的笔记。


appendix

  • 记录由一个shell脚本自动生成,实现计时, 提醒等功能,最终写入至一个log日志中。(借助chatgpt实现)

#!/bin/bash

total_work_time=14400   # 4 hours in seconds
work_period=3600        # 1 hour in seconds
start_time=$(date +"%Y-%m-%d %H:%M:%S")
start_timestamp=$(date +"%s")

trap 'cleanup_and_exit' INT TERM QUIT

cleanup_and_exit() {
    end_time=$(date +"%Y-%m-%d %H:%M:%S")
    end_timestamp=$(date +"%s")
    total_study_time=$((end_timestamp - start_timestamp))
    formatted_total_study_time=$(date -u -d @${total_study_time} +"%H:%M:%S")
    echo "${end_time}: Total study time: ${formatted_total_study_time}" >> ~/qiniu/study.log
    exit
}

while [ $total_work_time -gt 0 ]
do
    seconds_left=$total_work_time
    hours_init=$((seconds_left/3600))
    mins_init=$((seconds_left%3600/60))
    seconds_init=$((seconds_left%60))

    hours_remain=${hours_init}
    mins_remain=${mins_init}
    seconds_remain=${seconds_init}之
    echo "Working time in total is ${hours_init}:${mins_init}:${seconds_init}"
    echo "========================================"

    # Work for 1 hour
    while [ $seconds_left -gt $(($total_work_time - $work_period)) ]
    do
        echo "Keep working for ${hours_remain}:${mins_remain}:${seconds_remain} more......"
        sleep 1s
        seconds_left=$((seconds_left - 1))
        hours_remain=$((seconds_left/3600))
        mins_remain=$((seconds_left%3600/60))
        seconds_remain=$((seconds_left%60))
        clear
        echo "Working time in total is ${hours_init}:${mins_init}:${seconds_init}"
        echo "========================================"
    done

    mplayer -volume 20 ~/Music/rest.mp3  # Play the 'rest' music

    # Prompt user to continue or quit
    while true
    do
        read -p "Type 'continue' to start the next work period or 'q' to quit: " user_input

        if [ "$user_input" == "continue" ]
        then
            break
        elif [ "$user_input" == "q" ]
        then
            cleanup_and_exit
        else
            echo "Invalid input. Please type 'continue' to proceed or 'q' to quit."
        fi
    done

    total_work_time=$((total_work_time - work_period))
done
mplayer -volume 20 ~/Music/done.mp3  # Play the 'done' music upon exit
cleanup_and_exit

文章来源:https://blog.csdn.net/m0_71081799/article/details/132800183
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。