C++ 期末作业报告

项目介绍 这次作死来试试手写编辑器,作为一次 Project Based Learning ,我选择了这个教程 这个教程教你在单文件中用 1000 行C代码来实现一个迷你的编辑器,带有代码高亮,无第三方依赖 这个教程一共有7步,每一步教你实现 Setup 环境设置 Entering raw mode 进入终端原始模式 Raw input and output 原始的输入和输出 A text viewer 文本浏览 A text editor 文本编辑 Search 文字搜索 Syntax highlighting 语法高亮 这里由于能力有限,只实现到 文本浏览这一块,不过这个项目挺有意思,我打算有时间接着实现 设计思路 在 Linux 中,可以使用 ANSI 转义码(ANSI escape codes)设置终端的字符显示颜色、移动光标位置、清除字符显示等。 ANSI 转义码是由终端自身支持,独立于编程语言之外,可以在 C 语言、Java、Python、或者 Shell 中使用。 需要补充的是,电脑每秒都在按一定的频率刷新屏幕,在程序里的具体体现为,渲染好当前页面后,刷新,清楚页面,然后接着 把数据渲染上去 基于此,程序功能大致分为这么几块, data 全局数据相关 terminal 终端操作的 init 程序初始化操作 input 处理输入字符的 output 处理输出的,比如刷新屏幕 由于此前用C代码超了一遍源程序,对代码有了一些理解,这里打算用 C++ 来实现一版 另外发现在这个程序中使用类的继承是不合适的,这里用到 C++ 只是用来代替 C ,做一些抽象,少些点代码而已 作为编辑器的程序 这时候程序只是作为一个编辑器,需要响应的就只是光标的移动, 这时程序一共分为三大步 初始化环境 设置终端为原始模式 获取终端窗口大小 循环处理按键 刷新屏幕 读取按键 是 组合键 是 方向键 或 PageUp 或 Home 等按键 是 普通的字符 渲染屏幕 退出 还原终端为规范模式 注意 终端有三种工作模式:规范模式、非规范模式、原始模式 在termios结构的c_lflag中设置ICANNON标志来定义终端以何种模式工作,默认为规范模式。 规范模式 所有输入基于行进行处理。在用户输入一个行结束符(回车符、EOF等)之前, 系统调用 read 函数读不到用户输入的任何字符 其次,除了EOF之外的行结束符与普通字符一样会被 read 函数读取到缓冲区中。一次调用 read 只能读取一行数据。 非规范模式 所有输入时即时有效的,不需要用户另外输入行结束符。 原始模式 是一种特殊的非规范模式,所有的输入数据以字节为单位被处理。即有一个字节输入时,触发输入有效。 这里由于要处理方向键,组合键这类按键,所以选择 原始模式 作为文本浏览的程序 文本浏览不仅要在初始化环境时进入原始模式,还要读入文件 光标的移动由于文件的引入,需要实现 垂直滚动 和 水平滚动 ,需要全局状态来记录光标的位置 cursorx 与 cursory , 还要记录所在的行数 colsOffset 和列数 rowsOffset ,并与终端窗口大小比较,判断是否需要滚动 除此之外还要处理文本中的制表符 ‘\t’ ,需要为制表符指定渲染的长度,设置光标移动遇到制表符时,直接调到下一个字符, 这里定义一个新的 renderx 来替代 cursorx 的部分功能,并提供 cursorx 到 renderx 的转换方法 cxtorx 代码实现 主函数 int main(int argc, char * argv[]) { Editor editor; if(argc >= 2) { editor.

MLJ中 线性模型 在回归预测中的简单使用

开始之前 我想向大家介绍一下一些线性模型的用法,以及他们对数据的拟合程度 在我开始学习 MLJ 时,我对他们的拟合能力有所怀疑,经常遇到欠拟合的情况,经过一次简单的测试后,才慢慢了解如何使用模型,处理特征 这里将这个测试介绍给各位 数据准备 我们模拟对函数 f(x) = x^2 + 2x 的拟合,在理想的预测结果 standardy 上加上一点噪音,形成训练用测试结果 coly 接下来依次定义 f(x) standardy coly f(x) = x^2 + 2x colx = DataFrame(x1=-10:10) coly = f.(colx.x1) + rand(-2:2, length(colx.x1)) standardy = f.(colx.x1) 再绘制下图像 plot(colx.x1, standardy, label="standarty", color=:blue) plot!(colx.x1, coly, label="coly", color=:red) 模型介绍 拟合数据我们使用 Ridge 回归,他在损失函数上添加了 L2 正则化 \begin{array}{cl} {\min \limits_{w, b}} & {\dfrac{1}{n}\sum_{i = 1}^n (w^{\top} x_i + b - y_i)^2} \\ {\text{s.t.}} &{\|w\|_2^2 \le t} \end{array}

Titanic 生存预测,使用Logistic分类

项目介绍 最近终于去学习 Julia 了,重温了下没做完的 Titanic 项目,打算做完 那就先导入必要的库吧 using MLJ, DataFrames, StableRNGs, CSV, Plots plotly() 还要从 Kaggle 上下载好数据集 train.csv 与 test.csv , 并用 CSV 模块加载 origin_data = CSV.read("data/train.csv", DataFrame) 到提交的时候,数据表中的字段 PassengerId(Integer) 与 Survived(Integer) 数据探索 字段含义 我从网上查到这些字段的含义,有些字段的类型虽然是 Float ,但也是 1.0, 2.0之类的,比如 Age 字段名称 字段含义 字段类型 PassengerId 乘客ID Int Survived 是否存活 Int Pclass 乘客等级(1/2/3等舱位) Int Name 乘客姓名 String Sex 性别 String Age 年龄 Float SibSp 堂兄弟/妹个数 Float Parch 父母与小孩个数 Float Ticket 船票信息 String Fare 票价 Float Cabin 客舱 String Embarked 登船港口 String 字段科学类型 这个数据集使用分类预测,先要统一好各个字段的科学类型,不然一些 model 对字段不起作用 这里需要每个输入的数据类型是 Continuous, 而输出类型为 Multiclass 使用 schema 查看情况 schema(origin_data) 描述数据 看看这个数据有多少缺斤少两的 describe(origin_data) 数据处理 探索完数据后,接下来可以 填充缺失的数据 扔掉不用的数据 生成新的字段,或者优化数据 对 train.

在 Flutter 中使用数据库

在 Flutter 中使用数据库 介绍 以 sqlite 为例,flutter 在使用数据库时需要引入 sqflite 依赖 dependencies: flutter: sdk: flutter sqflite: 导入 package:sqflite/sqflite.dart 与 package:sqflite/sql.dart 后,可以在 openDatabase 中的 onCreate 参数中设置初始化 openDatabase( 'file:///home/steiner/workspace/playground/todolist/todolist.db', onCreate: (database, version) async { await database.execute( 'create table if not exists TaskList(' 'id integer primary key autoincrement,' 'name text not null' ');' ); }, version: 1 ); 其余数据库操作参考 中文文档 组件中使用数据库 由于在 Dart 中数据库的操作是异步的,返回值是 Future 类型,对 Future 使用 await 需要在异步函数中进行, 各个组件的 build 方法又是同步的,无法使用 Future 不过 flutter 提供了 FutureBuilder 组件,为其提供 futurue 选项来构造组件 FutureBuilder({ this.

Flutter 中 provider 的使用

Provider 的引入 Provider 解决的是组件之间传递数据的问题 在 Vue 中,父组件通过 props 传递数据给子组件,子组件通过 $emit 通知父组件,然后 Vue 重新渲染 DOM 在 Vue 中,也可以使用 provider 和 inject 传递数据,不过不能很好的处理响应性 与 Vue 相同的是,Flutter 的 Provider 的引入解决了数据传递中嵌套组件过多的问题,若在当前节点没有找到 Provider 组件, 则会通过上下文寻找 Provider ,直至找到 不过想使用 Provider,父组件得暴露出一个对象用以交互, 而这个对象得继承自 ChangeNotifier 以 ChangeNotifierProvider为例 ChangeNotifierProvider( builder: (context) => ExposedObject, child: ... ) 子组件想使用其中的值,得通过 Consumer 组件或者 context.read<ExposedType> Consumer( create: (context, ExposedType expose, child) { // call expose } ) var expose = context.read<ExposedType>(); 注意 除了 context.read 外,还有 context.

Flutter 中的Router

用你的应用来演示 路由用法 在这个演示里定义两个界面,HomePage 与 NextPage ,并从 HomePage 传递参数到 NextPage 中 接下来演示匿名路由和命名路由的情况 这是 HomePage 点击文字按钮后,跳转到 NextPage 1. 匿名路由跳转 首先是 HomePage class HomePage extends StatelessWidget { Widget buildBody(BuildContext context) { var fnpress = (String message) { return () { Navigator.push(context, MaterialPageRoute(builder: (builder) => NextPage(message: message))); }; }; return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ TextButton(onPressed: fnpress('Hello World'), child: Text('goto the next page with status 1')), TextButton(onPressed: fnpress('Fuck You'), child: Text('goto the next page with status 2')) ], ), ); } @override Widget build(BuildContext context) { // TODO: implement build return Scaffold( appBar: AppBar(title: Text('Home Page'),), body: buildBody(context), ); } } 在跳转时通过构造函数来传递参数,其中 NextPage 为 class NextPage extends StatelessWidget { String message; NextPage({required this.