# CppPrimer5_topic **Repository Path**: btg233/CppPrimer5_topic ## Basic Information - **Project Name**: CppPrimer5_topic - **Description**: c++primer5的一些题目 - **Primary Language**: C++ - **License**: GPL-3.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2023-04-17 - **Last Updated**: 2023-04-27 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # [infix_expression.cpp](https://gitee.com/btg233/cpp_topic/blob/master/infix_expression.cpp) **使用stack处理括号化的表达式。当你看到一个左括号,将其记录下来。当你在一个左括号之后看到一个右括号,从stack中pop对象,直至遇到左括号,将左括号也一起弹出栈。然后将一个值(括号内的运算结果)push到栈中,表示一个括号化的(子)表达式已经处理完毕,被其运算结果所替代** cpp primer5 9.52 _写出了中缀表达式的计算过程_ _当前一个字符为数字或者右括号)时,为减号,其余为负号_ # 文本查询程序 ## [自己的第一版](https://gitee.com/btg233/CppPrimer5_topic/blob/master/mytestquery.cpp)/[第一版参考答案](https://gitee.com/btg233/CppPrimer5_topic/blob/master/testquery1.cpp) **文本查询程序允许用户在一个给定的文件中查询单词** **结果:单词出现的次数以及所在行的列表,按行号升序输出,重复行只打印一次** ## 分析过程 1. 读取文件:因为输出行号,所以按行读取。再将行拆分成单词 2. 输出:次数、单词关联的行号、升序排列且无重复、打印特定行号文本 ### 根据分析可得 1. 使用`vector`保存文件拷贝 2. `istringstream`将每行拆分为单词 3. 使用`set`容器保证每行出现一次且有序 4. 使用`map`将单词与`set`关联 ### 为了方便使用,将这几种类型抽象 建立`TextQuery`和`QueryResult`两种类。 `TextQuery`读取文件,进行查询。内有`vector`和`map` `QueryResult`打印需要的信息(出现次数、行号、行文本) ### 类之间共享数据 如果`TextQuery`在`QueryResult`之前销毁,会出错。 使用智能指针管理内存。这里选择`shared_ptr`,多对象共享且自动管理内存 ## 总结 ### 程序设计时,先列出需求,再分析数据结构 ### 编写类时,先使用类。方便查看需求 # 拷贝控制。用于邮件处理的两个类 ## [message1.cpp](https://gitee.com/btg233/CppPrimer5_topic/blob/master/message1.cpp) **Message 消息,Folder 目录** **每个 Message 对象可以出现在多个Folder中,且只能有一个副本。这样更新了内容,使用它所在的任何Folder都能看到更新** **类似于分组:男人、女人、25岁以上、25岁以下。这条消息可以是男人25岁以下这两个分组的,每个分组也有多个消息** ### save和remove 向一个给定Folder添加或删去一个Message ### 拷贝 副本与原对象将是不同的对象,但是都出现在相同的Folder中。因此拷贝包括消息内容和指针的拷贝,且Folder要更新 ### 销毁 对所有的Folder删去指向这条消息的指针 ### 赋值 左侧删去,右侧添加 ## 总结 ### 公共的工作应该在private中定义一个工具函数 拷贝赋值运算符通常执行拷贝构造函数和析构函数中也要做的工作。则可以定义两个工具函数 # 实现 vector ## [strvec.cpp](https://gitee.com/btg233/CppPrimer5_topic/blob/master/strvec.cpp) ## 类的设计 1. 使用与`vector`类相似的内存策略,使用`allocator`获取原始内存。使用`allocator`的`construct`成员在原始内存中创建对象`。使用`destroy`销毁对象 2. 三个指针。`elements`指向分配的内存中的首元素、`first_free`指向最后一个实际元素之后的位置、`cap`指向分配内存的尾后位置 3. 工具函数:`alloc_n_cpoy`分配内存,并拷贝元素、`free`销毁构造的元素并释放内存、`chk_n_alloc`调用`reallocate`分配内存、`reallocate`分配内存 ## 关于`allocator` ### `construct` `allocator`分配的是未构造的内存,必须使用`construct`在内存中构造对象。 `construct`的第一个参数必须是指针,指向`allocate`所分配的未构造的内存空间,剩余参数确定用那个构造函数来构造对象 ### `destroy`和`deallocate` `destroy`方法用于销毁一个或多个对象。当使用`allocator`分配内存来存储对象时,这些对象需要在释放内存之前进行销毁。`destroy`方法将调用对象的析构函数来销毁对象。 `deallocate`方法用于释放使用`allocator`分配的内存,并将其返回给系统。在释放内存之前,需要确保所有对象都已经被销毁,因为释放内存会导致指向该内存的指针变得无效。 ### `reallocate`成员函数 1. 为一个新的、更大的数组分配内存 2. 在内存空间中的前一部分构造对象,保存现有元素 3. 销毁原内存空间中的元素,释放内存 因为这里的`string`用户在分配内存前后是唯一且不变的。因此拷贝是多余的,避免这些开销,使用移动构造函数