项目介绍这是一个超轻量级的C/C++项目,使用C/C++模拟实现一个简单的Lisp(一种函数式程序设计语言),会使用一些外部的库进行初始化工作,例如mpc、editline等
我们会使用类Python的REPL模式,使用Lisp程序,并不直接提供系统的编译运行环境,整个代码量大概在1000行左右
主要难点
语法规则与解析用户输入
递归与错误处理
S表达式,Q表达式
函数,标准库
我将会在这里逐步实现这个小项目并记录实现过程中出现的问题以及解决方案
会先使用C语言实现,再考虑使用C++补充和优化
读取输入的实现基本思路首先这是一个类Python的命令行输入的模式,基本思路就是使用一个while(1)循环,然后不断读入,再进行解析处理
如下
12345while(1){ char* input = readline("MyLisp> "); printf("The sentence is %s\n", input);}
这里的readline是为了适配linux和mac,我们重新写的一个有相似...
map和set关联式容器我们在之前讲过STL的一些基础容器,例如vector,list,deque,forward_list等
这些其实统一都称为序列式容器,因为其底层都是线性的序列数据结构,而且存储的内容是元素本身
关联式容器也是存储数据的容器,不同的是,里面存储的是<key,value>的键值对,类似于我们之前讲的二叉搜索树的KV模型
键值对键值对是我们用来表示一一对应关系的结构,包含key和value两个成员变量
key表示关键字,类似于字典中的单词,value表示具体的值,也就是字典中对应的具体释义
在C++中使用pair表示一对值,但并没有具体的对应关系,只是将这一对值进行了封装,可以读取和写入,当然pair也有一些非常有意思的内容,当我们观察其源码时可以看出
这里给出SGI-STL对pair的定义
12345678910111213141516171819template<class T1, class T2>struct pair{ typedef T1 first_type; typedef T2 second_type; ...
二叉搜索树二叉搜索树(BST,Binary Search Tree)又称为二叉排序树,空树也算
二叉搜索树有如下性质
若左子树不为空,则左子树上所有节点值小于根节点
若右子树不为空,则右子树上所有节点值大于根节点
左子树和右子树也都是二叉搜索树
例如
当然如果左大右小也可以
二叉搜索树的一个性质是中序遍历有序
查找从根节点开始查找比较,比根大向右查找,比根小向左查找
最多查找高度次,如果没找到就代表值不存在
插入如果为空,新增节点
如果不为空,按照性质插入节点
删除首先需要确定值是否在二叉树中
要删除就右四种情况
无子节点——直接删除即可,可以合并到只有一个节点的情况
只有左节点——删除,令该节点的父节点指向左节点
只有右节点——删除,令该节点的父节点指向右节点
有两个子节点——在左子树寻找关键之最大的节点或右子树的最小节点,以最小节点为例,找到最小节点后与删除节点替换,再处理替换后的节点删除问题
实现1234567891011121314151617181920212223242526272829303132333435363738394041424344454647...
多态概念多态是面向对象三大特性中相对复杂的一个,他从直观上理解就是,不同的人(对象)做同一件事情(调用函数),会产生不同的结果(状态)
多态又分为静态多态和动态多态,静态多态其实就是函数重载,在本篇文章中主要介绍动态多态,在讲到多态的原理时,我们会细讲其中的区别
定义及实现多态是在不同的为继承关系的类对象,调用同一个函数(同名函数),产生的不同的行为
例如,Student是Person的子类,同样的买票动作下,Person是全价,而Student是全价
构成条件构成多态必须有两个条件
必须通过父类的指针或引用调用虚函数
被调用的函数必须是虚函数,子类必须重写父类的虚函数
例如
1234567891011121314151617181920212223242526272829303132333435#include<iostream>using namespace std;class Person{public: virtual void Buyticket() { cout << "Person:...
继承继承的概念继承是C++面向对象的三大特性之一,他设计的初衷是为了提高代码的复用性
例如,对于重复的功能代码,我们可以提炼抽象成函数,减少代码量,提高复用性
而对于重复或者相似的类,我们也可以提炼出他们共同的部分,称之为基类,那提炼之前的类,我们可以把它想象成是基类派生出的类,称之为派生类,还有一种更形象化的叫法,父类与子类
那我们在这里就能明白了,继承是类的设计层面的复用
例如,我们想要从人派生出学生和教师两个子类,这里要重点理解两个方向,一是由下而上的集成学生和教师共同点产生的基类,二是由上而下的从人继承出学生和教师产生的子类
123456789101112class Person{public: void Print() { cout << "name:" << _name << endl; cout << "age:" << _age << endl; }protected: s...
模板进阶非类型模板参数模板参数分为类型形参和非类型形参
类型形参是出现在模板参数中,跟在class或者typename之后的参数类型名称
非类型形参是使用常量作为模板的一个参数,在类或者函数中可以作为常量使用
例如
12345678910111213141516171819202122232425262728namespace xu{ template<class T, size_t N = 10> class array { public: T& operator[](size_t index) { return _array[index]; } const T& operator[](size_t index) const { return _array[index]; } size_t size() const ...
CSS进阶复合选择器复和选择器是由两个或多个基础选择器,通过不同的方式组合而成,可以更准确、更高效的选择目标元素(标签)。
后代选择器后代选择器用于选中某元素的后代元素。
选择器写法:父选择器 子选择器 { CSS 属性},父子选择器之间用空格隔开。
12345678910<style> div span { color: red; }</style><span> span 标签</span><div> <span>这是 div 的儿子 span</span ></div>
子代选择器子代选择器用于选中某元素的子代元素(最近的子级)。
选择器写法:父选择器 > 子选择器 { CSS 属性},父子选择器之间用 > 隔开。
123456789101112<style> div > span { color: red; }</style><div> <span&g...
CSS基础层叠样式表 (Cascading Style Sheets,缩写为 CSS)是一种 样式表 语言,用来描述 HTML 文档的呈现(美化内容)。
一般在title 标签下方添加 style 双标签,style 标签里面书写 CSS 代码。
12345678910<title>CSS 初体验</title><style> /* 选择器 { } */ p { /* CSS 属性 */ color: red; }</style><p>CSS</p>
属性名和属性值成对出现 → 键值对。
CSS引入方式
内部样式表:学习使用
CSS 代码写在 style 标签里面
外部样式表:开发使用
CSS 代码写在单独的 CSS 文件中(**.css**)
在 HTML 使用 link 标签引入
1<link rel="stylesheet" href="./my.css">
行内样式:配合...